parser+lexer: support switch statements

Closes #4.
This commit is contained in:
Ryan Chandler 2022-08-04 10:53:41 +01:00
parent 65fa165ba8
commit 431d449f10
No known key found for this signature in database
GPG Key ID: F113BCADDB3B0CCA
4 changed files with 59 additions and 6 deletions

View File

@ -714,6 +714,7 @@ fn identifier_to_keyword(ident: &str) -> Option<TokenKind> {
"array" => TokenKind::Array,
"as" => TokenKind::As,
"break" => TokenKind::Break,
"case" => TokenKind::Case,
"catch" => TokenKind::Catch,
"class" => TokenKind::Class,
"clone" => TokenKind::Clone,

View File

@ -210,6 +210,7 @@ pub enum Statement {
},
Switch {
condition: Expression,
cases: Vec<Case>,
},
Break {
num: Option<Expression>,
@ -242,6 +243,12 @@ pub enum Statement {
Noop,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Case {
pub condition: Option<Expression>,
pub body: Block,
}
#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Catch {
pub types: Vec<Identifier>,

View File

@ -1,5 +1,5 @@
mod ast;
mod parser;
pub use ast::{Statement, Expression, Program, Block, Param, Identifier, Type, InfixOp, MatchArm, Catch};
pub use ast::{Statement, Expression, Program, Block, Param, Identifier, Type, InfixOp, MatchArm, Catch, Case};
pub use parser::{Parser, ParseError};

View File

@ -1,6 +1,6 @@
use std::{vec::IntoIter, fmt::{Display, write}};
use std::{vec::IntoIter, fmt::{Display}};
use trunk_lexer::{Token, TokenKind, Span};
use crate::{Program, Statement, Block, Expression, ast::{ArrayItem, Use, MethodFlag, ClassFlag, ElseIf, UseKind, MagicConst}, Identifier, Type, MatchArm, Catch};
use crate::{Program, Statement, Block, Expression, ast::{ArrayItem, Use, MethodFlag, ClassFlag, ElseIf, UseKind, MagicConst}, Identifier, Type, MatchArm, Catch, Case};
type ParseResult<T> = Result<T, ParseError>;
@ -343,10 +343,55 @@ impl Parser {
self.rparen()?;
self.lbrace()?;
self.rbrace()?;
self.semi()?;
Statement::Switch { condition }
let mut cases = Vec::new();
loop {
if self.current.kind == TokenKind::RightBrace {
break;
}
match self.current.kind {
TokenKind::Case => {
self.next();
let condition = self.expression(0)?;
expect!(self, TokenKind::Colon, "expected :");
let mut body = Block::new();
while self.current.kind != TokenKind::Case && self.current.kind != TokenKind::Default && self.current.kind != TokenKind::RightBrace {
body.push(self.statement()?);
}
cases.push(Case {
condition: Some(condition),
body
});
},
TokenKind::Default => {
self.next();
expect!(self, TokenKind::Colon, "expected :");
let mut body = Block::new();
while self.current.kind != TokenKind::Case && self.current.kind != TokenKind::Default && self.current.kind != TokenKind::RightBrace {
body.push(self.statement()?);
}
cases.push(Case {
condition: None,
body
});
},
_ => return Err(ParseError::UnexpectedToken(self.current.kind.to_string(), self.current.span))
}
}
self.rbrace()?;
Statement::Switch { condition, cases }
},
TokenKind::Namespace => {
self.next();