From a9457c1ab994bbf7141c5ae7aa3d3807c7aa4faa Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Thu, 15 May 2025 09:40:39 -0500 Subject: [PATCH] Successful work to compile, parse, and unparse basic Deimos. --- sketching/may_2025/hello_world.dm | 5 +++++ src/ast/build.rs | 5 +++-- src/ast/unparse.rs | 9 ++++++--- src/bin/dmc/ast_dump.rs | 21 +++++++++++++++++---- src/bin/dmc/main.rs | 8 ++++---- src/parser/deimos.pest | 14 +++++++------- 6 files changed, 42 insertions(+), 20 deletions(-) create mode 100644 sketching/may_2025/hello_world.dm diff --git a/sketching/may_2025/hello_world.dm b/sketching/may_2025/hello_world.dm new file mode 100644 index 0000000..c597a7e --- /dev/null +++ b/sketching/may_2025/hello_world.dm @@ -0,0 +1,5 @@ +fn main() { + println('Hello, World!'); + let x = 'I greet you!'; + println(x); +} \ No newline at end of file diff --git a/src/ast/build.rs b/src/ast/build.rs index 986f717..d17331b 100644 --- a/src/ast/build.rs +++ b/src/ast/build.rs @@ -259,6 +259,7 @@ fn build_compilation_unit(compilation_unit_pair: Pair) -> CompilationUnit Rule::ModuleLevelDeclaration => { declarations.push(build_module_level_declaration(inner_pair)); } + Rule::EOI => {} _ => unreachable!(), } } @@ -842,7 +843,7 @@ macro_rules! build_binary_expression { right: Box::new(right), }) } else { - $left_fn(inner.next().unwrap()) + expect_and_use(inner.next().unwrap(), $left_rule, $left_fn) } }}; } @@ -1113,7 +1114,7 @@ fn build_boolean_literal(pair: Pair) -> Literal { fn build_single_quote_string(pair: Pair) -> Literal { let inner_pair = pair.into_inner().next().unwrap(); - Literal::String(inner_pair.to_string()) + Literal::String(inner_pair.as_span().as_str().to_string()) } fn build_double_quote_string(pair: Pair) -> Literal { diff --git a/src/ast/unparse.rs b/src/ast/unparse.rs index b15532e..c45b7b1 100644 --- a/src/ast/unparse.rs +++ b/src/ast/unparse.rs @@ -505,8 +505,10 @@ impl Unparse for FunctionDefinition { write!(buf, " ")?; } write!(buf, "fn ")?; - self.generics.unparse(buf)?; - write!(buf, " ")?; + if !self.generics.is_empty() { + self.generics.unparse(buf)?; + write!(buf, " ")?; + } self.identifier.unparse(buf)?; self.parameters.unparse(buf)?; write!(buf, " ")?; @@ -694,12 +696,13 @@ impl Unparse for FieldDeclaration { impl Unparse for BlockStatement { fn unparse(&self, buf: &mut dyn std::fmt::Write) -> std::fmt::Result { - write!(buf, "{{")?; + write!(buf, "{{\n")?; for statement in &self.statements { statement.unparse(buf)?; } if let Some(expression) = &self.expression { expression.unparse(buf)?; + write!(buf, "\n")?; } write!(buf, "}}")?; unparse_ok!() diff --git a/src/bin/dmc/ast_dump.rs b/src/bin/dmc/ast_dump.rs index c4b1405..8c2dcb6 100644 --- a/src/bin/dmc/ast_dump.rs +++ b/src/bin/dmc/ast_dump.rs @@ -1,9 +1,22 @@ use std::path::PathBuf; - +use pest::Parser; use deimos::ast::build::build_ast; +use deimos::ast::unparse::Unparse; +use deimos::parser::{DeimosParser, Rule}; -pub fn dump_ast(path: &PathBuf) { +pub fn unparse(path: &PathBuf) { let src = std::fs::read_to_string(path).expect(&format!("Could not read {:?}", path)); - let ast = build_ast(&src); - println!("{:?}", ast); + let parse_result = DeimosParser::parse(Rule::CompilationUnit, &src); + match parse_result { + Ok(mut pairs) => { + let compilation_unit_pair = pairs.next().unwrap(); + let compilation_unit = build_ast(compilation_unit_pair); + let mut out = String::new(); + compilation_unit.unparse(&mut out).expect("Failed to write to string."); + println!("{}", out); + }, + Err(e) => { + eprintln!("{}", e); + } + } } diff --git a/src/bin/dmc/main.rs b/src/bin/dmc/main.rs index 9ad4390..88eb636 100644 --- a/src/bin/dmc/main.rs +++ b/src/bin/dmc/main.rs @@ -2,7 +2,7 @@ mod ast_dump; use std::path::PathBuf; -use ast_dump::dump_ast; +use ast_dump::unparse; use clap::{Parser, Subcommand}; #[derive(Debug, Parser)] @@ -16,15 +16,15 @@ struct Cli { #[derive(Debug, Subcommand)] enum Commands { #[command(arg_required_else_help = true)] - AstDump { paths: Vec }, + Unparse { paths: Vec }, } fn main() { let args = Cli::parse(); match args.command { - Commands::AstDump { paths } => { + Commands::Unparse { paths } => { for path in paths { - dump_ast(&path); + unparse(&path); } } } diff --git a/src/parser/deimos.pest b/src/parser/deimos.pest index be0282f..4c1ca9d 100644 --- a/src/parser/deimos.pest +++ b/src/parser/deimos.pest @@ -584,7 +584,7 @@ AndExpression = { } ComparisonExpression = { - AdditiveExpression + ShiftExpression ~ ( ( Greater | Less | GreaterEqual | LessEqual | EqualTo | NotEqualTo ) ~ Expression @@ -762,7 +762,7 @@ StringLiteral = { | BacktickString } -SingleQuoteString = ${ "'" ~ StringInner ~ "'" } +SingleQuoteString = { "'" ~ StringInner? ~ "'" } DoubleQuoteString = { "\"" @@ -771,10 +771,10 @@ DoubleQuoteString = { ~ "\"" } -StringInner = @{ StringChar* } +StringInner = @{ StringChar+ } StringChar = { - !( "\"" | "\\" ) ~ ANY + !( "\'" | "\\" ) ~ ANY | "\\" ~ ( "'" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" ) | "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} ) } @@ -794,15 +794,15 @@ DStringExpression = { BacktickString = { "`" - ~ ( DStringInner? ~ DStringExpression )* - ~ DStringInner? + ~ ( BacktickInner? ~ DStringExpression )* + ~ BacktickInner? ~ "`" } BacktickInner = @{ BacktickStringChar+ } BacktickStringChar = { - !( "\"" | "\\" ) ~ ANY + !( "\\`" | "\\" ) ~ ANY | "\\" ~ ( "`" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" ) | "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} ) }