use super::{CompilerError, Parser, Position}; type Ident = String; #[derive(Debug)] pub struct ParsedReid(pub Expression); #[derive(Debug)] pub enum Statement { LetStatement(Position, Ident, Box), ExprStatement(Position, Expression), } impl Statement { pub fn parse(parser: &mut Parser) -> Result { let pos = parser.pos(); if let Some(_) = parser.expect("let").get() { let ident = parser .expect_ident() .get_or(CompilerError::ExpectedIdent(pos))?; parser .expect("=") .get_or(CompilerError::ExpectedToken(pos, '='))?; match Expression::parse(parser) { Ok(expr) => { parser .expect(";") .get_or(CompilerError::ExpectedToken(pos, ';'))?; Ok(Statement::LetStatement(pos, ident, Box::new(expr))) } Err(err) => Err(CompilerError::ExpectedExpression(pos, Some(Box::new(err)))), } } else { match Expression::parse(parser) { Ok(expr) => { let statement = Statement::ExprStatement(pos, expr); parser .expect(";") .get_or(CompilerError::ExpectedToken(pos, ';'))?; Ok(statement) } Err(err) => Err(CompilerError::ExpectedStatement(pos, Some(Box::new(err)))), } } } } #[derive(Debug)] pub enum Expression { BlockExpr(Position, Vec), ValueRef(Position, Pattern), } impl Expression { pub fn parse(parser: &mut Parser) -> Result { let begin_pos = parser.pos(); let expect = parser.expect("{"); if let Some(_) = expect.get() { let mut statement_list = Vec::new(); while { match Statement::parse(parser) { Ok(exp) => { statement_list.push(exp); true } Err(_) => false, } } {} if let Some(_) = parser.expect("}").get() { Ok(Expression::BlockExpr(begin_pos, statement_list)) } else { Err(CompilerError::ExpectedToken(parser.pos(), '}')) } } else if let Ok(pattern) = Pattern::parse(parser) { Ok(Expression::ValueRef(begin_pos, pattern)) } else { Err(CompilerError::ExpectedExpression(begin_pos, None)) } } } #[derive(Debug)] pub enum Pattern { IdentPattern(Position, Ident), LiteralPattern(Position, LiteralPattern), } impl Pattern { fn parse(parser: &mut Parser) -> Result { let pos = parser.pos(); if let Some(string) = parser.expect_string_lit().get() { Ok(Pattern::LiteralPattern( pos, LiteralPattern::StringLit(string), )) } else if let Some(ident) = parser.expect_ident().get() { Ok(Pattern::IdentPattern(pos, ident)) } else { Err(CompilerError::ExpectedPattern(pos)) } } } #[derive(Debug)] pub enum LiteralPattern { StringLit(String), }