loops
This commit is contained in:
@@ -204,7 +204,7 @@ impl Parser {
|
||||
|
||||
let expr = match current_token.token_type {
|
||||
// match unsupported keywords
|
||||
TokenType::Keyword(e) if matches_keyword!(e, Keyword::Enum, Keyword::While) => {
|
||||
TokenType::Keyword(e) if matches_keyword!(e, Keyword::Enum) => {
|
||||
return Err(Error::UnsupportedKeyword(current_token.clone()));
|
||||
}
|
||||
|
||||
@@ -219,6 +219,22 @@ impl Parser {
|
||||
// match if statements
|
||||
TokenType::Keyword(Keyword::If) => Expression::If(self.if_expression()?),
|
||||
|
||||
// match loop statements
|
||||
TokenType::Keyword(Keyword::Loop) => Expression::Loop(self.loop_expression()?),
|
||||
|
||||
// match while statements
|
||||
TokenType::Keyword(Keyword::While) => Expression::While(self.while_expression()?),
|
||||
|
||||
// match break statements
|
||||
TokenType::Keyword(Keyword::Break) => {
|
||||
// make sure the next token is a semi-colon
|
||||
let next = token_from_option!(self.get_next()?);
|
||||
if !token_matches!(next, TokenType::Symbol(Symbol::Semicolon)) {
|
||||
return Err(Error::UnexpectedToken(next.clone()));
|
||||
}
|
||||
Expression::Break
|
||||
}
|
||||
|
||||
// match syscalls with a `syscall` keyword
|
||||
TokenType::Identifier(ref id) if SysCall::is_syscall(id) => {
|
||||
Expression::Syscall(self.syscall()?)
|
||||
@@ -832,6 +848,61 @@ impl Parser {
|
||||
})
|
||||
}
|
||||
|
||||
fn loop_expression(&mut self) -> Result<LoopExpression, Error> {
|
||||
let current_token = token_from_option!(self.current_token);
|
||||
if !self_matches_current!(self, TokenType::Keyword(Keyword::Loop)) {
|
||||
return Err(Error::UnexpectedToken(current_token.clone()));
|
||||
}
|
||||
|
||||
// check for '{'
|
||||
let next = token_from_option!(self.get_next()?);
|
||||
if !token_matches!(next, TokenType::Symbol(Symbol::LBrace)) {
|
||||
return Err(Error::UnexpectedToken(next.clone()));
|
||||
}
|
||||
|
||||
// parse body
|
||||
let body = self.block()?;
|
||||
|
||||
Ok(LoopExpression { body })
|
||||
}
|
||||
|
||||
fn while_expression(&mut self) -> Result<WhileExpression, Error> {
|
||||
let current_token = token_from_option!(self.current_token);
|
||||
if !self_matches_current!(self, TokenType::Keyword(Keyword::While)) {
|
||||
return Err(Error::UnexpectedToken(current_token.clone()));
|
||||
}
|
||||
|
||||
// consume 'while'
|
||||
let next = token_from_option!(self.get_next()?);
|
||||
if !token_matches!(next, TokenType::Symbol(Symbol::LParen)) {
|
||||
return Err(Error::UnexpectedToken(next.clone()));
|
||||
}
|
||||
self.assign_next()?;
|
||||
|
||||
// parse condition
|
||||
let condition = self.expression()?.ok_or(Error::UnexpectedEOF)?;
|
||||
|
||||
// check for ')'
|
||||
let next = token_from_option!(self.get_next()?);
|
||||
if !token_matches!(next, TokenType::Symbol(Symbol::RParen)) {
|
||||
return Err(Error::UnexpectedToken(next.clone()));
|
||||
}
|
||||
|
||||
// check for '{'
|
||||
let next = token_from_option!(self.get_next()?);
|
||||
if !token_matches!(next, TokenType::Symbol(Symbol::LBrace)) {
|
||||
return Err(Error::UnexpectedToken(next.clone()));
|
||||
}
|
||||
|
||||
// parse body
|
||||
let body = self.block()?;
|
||||
|
||||
Ok(WhileExpression {
|
||||
condition: boxed!(condition),
|
||||
body,
|
||||
})
|
||||
}
|
||||
|
||||
fn function(&mut self) -> Result<FunctionExpression, Error> {
|
||||
let current_token = token_from_option!(self.current_token);
|
||||
// Sanify check that the current token is a `fn` keyword
|
||||
@@ -1121,4 +1192,3 @@ impl Parser {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -185,11 +185,35 @@ impl std::fmt::Display for IfExpression {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct LoopExpression {
|
||||
pub body: BlockExpression,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for LoopExpression {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "(loop {})", self.body)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct WhileExpression {
|
||||
pub condition: Box<Expression>,
|
||||
pub body: BlockExpression,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for WhileExpression {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "(while {} {})", self.condition, self.body)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Expression {
|
||||
Assignment(AssignmentExpression),
|
||||
Binary(BinaryExpression),
|
||||
Block(BlockExpression),
|
||||
Break,
|
||||
Declaration(String, Box<Expression>),
|
||||
DeviceDeclaration(DeviceDeclarationExpression),
|
||||
Function(FunctionExpression),
|
||||
@@ -197,11 +221,13 @@ pub enum Expression {
|
||||
Invocation(InvocationExpression),
|
||||
Literal(Literal),
|
||||
Logical(LogicalExpression),
|
||||
Loop(LoopExpression),
|
||||
Negation(Box<Expression>),
|
||||
Priority(Box<Expression>),
|
||||
Return(Box<Expression>),
|
||||
Syscall(SysCall),
|
||||
Variable(String),
|
||||
While(WhileExpression),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Expression {
|
||||
@@ -209,19 +235,23 @@ impl std::fmt::Display for Expression {
|
||||
match self {
|
||||
Expression::Assignment(e) => write!(f, "{}", e),
|
||||
Expression::Binary(e) => write!(f, "{}", e),
|
||||
Expression::Literal(l) => write!(f, "{}", l),
|
||||
Expression::Negation(e) => write!(f, "(-{})", e),
|
||||
Expression::Logical(e) => write!(f, "{}", e),
|
||||
Expression::Declaration(id, e) => write!(f, "(let {} = {})", id, e),
|
||||
Expression::Function(e) => write!(f, "{}", e),
|
||||
Expression::Block(e) => write!(f, "{}", e),
|
||||
Expression::Break => write!(f, "break"),
|
||||
Expression::Declaration(id, e) => write!(f, "(let {} = {})", id, e),
|
||||
Expression::DeviceDeclaration(e) => write!(f, "{}", e),
|
||||
Expression::Function(e) => write!(f, "{}", e),
|
||||
Expression::If(e) => write!(f, "{}", e),
|
||||
Expression::Invocation(e) => write!(f, "{}", e),
|
||||
Expression::Variable(id) => write!(f, "{}", id),
|
||||
Expression::Literal(l) => write!(f, "{}", l),
|
||||
Expression::Logical(e) => write!(f, "{}", e),
|
||||
Expression::Loop(e) => write!(f, "{}", e),
|
||||
Expression::Negation(e) => write!(f, "(-{})", e),
|
||||
Expression::Priority(e) => write!(f, "({})", e),
|
||||
Expression::Return(e) => write!(f, "(return {})", e),
|
||||
Expression::DeviceDeclaration(e) => write!(f, "{}", e),
|
||||
Expression::Syscall(e) => write!(f, "{}", e),
|
||||
Expression::Variable(id) => write!(f, "{}", id),
|
||||
Expression::While(e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user