diff --git a/src/ast.rs b/src/ast.rs index 5087dd6..4441d32 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,84 +1,102 @@ +#![allow(dead_code)] + +/// imagine interning or something here +pub type Symbol = String; + +#[derive(Debug, Clone, PartialEq)] +pub struct Program(pub Block); + +#[derive(Debug, Clone, PartialEq)] pub struct Block(pub Vec); +#[derive(Debug, Clone, PartialEq)] pub enum Stmt { - VariableDecl(VariableDecl), + Declaration(Declaration), Assignment(Assignment), FnDecl(FnDecl), + If(IfStmt), + Loop(Block), + While(WhileStmt), Break, Return(Option), - Conditional(Conditional), - Loop(Block), - WhileLoop(WhileLoop), - ForLoop(Box), Expr(Expr), } -pub struct VariableDecl { - name: String, - init: Option, +#[derive(Debug, Clone, PartialEq)] +pub struct Declaration { + name: Symbol, + init: Expr, } +#[derive(Debug, Clone, PartialEq)] pub struct Assignment { - pub lhs: Expr, + pub lhs: Symbol, pub rhs: Expr, } +#[derive(Debug, Clone, PartialEq)] pub struct FnDecl { - pub name: String, - pub params: Vec, + pub name: Symbol, + pub params: Vec, pub body: Block, } -pub struct Conditional { +#[derive(Debug, Clone, PartialEq)] +pub struct IfStmt { pub condition: Expr, pub body: Block, - pub else_block: Option, + pub else_part: Box, } -pub struct WhileLoop { +#[derive(Debug, Clone, PartialEq)] +pub enum ElsePart { + Else(Block), + ElseIf(IfStmt), +} + +#[derive(Debug, Clone, PartialEq)] +pub struct WhileStmt { pub cond: Expr, pub body: Block, } -pub struct ForLoop { - pub init: Stmt, - pub cond: Expr, - pub post: Stmt, - pub body: Block, -} - +#[derive(Debug, Clone, PartialEq)] pub enum Expr { Literal(Literal), UnaryOp, BinaryOp, - Call, } +#[derive(Debug, Clone, PartialEq)] pub enum Literal { String(String), Number(f64), Array(Vec), - Object, // todo + Object, Boolean(bool), Null, } +#[derive(Debug, Clone, PartialEq)] pub struct UnaryOp { pub expr: Expr, pub kind: UnaryOpKind, } +#[derive(Debug, Clone, PartialEq)] pub enum UnaryOpKind { Not, Neg, } +#[derive(Debug, Clone, PartialEq)] pub struct BinaryOp { pub lhs: Expr, pub rhs: Expr, pub kind: BinaryOpKind, } +#[derive(Debug, Clone, PartialEq)] pub enum BinaryOpKind { And, Or, @@ -95,6 +113,7 @@ pub enum BinaryOpKind { Mod, } +#[derive(Debug, Clone, PartialEq)] pub enum Call { Function(Expr, Vec), Field(Expr, Vec), diff --git a/src/lex.rs b/src/lex.rs index 1d82fb8..5dc5496 100644 --- a/src/lex.rs +++ b/src/lex.rs @@ -48,6 +48,8 @@ pub enum TokenType<'code> { // ident Ident(&'code str), // punctuation + /// ; + Semi, /// + Plus, /// - diff --git a/src/lib.rs b/src/lib.rs index ca2be1e..0ec90d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,19 +8,23 @@ pub fn run_program(program: &str) { let lexer = lex::Lexer::lex(program); let (success, errors) = lexer.partition::, _>(|result| result.is_ok()); - if errors.is_empty() { - println!( - "{:#?}", - success - .into_iter() - .map(Result::unwrap) - .map(|token| token.kind) - .collect::>() - ); - } else { - errors - .into_iter() - .map(Result::unwrap_err) - .for_each(|err| crate::errors::display_error(program, err)); - } + // terrible, but works + let tokens = success.into_iter().collect::>(); + let _ast = parse::parse(tokens.unwrap()); + + // if errors.is_empty() { + // println!( + // "{:#?}", + // success + // .into_iter() + // .map(Result::unwrap) + // .map(|token| token.kind) + // .collect::>() + // ); + // } else { + // errors + // .into_iter() + // .map(Result::unwrap_err) + // .for_each(|err| crate::errors::display_error(program, err)); + // } } diff --git a/src/parse.rs b/src/parse.rs index e69de29..495471e 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -0,0 +1,100 @@ +#![allow(dead_code)] + +use crate::ast::*; +use crate::lex::{Token, TokenType}; +use std::iter::Peekable; + +pub fn parse(tokens: Vec) -> Result { + let mut parser = Parser { + tokens: tokens.into_iter().peekable(), + }; + let program = parser.program()?; + Ok(program) +} + +#[derive(Debug)] +struct Parser<'code> { + tokens: Peekable>>, +} + +type ParseResult<'code, T> = Result>; + +impl<'code> Parser<'code> { + fn program(&mut self) -> ParseResult<'code, Program> { + Ok(Program(self.block()?)) + } + + fn block(&mut self) -> ParseResult<'code, Block> { + let mut stmts = Vec::new(); + loop { + if let Some(Token { + kind: TokenType::BraceC, + .. + }) = self.peek() + { + let _ = self.next(); + return Ok(Block(stmts)); + } + let stmt = self.statement()?; + stmts.push(stmt); + } + } + + fn statement(&mut self) -> ParseResult<'code, Stmt> { + let expr = self.expression()?; + self.expect(TokenType::Semi); + Ok(Stmt::Expr(expr)) + } + + fn declaration(&mut self) -> ParseResult<'code, Declaration> { + todo!() + } + + fn assignment(&mut self) -> ParseResult<'code, Assignment> { + todo!() + } + + fn fn_decl(&mut self) -> ParseResult<'code, FnDecl> { + todo!() + } + + fn if_stmt(&mut self) -> ParseResult<'code, IfStmt> { + todo!() + } + + fn loop_stmt(&mut self) -> ParseResult<'code, Block> { + todo!() + } + + fn expression(&mut self) -> ParseResult<'code, Expr> { + todo!() + } + + // helpers + + fn next(&mut self) -> Option> { + self.tokens.next() + } + + fn peek(&mut self) -> Option<&Token<'code>> { + self.tokens.peek() + } + + fn expect(&mut self, kind: TokenType<'code>) -> ParseResult<'code, ()> { + if let Some(token) = self.next() { + if token.kind == kind { + Ok(()) + } else { + Err(ParseErr::MismatchedKind { expected: kind }) + } + } else { + Err(ParseErr::UnexpectedEOF { expected: kind }) + } + } +} + +#[derive(Debug)] +pub enum ParseErr<'code> { + MismatchedKind { expected: TokenType<'code> }, + UnexpectedEOF { expected: TokenType<'code> }, +}