diff --git a/src/ast/build.rs b/src/ast/build.rs index 2e947ae..35aff88 100644 --- a/src/ast/build.rs +++ b/src/ast/build.rs @@ -1277,25 +1277,12 @@ fn build_single_quote_string(file_id: usize, pair: Pair) -> Literal { fn build_double_quote_string(file_id: usize, pair: Pair) -> Literal { let mut parts: Vec = vec![]; - let inner = pair.into_inner(); - for inner_pair in inner { - match inner_pair.as_rule() { - Rule::DStringInner => { - parts.push(DStringPart::from_string(inner_pair.as_span().as_str())); - } - Rule::DStringExpression => { - let expression_pair = inner_pair.into_inner().next().unwrap(); - parts.push(DStringPart::from_expression(expect_and_use( - file_id, - expression_pair, - Rule::Expression, - build_expression, - ))); - } - _ => unreachable!(), - } - } - + handle_d_backtick_strings_inner( + Rule::DStringInner, + file_id, + pair, + &mut parts, + ); if parts.len() == 1 && parts[0].is_string() { Literal::String(parts.pop().unwrap().unwrap_string()) } else { @@ -1304,7 +1291,42 @@ fn build_double_quote_string(file_id: usize, pair: Pair) -> Literal { } fn build_backtick_string(file_id: usize, pair: Pair) -> Literal { - todo!() + let mut parts: Vec = vec![]; + handle_d_backtick_strings_inner( + Rule::BacktickInner, + file_id, + pair, + &mut parts, + ); + if parts.len() == 1 && parts[0].is_string() { + Literal::String(parts.pop().unwrap().unwrap_string()) + } else { + Literal::BacktickString(DString(parts)) + } +} + +fn handle_d_backtick_strings_inner( + inner_rule: Rule, + file_id: usize, + pair: Pair, + parts: &mut Vec, +) { + for inner_pair in pair.into_inner() { + let as_rule = inner_pair.as_rule(); + if as_rule == inner_rule { + parts.push(DStringPart::from_string(inner_pair.as_span().as_str())); + } else if as_rule == Rule::DStringExpression { + let expression_pair = inner_pair.into_inner().next().unwrap(); + parts.push(DStringPart::from_expression(expect_and_use( + file_id, + expression_pair, + Rule::Expression, + build_expression, + ))); + } else { + unreachable!() + } + } } #[cfg(test)] @@ -1369,7 +1391,7 @@ mod tests { #[test] fn d_string_literal_and_expression() { - assert_builds("fn main() { \"Hello, ${foo}!\" }"); + assert_builds("fn main() { \"Hello, ${foo}\" }"); } #[test] diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 944e1f8..100e7c2 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -600,6 +600,7 @@ pub enum Literal { USize(usize), String(String), DString(DString), + BacktickString(DString), Boolean(bool), } @@ -616,25 +617,25 @@ impl DStringPart { pub fn from_string(s: &str) -> DStringPart { DStringPart::String(String::from(s)) } - + pub fn from_expression(e: Expression) -> DStringPart { DStringPart::Expression(Box::new(e)) } - + pub fn is_string(&self) -> bool { match self { DStringPart::String(_) => true, _ => false, } } - + pub fn unwrap_string(self) -> String { match self { DStringPart::String(s) => s, _ => panic!(), } } - + pub fn is_expression(&self) -> bool { match self { DStringPart::Expression(_) => true, diff --git a/src/ast/pretty_print.rs b/src/ast/pretty_print.rs index 8a721ed..fbd565e 100644 --- a/src/ast/pretty_print.rs +++ b/src/ast/pretty_print.rs @@ -878,6 +878,7 @@ impl PrettyPrint for Literal { USize(u) => writer.writeln_indented(&format!("USize({})", u)), String(s) => writer.writeln_indented(&format!("String({})", s)), DString(d_string) => d_string.pretty_print(writer), + BacktickString(d_string) => d_string.pretty_print(writer), Boolean(b) => writer.writeln_indented(&format!("Boolean({})", b)), } } diff --git a/src/ast/unparse.rs b/src/ast/unparse.rs index a62cd35..d30cd2e 100644 --- a/src/ast/unparse.rs +++ b/src/ast/unparse.rs @@ -1043,6 +1043,7 @@ impl Unparse for Literal { USize(u) => writer.write(&format!("{}", u)), String(s) => writer.write(&format!("\"{}\"", s)), DString(d_string) => d_string.unparse(writer), + BacktickString(d_string) => d_string.unparse(writer), Boolean(b) => writer.write(&format!("{}", b)), } }