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;
|
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;
|
||||||
@@ -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 {
|
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();
|
||||||
|
|||||||
Reference in New Issue
Block a user