Browse Source

feat: parser implementation of match

match-statements
Garrit Franke 3 years ago
parent
commit
b4e9ae520d
  1. 1
      src/generator/c.rs
  2. 1
      src/generator/js.rs
  3. 3
      src/parser/node_type.rs
  4. 6
      src/parser/parser.rs
  5. 42
      src/parser/rules.rs

1
src/generator/c.rs

@ -112,6 +112,7 @@ fn generate_statement(statement: Statement) -> String {
Statement::For(_ident, _expr, _body) => todo!(),
Statement::Continue => todo!(),
Statement::Break => todo!(),
Statement::Match(_, _) => todo!(),
};
format!("{}\n", state)

1
src/generator/js.rs

@ -103,6 +103,7 @@ fn generate_statement(statement: Statement) -> String {
Statement::For(ident, expr, body) => generate_for_loop(ident, expr, *body),
Statement::Continue => generate_continue(),
Statement::Break => generate_break(),
Statement::Match(_, _) => todo!(),
};
format!("{};\n", state)

3
src/parser/node_type.rs

@ -20,6 +20,8 @@ use std::collections::HashMap;
/// Table that contains all symbol and its types
pub type SymbolTable = HashMap<String, Option<Type>>;
pub type MatchArm = (Expression, Statement);
#[derive(Debug)]
pub struct Program {
pub func: Vec<Function>,
@ -97,6 +99,7 @@ pub enum Statement {
If(Expression, Box<Statement>, Option<Box<Statement>>),
While(Expression, Box<Statement>),
For(Variable, Expression, Box<Statement>),
Match(Expression, Vec<MatchArm>),
Break,
Continue,
Exp(Expression),

6
src/parser/parser.rs

@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::lexer::Position;
use crate::lexer::Keyword;
use crate::lexer::{Token, TokenKind};
use crate::parser::infer::infer;
@ -126,6 +127,11 @@ impl Parser {
}
}
pub(super) fn make_error_msg(&mut self, pos: Position, msg: String) -> String {
let pos_string = format!("{}:{}", pos.line, pos.offset);
format!("ERROR: {}\nAt {}", msg, pos_string)
}
pub(super) fn prev(&mut self) -> Option<Token> {
self.prev.clone()
}

42
src/parser/rules.rs

@ -165,6 +165,7 @@ impl Parser {
TokenKind::Keyword(Keyword::Break) => self.parse_break(),
TokenKind::Keyword(Keyword::Continue) => self.parse_continue(),
TokenKind::Keyword(Keyword::For) => self.parse_for_loop(),
TokenKind::Keyword(Keyword::Match) => self.parse_match_statement(),
TokenKind::Identifier(_) => {
let ident = self.match_identifier()?;
let expr = if self.peek_token(TokenKind::Dot).is_ok() {
@ -457,6 +458,47 @@ impl Parser {
))
}
fn parse_match_statement(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::Match)?;
let subject = self.parse_expression()?;
self.match_token(TokenKind::CurlyBracesOpen)?;
let mut arms: Vec<MatchArm> = Vec::new();
// Used to mitigate multiple default cases were defined
let mut has_default = false;
loop {
let next = self.peek()?;
match next.kind {
TokenKind::Literal(_) | TokenKind::Identifier(_) => {
arms.push(self.parse_match_arm()?)
}
TokenKind::Keyword(Keyword::Default) => {
if has_default {
return Err(self.make_error_msg(
next.pos,
"Multiple defaults are not allowed".to_string(),
));
}
has_default = true;
arms.push(self.parse_match_arm()?);
}
TokenKind::CurlyBracesClose => break,
_ => return Err(self.make_error_msg(next.pos, "Illegal token".to_string()))
}
}
self.match_token(TokenKind::CurlyBracesClose)?;
Ok(Statement::Match(subject, arms))
}
fn parse_match_arm(&mut self) -> Result<MatchArm, String> {
let expr = self.parse_expression()?;
self.match_token(TokenKind::ArrowRight)?;
let statement = self.parse_statement()?;
Ok((expr, statement))
}
fn parse_conditional_statement(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::If)?;
let condition = self.parse_expression()?;

Loading…
Cancel
Save