A big refactor, step 2.1

This commit is contained in:
2023-11-10 15:04:42 -06:00
parent 8bdf4ba956
commit ce12cf4974
7 changed files with 185 additions and 135 deletions
+37
View File
@@ -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() })
);
}
}
@@ -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()
})
);
}
}
@@ -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![],
})
);
}
}
+6 -1
View File
@@ -1,4 +1,9 @@
pub mod declaration; pub mod declaration;
mod global; mod global;
mod r#const; mod r#const;
mod function; mod function;
mod function_prototype;
mod statement;
mod asm;
mod r#return;
mod assignment;
+34
View File
@@ -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()))))
);
}
}
@@ -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!(),
}
}
}
+1 -134
View File
@@ -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 { 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] #[test]
fn parse_var_decl() { fn parse_var_decl() {
assert_eq!( 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] #[test]
fn parse_program() { fn parse_program() {
let prog = Program::from_str("global foo; const blah = 3;").unwrap(); let prog = Program::from_str("global foo; const blah = 3;").unwrap();