From 0627c3c133c850fb8d2f03e573c0b278aba195ee Mon Sep 17 00:00:00 2001 From: Elijah Mirecki Date: Sun, 16 Jan 2022 13:29:44 -0500 Subject: [PATCH] refs #30. Parse #define statements --- src/ast.rs | 9 +++++++ src/parser.rs | 67 ++++++++++++++++++++++++++++++++++++++++++------ src/tokenizer.rs | 5 ++++ 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/src/ast.rs b/src/ast.rs index 26b4c29..1be595e 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -48,6 +48,7 @@ pub struct RootStatements { pub functions: Vec, pub variables: Vec, pub imports: Vec, + pub defines: Vec, } impl RootStatements { @@ -56,6 +57,7 @@ impl RootStatements { functions: vec!(), variables: vec!(), imports: vec!(), + defines: vec!(), } } } @@ -77,6 +79,13 @@ pub struct RSImport { pub path: String, } +pub struct RSDefine { + pub pos: Pos, + pub name: String, + pub args: Vec, + pub body: Expr, +} + #[derive(Debug)] pub enum Statement { // Statement representing executing a single expr diff --git a/src/parser.rs b/src/parser.rs index 52e1f36..1238dde 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -203,7 +203,7 @@ fn parse_var_entry(c: &mut ParseContext, name: String) -> Result { } } -// Expects the @import token to have been parsed +// Expects the #import token to have been parsed fn parse_import( c: &mut ParseContext ) -> Result { @@ -221,10 +221,51 @@ fn parse_import( } } -// Parses everything after the name of a function -fn parse_fun( - c: &mut ParseContext, pos: Pos, name: String -) -> Result { +// Expects the #define token to have been parsed +fn parse_define( + c: &mut ParseContext +) -> Result { + let pos = c.pos(); + let name = match pop_tok(c)? { + (_, Token::Id(id)) => id, + (pos, tok) => return CompErr::err(&pos, format!( + "ID expected. {:?} given", tok)), + }; + + // Handles cases with ambiguous parens + let next1 = pop_tok(c)?; + let next2 = pop_tok(c)?; + let should_parse_args = if next1.1 == Token::LParen { + if let (_, Token::Id(_)) = next2 { + true + } else { + next2.1 == Token::RParen + } + } else { + false + }; + push_tok(c, next2); + push_tok(c, next1); + + let args = if should_parse_args { + parse_args(c)? + } else { + vec!() + }; + let body = parse_expr(c)?; + parse_tok(c, Token::Semicolon)?; + + Ok(RSDefine { + pos, + name, + args, + body, + }) +} + +fn parse_args( + c: &mut ParseContext +) -> Result, CompErr> { parse_tok(c, Token::LParen)?; let mut args = Vec::::new(); @@ -256,10 +297,18 @@ fn parse_fun( &pos, format!("Unexpected token: {:?}", other)), } } + + Ok(args) +} + +// Parses everything after the name of a function +fn parse_fun( + c: &mut ParseContext, pos: Pos, name: String +) -> Result { Ok(RSFunction { - pos: pos, - name: name, - args: args, + pos, + name, + args: parse_args(c)?, body: parse_statement(c)?, }) } @@ -862,6 +911,8 @@ fn parse_content( }, (_, Token::Import) => root_statements.imports.push(parse_import(&mut c)?), + (_, Token::Define) => + root_statements.defines.push(parse_define(&mut c)?), (_, Token::Eof) => break, (pos, tok) => return CompErr::err(&pos, format!( "Expected id. {:?} found", tok)), diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 791cc6c..ed96795 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -14,6 +14,7 @@ pub enum Token { Char(Vec), Int(i64), Import, + Define, Return, Auto, Case, @@ -184,6 +185,10 @@ fn get_tok_meta(c: &mut ParseContext) -> Result<(Pos, Token), CompErr> { c.offset += 1 + next_word.len(); Ok((c.pos(), Token::Import)) }, + "define" => { + c.offset += 1 + next_word.len(); + Ok((c.pos(), Token::Define)) + }, other => { CompErr::err(&pos, format!("Invalid token: #{}", other)) },