documentation run
This commit is contained in:
parent
eefbcc8ae2
commit
3cbeab3434
1 changed files with 37 additions and 3 deletions
|
@ -81,6 +81,7 @@ struct Parser {
|
|||
|
||||
impl Parser {
|
||||
/// Create a new parser instance, fail if the tokens vector is empty.
|
||||
/// Initialize the current token to the first token in the list.
|
||||
fn new(tokens: Vec<Token>) -> Result<Self, ParserError> {
|
||||
let current_token = tokens.first().ok_or(ParserError::NoTokens)?.clone();
|
||||
|
||||
|
@ -92,6 +93,8 @@ impl Parser {
|
|||
}
|
||||
|
||||
/// Parse all tokens to a list of statements for execution.
|
||||
/// Continue parsing until reaching the end of the token stream.
|
||||
/// Handle errors by logging them and synchronizing to continue parsing.
|
||||
fn run(&mut self) -> Result<Vec<Statement>, ParserError> {
|
||||
let mut statements = Vec::new();
|
||||
|
||||
|
@ -110,7 +113,8 @@ impl Parser {
|
|||
|
||||
/// Check if any of the provided types match the type of the current token.
|
||||
///
|
||||
/// If so, advance the current token.
|
||||
/// If so, advance the current token and return true.
|
||||
/// Otherwise, return false without advancing.
|
||||
fn matches(&mut self, types: &[TokenType]) -> bool {
|
||||
let matches = types.iter().any(|x| self.check(x));
|
||||
matches.then(|| self.advance());
|
||||
|
@ -151,7 +155,7 @@ impl Parser {
|
|||
}
|
||||
|
||||
/// Consume the current token if its token type matches the provided token_type and advance the
|
||||
/// current token. Otherwise return None..
|
||||
/// current token. Otherwise return None.
|
||||
fn consume(&mut self, token_type: &TokenType) -> Option<&Token> {
|
||||
if self.check(token_type) {
|
||||
self.advance().ok()
|
||||
|
@ -185,6 +189,7 @@ impl Parser {
|
|||
self.assignment()
|
||||
}
|
||||
|
||||
/// Parse a declaration.
|
||||
fn declaration(&mut self) -> Result<Statement, ParserError> {
|
||||
if self.matches(&[Class]) {
|
||||
self.class_declaration()
|
||||
|
@ -197,6 +202,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse a statement.
|
||||
fn statement(&mut self) -> Result<Statement, ParserError> {
|
||||
if self.matches(&[For]) {
|
||||
self.for_statement()
|
||||
|
@ -215,7 +221,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
/// Build up a while statement from a for statement.
|
||||
/// Parse a for statement by desugaring it into a while loop.
|
||||
fn for_statement(&mut self) -> Result<Statement, ParserError> {
|
||||
let line = self.current_token.line;
|
||||
self.consume(&LeftParen)
|
||||
|
@ -264,6 +270,8 @@ impl Parser {
|
|||
Ok(body)
|
||||
}
|
||||
|
||||
/// Parse an if statement with a condition, then branch, and optional else branch.
|
||||
/// The condition must be enclosed in parentheses.
|
||||
fn if_statement(&mut self) -> Result<Statement, ParserError> {
|
||||
let line = self.current_token.line;
|
||||
self.consume(&LeftParen)
|
||||
|
@ -288,6 +296,8 @@ impl Parser {
|
|||
})
|
||||
}
|
||||
|
||||
/// Parse a print statement, which consists of an expression followed by a semicolon.
|
||||
/// The expression's value will be printed during execution.
|
||||
fn print_statement(&mut self) -> Result<Statement, ParserError> {
|
||||
let value = self.expression()?;
|
||||
let line = self.current_token.line;
|
||||
|
@ -297,6 +307,8 @@ impl Parser {
|
|||
Ok(Statement::Print(value))
|
||||
}
|
||||
|
||||
/// Parse a return statement, which may include a return value expression.
|
||||
/// The return value is optional - if not provided, nil is returned implicitly.
|
||||
fn return_statement(&mut self) -> Result<Statement, ParserError> {
|
||||
let keyword = self.previous()?.clone();
|
||||
let value = if self.check(&Semicolon) {
|
||||
|
@ -311,6 +323,8 @@ impl Parser {
|
|||
Ok(Statement::Return { keyword, value })
|
||||
}
|
||||
|
||||
/// Parse a class declaration with a name, optional superclass, and methods.
|
||||
/// A class can inherit from a superclass using the '<' operator.
|
||||
fn class_declaration(&mut self) -> Result<Statement, ParserError> {
|
||||
let line = self.current_token.line;
|
||||
let name = self
|
||||
|
@ -347,6 +361,8 @@ impl Parser {
|
|||
})
|
||||
}
|
||||
|
||||
/// Parse a variable declaration with a name and optional initializer.
|
||||
/// If no initializer is provided, the variable is initialized to nil.
|
||||
fn var_declaration(&mut self) -> Result<Statement, ParserError> {
|
||||
let line = self.current_token.line;
|
||||
let name = self
|
||||
|
@ -369,6 +385,8 @@ impl Parser {
|
|||
})
|
||||
}
|
||||
|
||||
/// Parse a while statement with a condition and body.
|
||||
/// The condition must be enclosed in parentheses.
|
||||
fn while_statement(&mut self) -> Result<Statement, ParserError> {
|
||||
let line = self.current_token.line;
|
||||
self.consume(&LeftParen)
|
||||
|
@ -387,6 +405,8 @@ impl Parser {
|
|||
})
|
||||
}
|
||||
|
||||
/// Parse an expression statement, which is an expression followed by a semicolon.
|
||||
/// The expression is evaluated for its side effects.
|
||||
fn expression_statement(&mut self) -> Result<Statement, ParserError> {
|
||||
let expr = self.expression()?;
|
||||
let line = self.current_token.line;
|
||||
|
@ -396,6 +416,8 @@ impl Parser {
|
|||
Ok(Statement::Expression(expr))
|
||||
}
|
||||
|
||||
/// Parse a function declaration with a name, parameters, and body.
|
||||
/// Used for both standalone functions and class methods.
|
||||
fn function(&mut self) -> Result<Statement, ParserError> {
|
||||
let line = self.current_token.line;
|
||||
let name = self
|
||||
|
@ -433,6 +455,8 @@ impl Parser {
|
|||
Ok(Statement::Function { name, params, body })
|
||||
}
|
||||
|
||||
/// Parse a block of statements enclosed in braces.
|
||||
/// A block creates a new scope for variable declarations.
|
||||
fn block(&mut self) -> Result<Vec<Statement>, ParserError> {
|
||||
let mut statements = Vec::new();
|
||||
|
||||
|
@ -447,6 +471,8 @@ impl Parser {
|
|||
Ok(statements)
|
||||
}
|
||||
|
||||
/// Parse an assignment expression, which can assign to a variable or object property.
|
||||
/// Assignment is right-associative, so we recursively parse the right side.
|
||||
fn assignment(&mut self) -> Result<Expression, ParserError> {
|
||||
let expr = self.or()?;
|
||||
|
||||
|
@ -473,6 +499,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse a logical expression with a specific operator (AND or OR).
|
||||
fn logical_operator<F>(
|
||||
&mut self,
|
||||
operator: TokenType,
|
||||
|
@ -497,10 +524,12 @@ impl Parser {
|
|||
Ok(expr)
|
||||
}
|
||||
|
||||
/// Parse a logical OR expression.
|
||||
fn or(&mut self) -> Result<Expression, ParserError> {
|
||||
self.logical_operator(Or, Self::and)
|
||||
}
|
||||
|
||||
/// Parse a logical AND expression.
|
||||
fn and(&mut self) -> Result<Expression, ParserError> {
|
||||
self.logical_operator(And, Self::equality)
|
||||
}
|
||||
|
@ -540,6 +569,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
/// Parse a call expression or property access.
|
||||
fn call(&mut self) -> Result<Expression, ParserError> {
|
||||
let mut expr = self.primary()?;
|
||||
|
||||
|
@ -565,6 +595,8 @@ impl Parser {
|
|||
Ok(expr)
|
||||
}
|
||||
|
||||
/// Complete parsing a function call after seeing the opening parenthesis.
|
||||
/// Parse the arguments and closing parenthesis.
|
||||
fn finish_call(&mut self, callee: Expression) -> Result<Expression, ParserError> {
|
||||
let mut args = Vec::new();
|
||||
|
||||
|
@ -643,6 +675,8 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
/// Synchronize the parser after an error by advancing to the next statement boundary.
|
||||
/// This allows parsing to continue after encountering a syntax error.
|
||||
fn synchronize(&mut self) {
|
||||
let _ = self.advance();
|
||||
while !self.is_at_end()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue