A big refactor, step 2.1
This commit is contained in:
@@ -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![],
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,9 @@
|
||||
pub mod declaration;
|
||||
mod global;
|
||||
mod r#const;
|
||||
mod function;
|
||||
mod function;
|
||||
mod function_prototype;
|
||||
mod statement;
|
||||
mod asm;
|
||||
mod r#return;
|
||||
mod assignment;
|
||||
@@ -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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user