Add DString building.

This commit is contained in:
Jesse Brault 2025-05-17 08:36:55 -05:00
parent bae2048aef
commit 78e7271950
6 changed files with 146 additions and 7 deletions

View File

@ -10,4 +10,8 @@ fn main(x: String) {
let z = 'z';
let test = 'oops.';
};
}
pub mod test {
}

View File

@ -1276,7 +1276,31 @@ fn build_single_quote_string(file_id: usize, pair: Pair<Rule>) -> Literal {
}
fn build_double_quote_string(file_id: usize, pair: Pair<Rule>) -> Literal {
todo!()
let mut parts: Vec<DStringPart> = 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!(),
}
}
if parts.len() == 1 && parts[0].is_string() {
Literal::String(parts.pop().unwrap().unwrap_string())
} else {
Literal::DString(DString(parts))
}
}
fn build_backtick_string(file_id: usize, pair: Pair<Rule>) -> Literal {
@ -1290,12 +1314,13 @@ mod tests {
use crate::parser::DeimosParser;
use indoc::indoc;
fn assert_builds(src: &str) -> CompilationUnit {
fn assert_builds(src: &str) {
let parse_result = DeimosParser::parse(Rule::CompilationUnit, src);
if let Err(e) = parse_result {
panic!("Parsing failed.\n{}", e)
} else {
build_ast(0, parse_result.unwrap().next().unwrap())
let ast = build_ast(0, parse_result.unwrap().next().unwrap());
dbg!(ast);
}
}
@ -1331,4 +1356,24 @@ mod tests {
fn double_literal() {
assert_builds("fn main() { 1.0 }");
}
#[test]
fn d_string_no_expressions() {
assert_builds("fn main() { \"Hello, World!\" }");
}
#[test]
fn d_string_one_expression() {
assert_builds("fn main() { \"${foo}\" }");
}
#[test]
fn d_string_literal_and_expression() {
assert_builds("fn main() { \"Hello, ${foo}!\" }");
}
#[test]
fn d_string_literal_expression_literal() {
assert_builds("fn main() { \"Hello, ${foo}! It is a nice day.\" }");
}
}

View File

@ -599,5 +599,46 @@ pub enum Literal {
Double(f64),
USize(usize),
String(String),
DString(DString),
Boolean(bool),
}
#[derive(Debug)]
pub struct DString(pub Vec<DStringPart>);
#[derive(Debug)]
pub enum DStringPart {
String(String),
Expression(Box<Expression>),
}
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,
_ => false,
}
}
}

View File

@ -877,7 +877,30 @@ impl PrettyPrint for Literal {
Double(d) => writer.writeln_indented(&format!("Double({})", d)),
USize(u) => writer.writeln_indented(&format!("USize({})", u)),
String(s) => writer.writeln_indented(&format!("String({})", s)),
DString(d_string) => d_string.pretty_print(writer),
Boolean(b) => writer.writeln_indented(&format!("Boolean({})", b)),
}
}
}
impl PrettyPrint for DString {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("DString")?;
writer.increase_indent();
for part in &self.0 {
part.pretty_print(writer)?;
}
Ok(())
}
}
impl PrettyPrint for DStringPart {
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.writeln_indented("DStringPart")?;
writer.increase_indent();
match self {
DStringPart::String(s) => writer.writeln_indented(&format!("String({})", s)),
DStringPart::Expression(e) => e.pretty_print(writer),
}
}
}

View File

@ -1042,7 +1042,32 @@ impl Unparse for Literal {
Double(d) => writer.write(&format!("{}", d)),
USize(u) => writer.write(&format!("{}", u)),
String(s) => writer.write(&format!("\"{}\"", s)),
DString(d_string) => d_string.unparse(writer),
Boolean(b) => writer.write(&format!("{}", b)),
}
}
}
impl Unparse for DString {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
writer.write("\"")?;
for part in &self.0 {
part.unparse(writer)?;
}
writer.write("\"")?;
Ok(())
}
}
impl Unparse for DStringPart {
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
match self {
DStringPart::String(s) => writer.write(s),
DStringPart::Expression(e) => {
writer.write("${")?;
e.unparse(writer)?;
writer.write("}")
}
}
}
}

View File

@ -795,14 +795,15 @@ StringChar = {
DStringInner = @{ DStringChar+ }
DStringChar = {
!( "\"" | "\\" ) ~ ANY
!( "\"" | "\\" | "${" ) ~ ANY
| "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" )
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
}
DStringExpression = {
"$"
~ BlockStatement
"${"
~ Expression
~ "}"
}
BacktickString = {
@ -815,7 +816,7 @@ BacktickString = {
BacktickInner = @{ BacktickStringChar+ }
BacktickStringChar = {
!( "\\`" | "\\" ) ~ ANY
!( "\\`" | "\\" | "${" ) ~ ANY
| "\\" ~ ( "`" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" )
| "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
}