The parse() function returns an Ast struct that represents your entire Lua program. Let’s explore what we can do with it:
use full_moon::parse;fn main() -> Result<(), Box<dyn std::error::Error>> { let ast = parse("local x = 1")?; // Access the root block let block = ast.nodes(); // Iterate over statements for stmt in block.stmts() { println!("Statement: {}", stmt); } // Count tokens let token_count = ast.nodes().tokens().count(); println!("Token count: {}", token_count); Ok(())}
Full Moon’s AST is lossless - it preserves all whitespace, comments, and formatting. When you print the AST back to a string, you get exactly the original code!
Full Moon preserves trivia (comments and whitespace) which you can access:
use full_moon::{parse, node::Node};fn main() -> Result<(), Box<dyn std::error::Error>> { let code = r#"-- This is a commentlocal x = 1-- Another commentlocal y = 2"#; let ast = parse(code)?; let stmt = ast.nodes().stmts().nth(1); if let Some(stmt) = stmt { let (prev_trivia, _) = stmt.surrounding_trivia(); for trivia in prev_trivia { println!("Trivia: {}", trivia); } } Ok(())}
For tools like IDEs that need to work with incomplete code, use parse_fallible:
use full_moon::{parse_fallible, LuaVersion};fn main() { let code = "local x = if"; // Invalid code let result = parse_fallible(code, LuaVersion::new()); // Always returns an AST, even with errors let ast = result.ast(); println!("Partial AST: {}", ast); // Check for errors if !result.errors().is_empty() { eprintln!("Errors found:"); for error in result.errors() { eprintln!(" - {}", error.error_message()); } }}
Partial ASTs from parse_fallible may contain phantom tokens with null positions and may not print to valid Lua code. Use ast.update_positions() if you need accurate positions for phantom tokens.
use full_moon::parse;use std::fs;fn main() -> Result<(), Box<dyn std::error::Error>> { let code = fs::read_to_string("script.lua")?; let ast = parse(&code)?; println!("Parsed {} tokens", ast.nodes().tokens().count()); Ok(())}
Check if two statements are similar
use full_moon::{parse, node::Node};fn main() -> Result<(), Box<dyn std::error::Error>> { let ast = parse("local x = 1; local x = 1; local x = 2;")?; let stmts: Vec<_> = ast.nodes().stmts().collect(); assert!(stmts[0].similar(stmts[1])); // Same structure assert!(!stmts[0].similar(stmts[2])); // Different values Ok(())}
Specify Lua version
use full_moon::{parse_fallible, LuaVersion};fn main() { // Parse as Lua 5.2 (requires lua52 feature) #[cfg(feature = "lua52")] { let code = "goto label; ::label::"; let result = parse_fallible(code, LuaVersion::lua52()); println!("Parsed Lua 5.2 code"); } // Parse as Luau (requires luau feature) #[cfg(feature = "luau")] { let code = "local x: number = 1"; let result = parse_fallible(code, LuaVersion::luau()); println!("Parsed Luau code"); }}