Full Moon provides comprehensive error handling with two main error types and utilities for error recovery. Whether you’re building a strict compiler or a forgiving IDE, full-moon has you covered.
Full Moon uses a unified Error enum that encompasses both tokenization and parsing errors:
pub enum Error { /// Triggered if there's an issue creating an AST (tokenizing succeeded) AstError(ast::AstError), /// Triggered if there's an issue when tokenizing TokenizerError(tokenizer::TokenizerError),}
use full_moon::Error;fn handle_error(error: &Error) { // Get human-readable message let message = error.error_message(); println!("Message: {}", message); // Get position range let (start, end) = error.range(); println!("Position: line {}, column {} to line {}, column {}", start.line(), start.character(), end.line(), end.character() );}
For tools like linters, formatters, and IDEs, you often want to parse incomplete or invalid code:
use full_moon::{parse_fallible, LuaVersion};let code = "if x == 2 code()";let result = parse_fallible(code, LuaVersion::new());// ALWAYS produces an AST, even with errorslet ast = result.ast();println!("AST: {}", ast);// Check if there were errorsif !result.errors().is_empty() { println!("Recovered from {} error(s)", result.errors().len()); for error in result.errors() { eprintln!("Error: {}", error.error_message()); }}
parse_fallible may insert phantom tokens (like missing then keywords) to create a valid AST structure. These phantom tokens have null positions.
When using parse_fallible, full-moon may insert phantom tokens:
use full_moon::{parse_fallible, LuaVersion};use full_moon::node::Node;let code = "if x == 2 code()";let result = parse_fallible(code, LuaVersion::new());let ast = result.ast();// The AST will have a phantom `then` tokenfor stmt in ast.nodes().stmts() { if let Stmt::If(if_stmt) = stmt { let then_token = if_stmt.then_token(); // Check if token is phantom (null position) if then_token.start_position().is_none() { println!("Phantom token detected"); } }}