From ce12cf4974f452b0638b8c87fc836e069b25a699 Mon Sep 17 00:00:00 2001 From: Ross Andrews Date: Fri, 10 Nov 2023 15:04:42 -0600 Subject: [PATCH] A big refactor, step 2.1 --- forge_core/src/parser/ast_nodes/asm.rs | 37 +++++ forge_core/src/parser/ast_nodes/assignment.rs | 52 +++++++ .../parser/ast_nodes/function_prototype.rs | 35 +++++ forge_core/src/parser/ast_nodes/mod.rs | 7 +- forge_core/src/parser/ast_nodes/return.rs | 34 +++++ forge_core/src/parser/ast_nodes/statement.rs | 20 +++ forge_core/src/parser/mod.rs | 135 +----------------- 7 files changed, 185 insertions(+), 135 deletions(-) create mode 100644 forge_core/src/parser/ast_nodes/asm.rs create mode 100644 forge_core/src/parser/ast_nodes/assignment.rs create mode 100644 forge_core/src/parser/ast_nodes/function_prototype.rs create mode 100644 forge_core/src/parser/ast_nodes/return.rs create mode 100644 forge_core/src/parser/ast_nodes/statement.rs diff --git a/forge_core/src/parser/ast_nodes/asm.rs b/forge_core/src/parser/ast_nodes/asm.rs new file mode 100644 index 0000000..5d2530d --- /dev/null +++ b/forge_core/src/parser/ast_nodes/asm.rs @@ -0,0 +1,37 @@ +use crate::ast::{Asm, Expr}; +use crate::parser::{AstNode, PestRule, Pair}; + +impl AstNode for Asm { + const RULE: PestRule = PestRule::asm; + fn from_pair(pair: Pair) -> Self { + let mut args = Vec::new(); + let mut body = None; + for p in pair.into_inner() { + match p.as_rule() { + PestRule::expr => args.push(Expr::from_pair(p).into()), + PestRule::asm_body => body = Some(String::from(p.as_str().trim())), + _ => unreachable!() + } + } + Self { args, body: body.unwrap() } + } +} + +#[cfg(test)] +mod test { + use crate::parser::Parseable; + use super::*; + + #[test] + fn parse_asm() { + assert_eq!( + Asm::from_str("asm { push 34 }"), + Ok(Asm { args: vec![], body: "push 34".into() }) + ); + + assert_eq!( + Asm::from_str("asm (&a) { swap 34\nstorew }"), + Ok(Asm { args: vec![Expr::Address("a".into()).into()], body: "swap 34\nstorew".into() }) + ); + } +} \ No newline at end of file diff --git a/forge_core/src/parser/ast_nodes/assignment.rs b/forge_core/src/parser/ast_nodes/assignment.rs new file mode 100644 index 0000000..e25d5c2 --- /dev/null +++ b/forge_core/src/parser/ast_nodes/assignment.rs @@ -0,0 +1,52 @@ +use crate::ast::{Assignment, Expr}; +use crate::parser::{AstNode, Pair, PestRule}; + +impl AstNode for Assignment { + const RULE: PestRule = PestRule::assignment; + fn from_pair(pair: Pair) -> Self { + let mut pairs = pair.into_inner(); + let lvalue = Expr::from_pair(pairs.next().unwrap()).into(); + let rvalue = Expr::from_pair(pairs.next().unwrap()); + Self { lvalue, rvalue } + } +} + +#[cfg(test)] +mod test { + use crate::ast::Statement; + use crate::parser::Parseable; + use super::*; + + #[test] + fn parse_assignment() { + assert_eq!( + Statement::from_str("foo = 7;"), + Ok(Statement::Assignment(Assignment { + lvalue: "foo".into(), + rvalue: 7.into(), + })) + ); + } + + #[test] + fn subscript_assignment() { + assert_eq!( + Assignment::from_str("foo[45] = 7"), + Ok(Assignment { + lvalue: Expr::Subscript("foo".into(), 45.into()).into(), + rvalue: 7.into(), + }) + ); + } + + #[test] + fn pointer_assignment() { + assert_eq!( + Assignment::from_str("*foo = 12"), + Ok(Assignment { + lvalue: Expr::Deref("foo".into()).into(), + rvalue: 12.into() + }) + ); + } +} \ No newline at end of file diff --git a/forge_core/src/parser/ast_nodes/function_prototype.rs b/forge_core/src/parser/ast_nodes/function_prototype.rs new file mode 100644 index 0000000..14199d1 --- /dev/null +++ b/forge_core/src/parser/ast_nodes/function_prototype.rs @@ -0,0 +1,35 @@ +use crate::ast::FunctionPrototype; +use crate::parser::{AstNode, Pair, PestRule}; + +impl AstNode for FunctionPrototype { + const RULE: PestRule = PestRule::function_prototype; + fn from_pair(pair: Pair<'_>) -> Self { + let mut inner = pair.into_inner().peekable(); + let name = String::from(inner.next().unwrap().as_str()); + let args: Vec<_> = inner + .next() + .unwrap() + .into_inner() + .map(|p| String::from(p.as_str())) + .collect(); + + Self { name, args } + } +} + +#[cfg(test)] +mod test { + use crate::parser::Parseable; + use super::*; + + #[test] + fn parse_fn_prototype() { + assert_eq!( + FunctionPrototype::from_str("fn foo();"), + Ok(FunctionPrototype { + name: "foo".into(), + args: vec![], + }) + ); + } +} \ No newline at end of file diff --git a/forge_core/src/parser/ast_nodes/mod.rs b/forge_core/src/parser/ast_nodes/mod.rs index 8ae9454..1614792 100644 --- a/forge_core/src/parser/ast_nodes/mod.rs +++ b/forge_core/src/parser/ast_nodes/mod.rs @@ -1,4 +1,9 @@ pub mod declaration; mod global; mod r#const; -mod function; \ No newline at end of file +mod function; +mod function_prototype; +mod statement; +mod asm; +mod r#return; +mod assignment; \ No newline at end of file diff --git a/forge_core/src/parser/ast_nodes/return.rs b/forge_core/src/parser/ast_nodes/return.rs new file mode 100644 index 0000000..c8c4cc8 --- /dev/null +++ b/forge_core/src/parser/ast_nodes/return.rs @@ -0,0 +1,34 @@ +use crate::ast::{Expr, Return}; +use crate::parser::{AstNode, Pair, PestRule}; + +impl AstNode for Return { + const RULE: PestRule = PestRule::return_stmt; + fn from_pair(pair: Pair) -> Self { + pair.into_inner() + .next() + .map_or(Self(None), |expr| Self(Some(Expr::from_pair(expr)))) + } +} + +#[cfg(test)] +mod test { + use crate::ast::Statement; + use crate::parser::Parseable; + use super::*; + + #[test] + fn parse_return() { + assert_eq!( + Statement::from_str("return;"), + Ok(Statement::Return(Return(None))) + ); + } + + #[test] + fn parse_return_with_value() { + assert_eq!( + Statement::from_str("return 17;"), + Ok(Statement::Return(Return(Some(17.into())))) + ); + } +} \ No newline at end of file diff --git a/forge_core/src/parser/ast_nodes/statement.rs b/forge_core/src/parser/ast_nodes/statement.rs new file mode 100644 index 0000000..0c5a8ea --- /dev/null +++ b/forge_core/src/parser/ast_nodes/statement.rs @@ -0,0 +1,20 @@ +use crate::ast::*; +use crate::parser::{AstNode, Pair, PairExt, PestRule}; + +impl AstNode for Statement { + const RULE: PestRule = PestRule::statement; + fn from_pair(pair: Pair) -> Self { + let pair = pair.first(); + match pair.as_rule() { + PestRule::return_stmt => Self::Return(Return::from_pair(pair)), + PestRule::assignment => Self::Assignment(Assignment::from_pair(pair)), + PestRule::expr => Self::Expr(Expr::from_pair(pair)), + PestRule::var_decl => Self::VarDecl(VarDecl::from_pair(pair)), + PestRule::conditional => Self::Conditional(Conditional::from_pair(pair)), + PestRule::while_loop => Self::WhileLoop(WhileLoop::from_pair(pair)), + PestRule::repeat_loop => Self::RepeatLoop(RepeatLoop::from_pair(pair)), + PestRule::asm => Self::Asm(Asm::from_pair(pair)), + _ => unreachable!(), + } + } +} \ No newline at end of file diff --git a/forge_core/src/parser/mod.rs b/forge_core/src/parser/mod.rs index b8f133b..8edf413 100644 --- a/forge_core/src/parser/mod.rs +++ b/forge_core/src/parser/mod.rs @@ -87,83 +87,14 @@ mod ast_nodes; /////////////////////////////////////////////////////////////////////////////////////////// -impl AstNode for FunctionPrototype { - const RULE: PestRule = PestRule::function_prototype; - fn from_pair(pair: Pair<'_>) -> Self { - let mut inner = pair.into_inner().peekable(); - let name = String::from(inner.next().unwrap().as_str()); - let args: Vec<_> = inner - .next() - .unwrap() - .into_inner() - .map(|p| String::from(p.as_str())) - .collect(); - - Self { name, args } - } -} +/////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// -impl AstNode for Statement { - const RULE: PestRule = PestRule::statement; - fn from_pair(pair: Pair) -> Self { - let pair = pair.first(); - match pair.as_rule() { - PestRule::return_stmt => Self::Return(Return::from_pair(pair)), - PestRule::assignment => Self::Assignment(Assignment::from_pair(pair)), - PestRule::expr => Self::Expr(Expr::from_pair(pair)), - PestRule::var_decl => Self::VarDecl(VarDecl::from_pair(pair)), - PestRule::conditional => Self::Conditional(Conditional::from_pair(pair)), - PestRule::while_loop => Self::WhileLoop(WhileLoop::from_pair(pair)), - PestRule::repeat_loop => Self::RepeatLoop(RepeatLoop::from_pair(pair)), - PestRule::asm => Self::Asm(Asm::from_pair(pair)), - _ => unreachable!(), - } - } -} - /////////////////////////////////////////////////////////////////////////////////////////// -impl AstNode for Asm { - const RULE: PestRule = PestRule::asm; - fn from_pair(pair: Pair) -> Self { - let mut args = Vec::new(); - let mut body = None; - for p in pair.into_inner() { - match p.as_rule() { - PestRule::expr => args.push(Expr::from_pair(p).into()), - PestRule::asm_body => body = Some(String::from(p.as_str().trim())), - _ => unreachable!() - } - } - Self { args, body: body.unwrap() } - } -} - /////////////////////////////////////////////////////////////////////////////////////////// -impl AstNode for Return { - const RULE: PestRule = PestRule::return_stmt; - fn from_pair(pair: Pair) -> Self { - pair.into_inner() - .next() - .map_or(Self(None), |expr| Self(Some(Expr::from_pair(expr)))) - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// - -impl AstNode for Assignment { - const RULE: PestRule = PestRule::assignment; - fn from_pair(pair: Pair) -> Self { - let mut pairs = pair.into_inner(); - let lvalue = Expr::from_pair(pairs.next().unwrap()).into(); - let rvalue = Expr::from_pair(pairs.next().unwrap()); - Self { lvalue, rvalue } - } -} - /////////////////////////////////////////////////////////////////////////////////////////// impl AstNode for VarDecl { @@ -520,46 +451,6 @@ mod test { ); } - #[test] - fn parse_return() { - assert_eq!( - Statement::from_str("return;"), - Ok(Statement::Return(Return(None))) - ); - - assert_eq!( - Statement::from_str("return 17;"), - Ok(Statement::Return(Return(Some(17.into())))) - ); - } - - #[test] - fn parse_assignment() { - assert_eq!( - Statement::from_str("foo = 7;"), - Ok(Statement::Assignment(Assignment { - lvalue: "foo".into(), - rvalue: 7.into(), - })) - ); - - assert_eq!( - Assignment::from_str("foo[45] = 7"), - Ok(Assignment { - lvalue: Expr::Subscript("foo".into(), 45.into()).into(), - rvalue: 7.into(), - }) - ); - - assert_eq!( - Assignment::from_str("*foo = 12"), - Ok(Assignment { - lvalue: Expr::Deref("foo".into()).into(), - rvalue: 12.into() - }) - ); - } - #[test] fn parse_var_decl() { assert_eq!( @@ -658,30 +549,6 @@ mod test { }); } - #[test] - fn parse_asm() { - assert_eq!( - Asm::from_str("asm { push 34 }"), - Ok(Asm { args: vec![], body: "push 34".into() }) - ); - - assert_eq!( - Asm::from_str("asm (&a) { swap 34\nstorew }"), - Ok(Asm { args: vec![Expr::Address("a".into()).into()], body: "swap 34\nstorew".into() }) - ); - } - - #[test] - fn parse_fn_prototype() { - assert_eq!( - FunctionPrototype::from_str("fn foo();"), - Ok(FunctionPrototype { - name: "foo".into(), - args: vec![], - }) - ); - } - #[test] fn parse_program() { let prog = Program::from_str("global foo; const blah = 3;").unwrap();