use crate::ast::Expression;
use crate::ast::Node;
use crate::ast::Statement;
use crate::error::SyntaxErrorType;
use crate::error::SyntaxResult;
use crate::parse::Parser;
use crate::symbol::ScopeType;
use crate::token::TokenType;
use crate::token::TokenTypeSet;
impl<'a> Parser<'a> {
pub fn parse_stmt(&mut self, require_semicolon: bool) -> SyntaxResult<Node<Statement>> {
let stmt = match self.peek()?.typ {
TokenType::KeywordBreak => self.parse_stmt_break(),
TokenType::KeywordContinue => self.parse_stmt_continue(),
TokenType::KeywordFor => self.parse_stmt_for(),
TokenType::KeywordLet => self.parse_stmt_let(),
TokenType::KeywordLoop => self.parse_stmt_loop(),
TokenType::KeywordReturn => self.parse_stmt_return(),
_ => {
let expr = self.parse_expr_until(TokenTypeSet::new(&[
TokenType::Equals,
TokenType::Semicolon,
TokenType::BraceClose,
]))?;
let stmt = if self.consume_if(TokenType::Equals)?.is_match() {
let value = self.parse_expr(TokenType::Semicolon)?;
self.new_statement(expr.loc + value.loc, match *expr.stx {
Expression::Field {
object,
field,
optional,
} => Statement::FieldAssign {
object,
field,
value,
optional,
},
Expression::Index {
object,
index,
optional,
} => Statement::IndexAssign {
object,
index,
value,
optional,
},
Expression::Var { name } => Statement::VarAssign {
variable: name,
value,
},
_ => {
return Err(
expr
.loc
.error(SyntaxErrorType::InvalidAssigmentTarget, None),
)
}
})
} else {
self.new_statement(expr.loc, Statement::Expression { expression: expr })
};
Ok(stmt)
}
}?;
if require_semicolon {
self.require(TokenType::Semicolon)?;
};
Ok(stmt)
}
pub fn parse_stmt_break(&mut self) -> SyntaxResult<Node<Statement>> {
let loc = self.require(TokenType::KeywordBreak)?.loc;
Ok(self.new_statement(loc, Statement::Break))
}
pub fn parse_stmt_continue(&mut self) -> SyntaxResult<Node<Statement>> {
let loc = self.require(TokenType::KeywordContinue)?.loc;
Ok(self.new_statement(loc, Statement::Continue))
}
pub fn parse_stmt_for(&mut self) -> SyntaxResult<Node<Statement>> {
let parent_scope = self.enter_new_scope(ScopeType::Block);
let loc_start = self.require(TokenType::KeywordFor)?.loc;
let (_, variable) = self.require_identifier_as_string()?;
assert!(self.scope.add_symbol(variable.clone()));
self.require(TokenType::KeywordIn)?;
let iterable = self.parse_expr(TokenType::BraceOpen)?;
let body = self.parse_expr_block_without_new_scope()?;
match body.stx.as_ref() {
Expression::Block {
result: Some(..), ..
} => return Err(body.loc.error(SyntaxErrorType::LoopCannotResult, None)),
_ => {}
};
let stmt = self.new_statement(loc_start + body.loc, Statement::For {
variable,
iterable,
body,
});
self.return_to_scope(parent_scope);
Ok(stmt)
}
pub fn parse_stmt_let(&mut self) -> SyntaxResult<Node<Statement>> {
let loc_start = self.require(TokenType::KeywordLet)?.loc;
let (variable_loc, variable) = self.require_identifier_as_string()?;
if !self.scope.add_symbol(variable.clone()) {
return Err(variable_loc.error(SyntaxErrorType::RedeclaredVar, None));
};
self.require(TokenType::Equals)?;
let value = self.parse_expr(TokenType::Semicolon)?;
Ok(self.new_statement(loc_start + value.loc, Statement::Let { variable, value }))
}
pub fn parse_stmt_loop(&mut self) -> SyntaxResult<Node<Statement>> {
let loc_start = self.require(TokenType::KeywordLoop)?.loc;
let body = self.parse_expr_block()?;
match body.stx.as_ref() {
Expression::Block {
result: Some(..), ..
} => return Err(body.loc.error(SyntaxErrorType::LoopCannotResult, None)),
_ => {}
};
Ok(self.new_statement(loc_start + body.loc, Statement::Loop { body }))
}
pub fn parse_stmt_return(&mut self) -> SyntaxResult<Node<Statement>> {
let loc_start = self.require(TokenType::KeywordReturn)?.loc;
let value = if self.peek()?.typ == TokenType::Semicolon {
None
} else {
Some(self.parse_expr(TokenType::Semicolon)?)
};
Ok(self.new_statement(loc_start, Statement::Return { value }))
}
}