Clean up and add docs
This commit is contained in:
parent
e99a7b5e1e
commit
dc9b451b37
@ -278,7 +278,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_boolean(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_boolean(&mut self) -> Result<(), CompileError> {
|
||||||
let position = self.current_position;
|
let position = self.current_position;
|
||||||
|
|
||||||
if let Token::Boolean(text) = self.current_token {
|
if let Token::Boolean(text) = self.current_token {
|
||||||
@ -304,7 +304,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_byte(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_byte(&mut self) -> Result<(), CompileError> {
|
||||||
let position = self.current_position;
|
let position = self.current_position;
|
||||||
|
|
||||||
if let Token::Byte(text) = self.current_token {
|
if let Token::Byte(text) = self.current_token {
|
||||||
@ -328,7 +328,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_character(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_character(&mut self) -> Result<(), CompileError> {
|
||||||
let position = self.current_position;
|
let position = self.current_position;
|
||||||
|
|
||||||
if let Token::Character(character) = self.current_token {
|
if let Token::Character(character) = self.current_token {
|
||||||
@ -350,7 +350,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_float(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_float(&mut self) -> Result<(), CompileError> {
|
||||||
let position = self.current_position;
|
let position = self.current_position;
|
||||||
|
|
||||||
if let Token::Float(text) = self.current_token {
|
if let Token::Float(text) = self.current_token {
|
||||||
@ -378,7 +378,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_integer(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_integer(&mut self) -> Result<(), CompileError> {
|
||||||
let position = self.current_position;
|
let position = self.current_position;
|
||||||
|
|
||||||
if let Token::Integer(text) = self.current_token {
|
if let Token::Integer(text) = self.current_token {
|
||||||
@ -406,7 +406,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_string(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_string(&mut self) -> Result<(), CompileError> {
|
||||||
let position = self.current_position;
|
let position = self.current_position;
|
||||||
|
|
||||||
if let Token::String(text) = self.current_token {
|
if let Token::String(text) = self.current_token {
|
||||||
@ -428,7 +428,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_grouped(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_grouped(&mut self) -> Result<(), CompileError> {
|
||||||
self.allow(Token::LeftParenthesis)?;
|
self.allow(Token::LeftParenthesis)?;
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
self.expect(Token::RightParenthesis)?;
|
self.expect(Token::RightParenthesis)?;
|
||||||
@ -438,7 +438,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_unary(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_unary(&mut self) -> Result<(), CompileError> {
|
||||||
let operator = self.current_token;
|
let operator = self.current_token;
|
||||||
let operator_position = self.current_position;
|
let operator_position = self.current_position;
|
||||||
|
|
||||||
@ -758,7 +758,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_variable(&mut self, allowed: Allowed) -> Result<(), CompileError> {
|
fn parse_variable(&mut self) -> Result<(), CompileError> {
|
||||||
let start_position = self.current_position;
|
let start_position = self.current_position;
|
||||||
let identifier = if let Token::Identifier(text) = self.current_token {
|
let identifier = if let Token::Identifier(text) = self.current_token {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
@ -809,13 +809,6 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.allow(Token::Equal)? {
|
if self.allow(Token::Equal)? {
|
||||||
if !allowed.assignment {
|
|
||||||
return Err(CompileError::InvalidAssignmentTarget {
|
|
||||||
found: self.current_token.to_owned(),
|
|
||||||
position: self.current_position,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if !is_mutable {
|
if !is_mutable {
|
||||||
return Err(CompileError::CannotMutateImmutableVariable {
|
return Err(CompileError::CannotMutateImmutableVariable {
|
||||||
identifier: self.chunk.get_identifier(local_index).unwrap(),
|
identifier: self.chunk.get_identifier(local_index).unwrap(),
|
||||||
@ -886,18 +879,12 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_block(&mut self) -> Result<(), CompileError> {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
self.chunk.begin_scope();
|
self.chunk.begin_scope();
|
||||||
|
|
||||||
while !self.allow(Token::RightCurlyBrace)? && !self.is_eof() {
|
while !self.allow(Token::RightCurlyBrace)? && !self.is_eof() {
|
||||||
self.parse(
|
self.parse(Precedence::None)?;
|
||||||
Precedence::None,
|
|
||||||
Allowed {
|
|
||||||
assignment: true,
|
|
||||||
explicit_return: true,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.chunk.end_scope();
|
self.chunk.end_scope();
|
||||||
@ -905,7 +892,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_list(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_list(&mut self) -> Result<(), CompileError> {
|
||||||
let start = self.current_position.0;
|
let start = self.current_position.0;
|
||||||
|
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
@ -942,7 +929,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_if(&mut self, allowed: Allowed) -> Result<(), CompileError> {
|
fn parse_if(&mut self) -> Result<(), CompileError> {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
|
||||||
@ -964,7 +951,7 @@ impl<'src> Compiler<'src> {
|
|||||||
let if_block_start_position = self.current_position;
|
let if_block_start_position = self.current_position;
|
||||||
|
|
||||||
if let Token::LeftCurlyBrace = self.current_token {
|
if let Token::LeftCurlyBrace = self.current_token {
|
||||||
self.parse_block(allowed)?;
|
self.parse_block()?;
|
||||||
} else {
|
} else {
|
||||||
return Err(CompileError::ExpectedToken {
|
return Err(CompileError::ExpectedToken {
|
||||||
expected: TokenKind::LeftCurlyBrace,
|
expected: TokenKind::LeftCurlyBrace,
|
||||||
@ -996,7 +983,7 @@ impl<'src> Compiler<'src> {
|
|||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
if let Token::LeftCurlyBrace = self.current_token {
|
if let Token::LeftCurlyBrace = self.current_token {
|
||||||
self.parse_block(allowed)?;
|
self.parse_block()?;
|
||||||
} else {
|
} else {
|
||||||
return Err(CompileError::ExpectedTokenMultiple {
|
return Err(CompileError::ExpectedTokenMultiple {
|
||||||
expected: &[TokenKind::If, TokenKind::LeftCurlyBrace],
|
expected: &[TokenKind::If, TokenKind::LeftCurlyBrace],
|
||||||
@ -1073,7 +1060,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_while(&mut self, allowed: Allowed) -> Result<(), CompileError> {
|
fn parse_while(&mut self) -> Result<(), CompileError> {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let expression_start = self.chunk.len() as u8;
|
let expression_start = self.chunk.len() as u8;
|
||||||
@ -1096,10 +1083,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
let block_start = self.chunk.len();
|
let block_start = self.chunk.len();
|
||||||
|
|
||||||
self.parse_block(Allowed {
|
self.parse_block()?;
|
||||||
assignment: true,
|
|
||||||
explicit_return: allowed.explicit_return,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let block_end = self.chunk.len() as u8;
|
let block_end = self.chunk.len() as u8;
|
||||||
|
|
||||||
@ -1158,13 +1142,7 @@ impl<'src> Compiler<'src> {
|
|||||||
|
|
||||||
fn parse_top_level(&mut self) -> Result<(), CompileError> {
|
fn parse_top_level(&mut self) -> Result<(), CompileError> {
|
||||||
loop {
|
loop {
|
||||||
self.parse(
|
self.parse(Precedence::None)?;
|
||||||
Precedence::None,
|
|
||||||
Allowed {
|
|
||||||
assignment: true,
|
|
||||||
explicit_return: false,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if self.is_eof() || self.allow(Token::RightCurlyBrace)? {
|
if self.is_eof() || self.allow(Token::RightCurlyBrace)? {
|
||||||
self.parse_implicit_return()?;
|
self.parse_implicit_return()?;
|
||||||
@ -1177,13 +1155,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expression(&mut self) -> Result<(), CompileError> {
|
fn parse_expression(&mut self) -> Result<(), CompileError> {
|
||||||
self.parse(
|
self.parse(Precedence::None)?;
|
||||||
Precedence::None,
|
|
||||||
Allowed {
|
|
||||||
assignment: false,
|
|
||||||
explicit_return: false,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if !self.previous_is_expression || self.chunk.is_empty() {
|
if !self.previous_is_expression || self.chunk.is_empty() {
|
||||||
return Err(CompileError::ExpectedExpression {
|
return Err(CompileError::ExpectedExpression {
|
||||||
@ -1196,22 +1168,10 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_sub_expression(&mut self, precedence: &Precedence) -> Result<(), CompileError> {
|
fn parse_sub_expression(&mut self, precedence: &Precedence) -> Result<(), CompileError> {
|
||||||
self.parse(
|
self.parse(precedence.increment())
|
||||||
precedence.increment(),
|
|
||||||
Allowed {
|
|
||||||
assignment: false,
|
|
||||||
explicit_return: false,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_return_statement(&mut self, allowed: Allowed) -> Result<(), CompileError> {
|
|
||||||
if !allowed.explicit_return {
|
|
||||||
return Err(CompileError::UnexpectedReturn {
|
|
||||||
position: self.current_position,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_return_statement(&mut self) -> Result<(), CompileError> {
|
||||||
let start = self.current_position.0;
|
let start = self.current_position.0;
|
||||||
|
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
@ -1248,14 +1208,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_let_statement(&mut self, allowed: Allowed) -> Result<(), CompileError> {
|
fn parse_let_statement(&mut self) -> Result<(), CompileError> {
|
||||||
if !allowed.assignment {
|
|
||||||
return Err(CompileError::ExpectedExpression {
|
|
||||||
found: self.current_token.to_owned(),
|
|
||||||
position: self.current_position,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
let scope = self.chunk.current_scope();
|
let scope = self.chunk.current_scope();
|
||||||
@ -1299,7 +1252,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_function(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_function(&mut self) -> Result<(), CompileError> {
|
||||||
let function_start = self.current_position.0;
|
let function_start = self.current_position.0;
|
||||||
let mut function_compiler = Compiler::new(self.lexer)?;
|
let mut function_compiler = Compiler::new(self.lexer)?;
|
||||||
let identifier = if let Token::Identifier(text) = function_compiler.current_token {
|
let identifier = if let Token::Identifier(text) = function_compiler.current_token {
|
||||||
@ -1477,7 +1430,7 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_semicolon(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn parse_semicolon(&mut self) -> Result<(), CompileError> {
|
||||||
self.advance()?;
|
self.advance()?;
|
||||||
|
|
||||||
self.previous_is_expression = false;
|
self.previous_is_expression = false;
|
||||||
@ -1485,21 +1438,21 @@ impl<'src> Compiler<'src> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expect_expression(&mut self, _: Allowed) -> Result<(), CompileError> {
|
fn expect_expression(&mut self) -> Result<(), CompileError> {
|
||||||
Err(CompileError::ExpectedExpression {
|
Err(CompileError::ExpectedExpression {
|
||||||
found: self.current_token.to_owned(),
|
found: self.current_token.to_owned(),
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(&mut self, precedence: Precedence, allowed: Allowed) -> Result<(), CompileError> {
|
fn parse(&mut self, precedence: Precedence) -> Result<(), CompileError> {
|
||||||
if let Some(prefix_parser) = ParseRule::from(&self.current_token).prefix {
|
if let Some(prefix_parser) = ParseRule::from(&self.current_token).prefix {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"{} is prefix with precedence {precedence}",
|
"{} is prefix with precedence {precedence}",
|
||||||
self.current_token.to_string().bold(),
|
self.current_token.to_string().bold(),
|
||||||
);
|
);
|
||||||
|
|
||||||
prefix_parser(self, allowed)?;
|
prefix_parser(self)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut infix_rule = ParseRule::from(&self.current_token);
|
let mut infix_rule = ParseRule::from(&self.current_token);
|
||||||
@ -1511,7 +1464,7 @@ impl<'src> Compiler<'src> {
|
|||||||
self.current_token.to_string().bold(),
|
self.current_token.to_string().bold(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if !allowed.assignment && self.current_token == Token::Equal {
|
if self.current_token == Token::Equal {
|
||||||
return Err(CompileError::InvalidAssignmentTarget {
|
return Err(CompileError::InvalidAssignmentTarget {
|
||||||
found: self.current_token.to_owned(),
|
found: self.current_token.to_owned(),
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
@ -1530,6 +1483,7 @@ impl<'src> Compiler<'src> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Operator precedence levels.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum Precedence {
|
pub enum Precedence {
|
||||||
None,
|
None,
|
||||||
@ -1571,19 +1525,13 @@ impl Display for Precedence {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
type Parser<'a> = fn(&mut Compiler<'a>) -> Result<(), CompileError>;
|
||||||
struct Allowed {
|
|
||||||
pub assignment: bool,
|
|
||||||
pub explicit_return: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
type PrefixFunction<'a> = fn(&mut Compiler<'a>, Allowed) -> Result<(), CompileError>;
|
|
||||||
type InfixFunction<'a> = fn(&mut Compiler<'a>) -> Result<(), CompileError>;
|
|
||||||
|
|
||||||
|
/// Rule that defines how to parse a token.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
struct ParseRule<'a> {
|
struct ParseRule<'a> {
|
||||||
pub prefix: Option<PrefixFunction<'a>>,
|
pub prefix: Option<Parser<'a>>,
|
||||||
pub infix: Option<InfixFunction<'a>>,
|
pub infix: Option<Parser<'a>>,
|
||||||
pub precedence: Precedence,
|
pub precedence: Precedence,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1854,6 +1802,7 @@ impl From<&Token<'_>> for ParseRule<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Compilation errors
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum CompileError {
|
pub enum CompileError {
|
||||||
// Token errors
|
// Token errors
|
||||||
@ -1868,7 +1817,7 @@ pub enum CompileError {
|
|||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Expression errors
|
// Parsing errors
|
||||||
CannotChainComparison {
|
CannotChainComparison {
|
||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
@ -1876,6 +1825,13 @@ pub enum CompileError {
|
|||||||
found: TokenOwned,
|
found: TokenOwned,
|
||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
|
InvalidAssignmentTarget {
|
||||||
|
found: TokenOwned,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
|
UnexpectedReturn {
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
|
|
||||||
// Variable errors
|
// Variable errors
|
||||||
CannotMutateImmutableVariable {
|
CannotMutateImmutableVariable {
|
||||||
@ -1897,15 +1853,6 @@ pub enum CompileError {
|
|||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Statement errors
|
|
||||||
InvalidAssignmentTarget {
|
|
||||||
found: TokenOwned,
|
|
||||||
position: Span,
|
|
||||||
},
|
|
||||||
UnexpectedReturn {
|
|
||||||
position: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Wrappers around foreign errors
|
// Wrappers around foreign errors
|
||||||
Chunk {
|
Chunk {
|
||||||
error: ChunkError,
|
error: ChunkError,
|
||||||
|
Loading…
Reference in New Issue
Block a user