feat: Add AST emitter and comment support
Introduces a new AST emitter module responsible for serializing AST nodes back into Myc source code. This emitter preserves leading comments and whitespace, enabling a round-trip guarantee for the parser and emitter. The documentation in `docs/BNF.md` has been updated to reflect the new syntax rules for comments, including single-line comments (`;`) and documentation comments (`;;`). The rules clarify that comments must be whole lines and that inline comments are disallowed. The lexer and AST node structures have been updated to accommodate `CommentLine` variants, allowing for different types of comments (regular, documentation, and blank lines) to be stored and processed. A new test suite `tests/comment_roundtrip.rs` has been added to verify the round-trip property of the parser and emitter across all example `.myc` files. This test ensures that parsing source code, emitting it, and then parsing the emitted code again results in the same output string. The `ast.rs` binary now includes a `--emit` flag that uses the new emitter to output the parsed source code, facilitating debugging and testing of the emitter itself.
This commit is contained in:
+17
-1
@@ -1,5 +1,7 @@
|
||||
use clap::Parser;
|
||||
use myc::ast::compiler::emitter;
|
||||
use myc::ast::environment::Environment;
|
||||
use myc::ast::parser::Parser as MycParser;
|
||||
use myc::utils::tester;
|
||||
use std::fs;
|
||||
use std::io::{self, IsTerminal, Read};
|
||||
@@ -43,6 +45,10 @@ struct Cli {
|
||||
/// Start MCP server (stdio transport, for LLM integration)
|
||||
#[arg(long)]
|
||||
mcp: bool,
|
||||
|
||||
/// Emit the parsed source back as Myc code (round-trip test)
|
||||
#[arg(long)]
|
||||
emit: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -108,7 +114,17 @@ fn main() {
|
||||
};
|
||||
|
||||
if let Some(content) = source {
|
||||
if cli.dump {
|
||||
if cli.emit {
|
||||
let mut parser = MycParser::new(&content);
|
||||
let syntax_ast = parser.parse_expression();
|
||||
if parser.diagnostics.has_errors() {
|
||||
for diag in &parser.diagnostics.items {
|
||||
eprintln!("ERROR: {}", diag.message);
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
print!("{}", emitter::emit(&syntax_ast));
|
||||
} else if cli.dump {
|
||||
match env.dump_ast(&content) {
|
||||
Ok(dump) => println!("{}", dump),
|
||||
Err(e) => eprintln!("Error dumping AST: {}", e),
|
||||
|
||||
Reference in New Issue
Block a user