Much better working grammar, more fixed tests
This commit is contained in:
+73
-47
@@ -80,7 +80,7 @@ pub struct Assignment {
|
|||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub enum Lvalue {
|
pub enum Lvalue {
|
||||||
ArrayRef(ArrayRef),
|
ArrayRef(String, Expr),
|
||||||
Name(String),
|
Name(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,62 +150,78 @@ pub enum Prefix {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Suffix {
|
pub enum Suffix {
|
||||||
Subscript(Expr),
|
Subscript(BoxExpr),
|
||||||
Arglist(Vec<Rvalue>),
|
Arglist(Vec<Rvalue>),
|
||||||
Member(String),
|
Member(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Expr {
|
pub enum Expr {
|
||||||
pub lhs: Val,
|
Val(Val),
|
||||||
pub op: Option<Operator>,
|
Prefix(Prefix, BoxExpr),
|
||||||
pub rhs: Option<BoxExpr>,
|
Suffix(BoxExpr, Suffix),
|
||||||
|
Infix(BoxExpr, Operator, BoxExpr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[derive(PartialEq, Clone, Debug)]
|
||||||
|
// pub struct Expr {
|
||||||
|
// pub lhs: Val,
|
||||||
|
// pub prefix: Vec<Prefix>,
|
||||||
|
// pub suffix: Vec<Suffix>,
|
||||||
|
// pub op: Option<Operator>,
|
||||||
|
// pub rhs: Option<BoxExpr>,
|
||||||
|
// }
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub enum Val {
|
pub enum Val {
|
||||||
Number(i32, Vec<Prefix>, Vec<Suffix>),
|
Number(i32),
|
||||||
Name(String, Vec<Prefix>, Vec<Suffix>),
|
Name(String),
|
||||||
Expr(BoxExpr, Vec<Prefix>, Vec<Suffix>),
|
Expr(BoxExpr),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Val {
|
// impl Val {
|
||||||
pub fn is_simple(&self) -> bool {
|
// pub fn is_simple(&self) -> bool {
|
||||||
if let Self::Expr(expr, pre, suf) = &self {
|
// if let Self::Expr(expr, pre, suf) = &self {
|
||||||
pre.is_empty() && suf.is_empty() && expr.0.op.is_none()
|
// pre.is_empty() && suf.is_empty() && expr.0.op.is_none()
|
||||||
} else {
|
// } else {
|
||||||
false
|
// false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
pub fn inner_expr(self) -> Option<Expr> {
|
// pub fn inner_expr(self) -> Option<Expr> {
|
||||||
if let Self::Expr(expr, _, _) = self {
|
// if let Self::Expr(expr, _, _) = self {
|
||||||
Some(expr.into())
|
// Some(expr.into())
|
||||||
} else { None }
|
// } else { None }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl From<i32> for Val {
|
impl From<i32> for Val {
|
||||||
fn from(val: i32) -> Self {
|
fn from(val: i32) -> Self {
|
||||||
Self::Number(val, vec![], vec![])
|
Self::Number(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&str> for Val {
|
impl From<&str> for Val {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
Self::Name(String::from(s), vec![], vec![])
|
Self::Name(String::from(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Expr> for Val {
|
impl From<Expr> for Val {
|
||||||
fn from(value: Expr) -> Self {
|
fn from(value: Expr) -> Self {
|
||||||
Self::Expr(value.into(), vec![], vec![])
|
Self::Expr(value.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BoxExpr> for Val {
|
impl From<BoxExpr> for Val {
|
||||||
fn from(value: BoxExpr) -> Self {
|
fn from(value: BoxExpr) -> Self {
|
||||||
Self::Expr(value, vec![], vec![])
|
Self::Expr(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Val> for BoxExpr {
|
||||||
|
fn from(value: Val) -> Self {
|
||||||
|
Self::from(Expr::from(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,11 +231,7 @@ pub struct BoxExpr(pub Box<Expr>);
|
|||||||
|
|
||||||
impl From<Val> for Expr {
|
impl From<Val> for Expr {
|
||||||
fn from(value: Val) -> Self {
|
fn from(value: Val) -> Self {
|
||||||
Self {
|
Self::Val(value)
|
||||||
lhs: value,
|
|
||||||
op: None,
|
|
||||||
rhs: None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,29 +242,43 @@ impl From<i32> for BoxExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<Expr> for BoxExpr {
|
impl From<Expr> for BoxExpr {
|
||||||
fn from(val: Expr) -> Self {
|
fn from(expr: Expr) -> Self {
|
||||||
BoxExpr(Box::from(val))
|
BoxExpr(Box::from(expr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for BoxExpr {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
Expr::Val(Val::Name(String::from(value))).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BoxExpr> for Expr {
|
impl From<BoxExpr> for Expr {
|
||||||
fn from(val: BoxExpr) -> Self {
|
fn from(expr: BoxExpr) -> Self {
|
||||||
*(val.0)
|
*(expr.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i32> for Expr {
|
impl From<i32> for Expr {
|
||||||
fn from(value: i32) -> Self {
|
fn from(value: i32) -> Self {
|
||||||
Self {
|
Self::Val(Val::Number(value))
|
||||||
lhs: Val::Number(value, vec![], vec![]),
|
|
||||||
op: None,
|
|
||||||
rhs: None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
impl From<&str> for Expr {
|
||||||
pub struct ArrayRef {
|
fn from(value: &str) -> Self {
|
||||||
pub name: String,
|
Self::Val(Val::Name(String::from(value)))
|
||||||
pub subscript: BoxExpr,
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i32> for Rvalue {
|
||||||
|
fn from(value: i32) -> Self {
|
||||||
|
Self::Expr(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Rvalue {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
Self::String(value.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ impl Compilable for Lvalue {
|
|||||||
let global_scope = &state.global_scope;
|
let global_scope = &state.global_scope;
|
||||||
let mut sig = sig.expect("lvalue outside a function");
|
let mut sig = sig.expect("lvalue outside a function");
|
||||||
match self {
|
match self {
|
||||||
Lvalue::ArrayRef(_) => todo!("Arrays are not implemented yet"),
|
Lvalue::ArrayRef(_, _) => todo!("Arrays are not implemented yet"),
|
||||||
Lvalue::Name(name) => {
|
Lvalue::Name(name) => {
|
||||||
if let Some(var) = lookup(&name, global_scope, &sig.local_scope) {
|
if let Some(var) = lookup(&name, global_scope, &sig.local_scope) {
|
||||||
match var {
|
match var {
|
||||||
|
|||||||
+158
-148
@@ -1,4 +1,4 @@
|
|||||||
use pest::pratt_parser::PrattParser;
|
use pest::pratt_parser::{Op, PrattParser};
|
||||||
use pest::Parser;
|
use pest::Parser;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
@@ -23,6 +23,7 @@ lazy_static::lazy_static! {
|
|||||||
.op(Op::infix(add, Left) | Op::infix(sub, Left))
|
.op(Op::infix(add, Left) | Op::infix(sub, Left))
|
||||||
.op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(modulus, Left))
|
.op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(modulus, Left))
|
||||||
.op(Op::prefix(Rule::prefix))
|
.op(Op::prefix(Rule::prefix))
|
||||||
|
.op(Op::postfix(Rule::suffix))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,12 +325,13 @@ impl AstNode for Assignment {
|
|||||||
const RULE: Rule = Rule::assignment;
|
const RULE: Rule = Rule::assignment;
|
||||||
fn from_pair(pair: Pair) -> Self {
|
fn from_pair(pair: Pair) -> Self {
|
||||||
let mut pairs = pair.into_inner();
|
let mut pairs = pair.into_inner();
|
||||||
let lvalue_pair = pairs.next().unwrap().first();
|
let lvalue_pair = pairs.next().unwrap();
|
||||||
let lvalue = match lvalue_pair.as_rule() {
|
let lvalue = Lvalue::from_pair(lvalue_pair);
|
||||||
//Rule::arrayref => Lvalue::ArrayRef(ArrayRef::from_pair(lvalue_pair)),
|
// let lvalue = match lvalue_pair.as_rule() {
|
||||||
Rule::name => Lvalue::Name(String::from(lvalue_pair.as_str())),
|
// Rule::subscript => Lvalue::ArrayRef(Subscript::from_pair(lvalue_pair)),
|
||||||
_ => unreachable!(),
|
// Rule::name => Lvalue::Name(String::from(lvalue_pair.as_str())),
|
||||||
};
|
// _ => unreachable!(),
|
||||||
|
// };
|
||||||
let rvalue = Rvalue::from_pair(pairs.next().unwrap());
|
let rvalue = Rvalue::from_pair(pairs.next().unwrap());
|
||||||
Self { lvalue, rvalue }
|
Self { lvalue, rvalue }
|
||||||
}
|
}
|
||||||
@@ -337,6 +339,18 @@ impl AstNode for Assignment {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
impl AstNode for Lvalue {
|
||||||
|
const RULE: Rule = Rule::lvalue;
|
||||||
|
fn from_pair(pair: Pair) -> Self {
|
||||||
|
let mut pairs = pair.into_inner();
|
||||||
|
let name = pairs.next().unwrap().as_str();
|
||||||
|
pairs.next().map_or(Lvalue::Name(String::from(name)),
|
||||||
|
|subscript| Lvalue::ArrayRef(String::from(name), Expr::from_pair(subscript.first())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl AstNode for Rvalue {
|
impl AstNode for Rvalue {
|
||||||
const RULE: Rule = Rule::rvalue;
|
const RULE: Rule = Rule::rvalue;
|
||||||
|
|
||||||
@@ -428,20 +442,35 @@ impl AstNode for RepeatLoop {
|
|||||||
impl AstNode for Expr {
|
impl AstNode for Expr {
|
||||||
const RULE: Rule = Rule::expr;
|
const RULE: Rule = Rule::expr;
|
||||||
fn from_pair(pair: Pair) -> Self {
|
fn from_pair(pair: Pair) -> Self {
|
||||||
|
// The way this works is, the rule has to be of the form:
|
||||||
|
// expr = { prefix* ~ val ~ suffix* ~ (operator ~ prefix* ~ val ~ suffix*)* }
|
||||||
|
// Each of these map methods turns a thing into an expr. Which means expr HAS
|
||||||
|
// to be an enum with the different possible forms these things can take:
|
||||||
|
// - if it's a val, it goes into map_primary and returns an Expr::Val
|
||||||
|
// - If it's a prefix or suffix, it goes into map_prefix or map_postfix, and
|
||||||
|
// returns an Expr::Prefix or Expr::Suffix
|
||||||
|
// - Operators go into map_infix along with two exprs for the left and right
|
||||||
|
// sides
|
||||||
|
// The output of all this is an Expr, containing a tree of other Exprs of
|
||||||
|
// various forms.
|
||||||
PRATT_PARSER
|
PRATT_PARSER
|
||||||
.map_primary(|val| {
|
.map_primary(|val| {
|
||||||
Expr {
|
let val = Val::from_pair(val);
|
||||||
lhs: Val::from_pair(val),
|
// If the val is a parenthesized expr, just unwrap it
|
||||||
op: None,
|
if let Val::Expr(expr) = val {
|
||||||
rhs: None
|
*expr.0
|
||||||
|
} else {
|
||||||
|
Expr::Val(val)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map_infix(|lhs, op, rhs|
|
.map_infix(|lhs, op, rhs|
|
||||||
Expr {
|
Expr::Infix(lhs.into(), Operator::from_pair(op), rhs.into())
|
||||||
lhs: Val::from(lhs),
|
)
|
||||||
op: Some(Operator::from_pair(op)),
|
.map_prefix(|prefix, expr|
|
||||||
rhs: Some(rhs.into()),
|
Expr::Prefix(Prefix::from_pair(prefix), expr.into())
|
||||||
})
|
)
|
||||||
|
.map_postfix(|expr, suffix|
|
||||||
|
Expr::Suffix(expr.into(), Suffix::from_pair(suffix)))
|
||||||
.parse(pair.into_inner())
|
.parse(pair.into_inner())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -503,7 +532,7 @@ impl AstNode for Suffix {
|
|||||||
fn from_pair(pair: Pair) -> Self {
|
fn from_pair(pair: Pair) -> Self {
|
||||||
let first = pair.first();
|
let first = pair.first();
|
||||||
match first.as_rule() {
|
match first.as_rule() {
|
||||||
Rule::subscript => Subscript(Expr::from_pair(first.first())),
|
Rule::subscript => Subscript(Expr::from_pair(first.first()).into()),
|
||||||
Rule::member => Self::Member(first.first_as_string()),
|
Rule::member => Self::Member(first.first_as_string()),
|
||||||
Rule::arglist => Arglist(first.into_inner().map(Rvalue::from_pair).collect()),
|
Rule::arglist => Arglist(first.into_inner().map(Rvalue::from_pair).collect()),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
@@ -533,23 +562,11 @@ impl AstNode for Val {
|
|||||||
const RULE: Rule = Rule::val;
|
const RULE: Rule = Rule::val;
|
||||||
|
|
||||||
fn from_pair(pair: Pair) -> Self {
|
fn from_pair(pair: Pair) -> Self {
|
||||||
let mut suffix = vec![];
|
let val = pair.first();
|
||||||
let mut prefix = vec![];
|
|
||||||
let mut val = None;
|
|
||||||
for child in pair.into_inner() {
|
|
||||||
match child.as_rule() {
|
|
||||||
Rule::prefix => prefix.push(Prefix::from_pair(child)),
|
|
||||||
Rule::suffix => suffix.push(Suffix::from_pair(child)),
|
|
||||||
Rule::number | Rule::name | Rule::expr => val = Some(child),
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let val = val.unwrap();
|
|
||||||
match val.as_rule() {
|
match val.as_rule() {
|
||||||
Rule::number => Self::Number(val.into_number(), prefix, suffix),
|
Rule::number => Self::Number(val.into_number()),
|
||||||
Rule::name => Self::Name(String::from(val.as_str()), prefix, suffix),
|
Rule::name => Self::Name(String::from(val.as_str())),
|
||||||
Rule::expr => Self::Expr(Expr::from_pair(val).into(), prefix, suffix),
|
Rule::expr => Self::Expr(Expr::from_pair(val).into()),
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -565,23 +582,7 @@ mod test {
|
|||||||
fn parse_vals() {
|
fn parse_vals() {
|
||||||
// Basic vals with no extras:
|
// Basic vals with no extras:
|
||||||
assert_eq!(Val::from_str("10"), Ok(10.into()));
|
assert_eq!(Val::from_str("10"), Ok(10.into()));
|
||||||
assert_eq!(Val::from_str("blah"), Ok(Val::Name("blah".into(), vec![], vec![])));
|
assert_eq!(Val::from_str("blah"), Ok(Val::Name("blah".into())));
|
||||||
|
|
||||||
// Simple prefix
|
|
||||||
assert_eq!(Val::from_str("-5"),
|
|
||||||
Ok(Val::Number(5, vec![Prefix::Neg], vec![])));
|
|
||||||
|
|
||||||
// Multiple prefixes
|
|
||||||
assert_eq!(Val::from_str("!&foo"),
|
|
||||||
Ok(Val::Name("foo".into(), vec![Prefix::Not, Prefix::Address], vec![])));
|
|
||||||
|
|
||||||
// Simple suffix
|
|
||||||
assert_eq!(Val::from_str("foo[10]"),
|
|
||||||
Ok(Val::Name("foo".into(), vec![], vec![Suffix::Subscript(10.into())])));
|
|
||||||
|
|
||||||
// Multi-suffix
|
|
||||||
assert_eq!(Val::from_str("foo[10].bar"),
|
|
||||||
Ok(Val::Name("foo".into(), vec![], vec![Suffix::Subscript(10.into()), Suffix::Member("bar".into())])));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -642,7 +643,7 @@ mod test {
|
|||||||
Const::from_str("const a = -7;"),
|
Const::from_str("const a = -7;"),
|
||||||
Ok(Const {
|
Ok(Const {
|
||||||
name: "a".into(),
|
name: "a".into(),
|
||||||
value: Some(Val::Number(7, vec![Prefix::Neg], vec![]).into()),
|
value: Some(Expr::Prefix(Prefix::Neg, 7.into()).into()),
|
||||||
string: None,
|
string: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -755,108 +756,127 @@ mod test {
|
|||||||
}],
|
}],
|
||||||
body: Block(vec![]),
|
body: Block(vec![]),
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
Function::from_str("fn foo<inline, org=0x400>(a) {}"),
|
|
||||||
Ok(func.clone())
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Function::from_str("fn foo<org=0x400, inline>(a) {}"),
|
|
||||||
Ok(func)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_exprs() {
|
fn parse_exprs() {
|
||||||
use Operator::*;
|
use Operator::*;
|
||||||
|
use Prefix::*;
|
||||||
|
use Suffix::*;
|
||||||
|
use Expr::Infix;
|
||||||
|
|
||||||
// A very, very basic expression
|
// A very, very basic expression
|
||||||
// For the rest of these we'll .into() stuff for brevity
|
assert_eq!(
|
||||||
//Some(assert_eq!(Expr::from_str("23"), Ok(Expr { lhs: Val::Number(23, vec![], vec![]), op: None, rhs: None })));
|
Expr::from_str("23"),
|
||||||
|
Ok(Expr::Val(Val::Number(23)))
|
||||||
|
);
|
||||||
|
|
||||||
// Two vals with an operator
|
// Two vals with an operator
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("23 + 5"),
|
Expr::from_str("23 + 5"),
|
||||||
Ok(Expr { lhs: 23.into(), op: Some(Add), rhs: Some(5.into()) })
|
Ok(Infix(23.into(), Add, 5.into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Multiple terms at the same precedence level
|
// Multiple terms at the same precedence level
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("1 + 2 + 3"),
|
Expr::from_str("1 + 2 + 3"),
|
||||||
Ok(Expr { lhs: 1.into(), op: Some(Add), rhs: Some(Expr { lhs: 2.into(), op: Some(Add), rhs: Some(3.into()) }.into()) })
|
Ok(Infix(Infix(1.into(), Add, 2.into()).into(), Add, 3.into()))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Simple prefix
|
||||||
|
assert_eq!(Expr::from_str("-5"),
|
||||||
|
Ok(Expr::Prefix(Neg, 5.into())));
|
||||||
|
|
||||||
|
// Multiple prefixes
|
||||||
|
assert_eq!(
|
||||||
|
Expr::from_str("!&foo"),
|
||||||
|
Ok(Expr::Prefix(Not,
|
||||||
|
Expr::Prefix(Address, "foo".into()).into())));
|
||||||
|
|
||||||
|
// Simple suffix
|
||||||
|
assert_eq!(
|
||||||
|
Expr::from_str("foo[10]"),
|
||||||
|
Ok(Expr::Suffix("foo".into(), Subscript(10.into())))
|
||||||
|
);
|
||||||
|
|
||||||
|
// Multi-suffix
|
||||||
|
assert_eq!(
|
||||||
|
Expr::from_str("foo[10].bar"),
|
||||||
|
Ok(Expr::Suffix(
|
||||||
|
Expr::Suffix("foo".into(), Subscript(10.into())).into(),
|
||||||
|
Member("bar".into())))
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
|
||||||
// Higher precedence levels
|
// Higher precedence levels
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("1 + 2 * 3"),
|
Expr::from_str("1 + 2 * 3"),
|
||||||
Ok(Expr(1.into(), Add, Expr(2.into(), Mul, 3.into()).into()))
|
Ok(Infix(1.into(), Add, Infix(2.into(), Mul, 3.into()).into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(Node::from_str("2 * 3"), Ok(Expr(2.into(), Mul, 3.into())));
|
assert_eq!(
|
||||||
|
Expr::from_str("2 * 3"),
|
||||||
|
Ok(Infix(2.into(), Mul, 3.into()))
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("2 * 3 + 4"),
|
Expr::from_str("2 * 3 + 4"),
|
||||||
Ok(Expr(Expr(2.into(), Mul, 3.into()).into(), Add, 4.into()))
|
Ok(Infix(Infix(2.into(), Mul, 3.into()).into(), Add, 4.into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Various operators
|
// Various operators
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("1 || 2 && 3"),
|
Expr::from_str("1 || 2 && 3"),
|
||||||
Ok(Expr(1.into(), Or, Expr(2.into(), And, 3.into()).into()))
|
Ok(Infix(1.into(), Or, Infix(2.into(), And, 3.into()).into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("2 && &blah"),
|
Expr::from_str("2 && &blah"),
|
||||||
Ok(Expr(2.into(), And, Address("blah".into()).into()))
|
Ok(Infix(2.into(), And, Expr::Prefix(Address, "blah".into()).into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("2 & &blah"),
|
Expr::from_str("2 & &blah"),
|
||||||
Ok(Expr(2.into(), BitAnd, Address("blah".into()).into()))
|
Ok(Infix(2.into(), BitAnd, Expr::Prefix(Address, "blah".into()).into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("1 | 2 ^ 3"),
|
Expr::from_str("1 | 2 ^ 3"),
|
||||||
Ok(Expr(1.into(), BitOr, Expr(2.into(), Xor, 3.into()).into()))
|
Ok(Infix(1.into(), BitOr, Infix(2.into(), Xor, 3.into()).into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("x == y > z"),
|
Expr::from_str("x == y > z"),
|
||||||
Ok(Expr(
|
Ok(Infix("x".into(), Eq, Infix("y".into(), Gt, "z".into()).into()))
|
||||||
Name("x".into()).into(),
|
|
||||||
Eq,
|
|
||||||
Expr(Name("y".into()).into(), Gt, Name("z".into()).into()).into()
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("1 << 6"),
|
Expr::from_str("1 << 6"),
|
||||||
Ok(Expr(1.into(), Lshift, 6.into()))
|
Ok(Infix(1.into(), Lshift, 6.into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("!a - -3"),
|
Expr::from_str("!a - -3"),
|
||||||
Ok(Expr(
|
Ok(Infix(Expr::Prefix(Not, "a".into()).into(), Sub, Expr::Prefix(Neg, 3.into()).into()))
|
||||||
Prefix(crate::ast::Prefix::Not, Name("a".into()).into()).into(),
|
|
||||||
Sub,
|
|
||||||
Prefix(crate::ast::Prefix::Neg, 3.into()).into()
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("-(4 * 5)"),
|
Expr::from_str("-(4 * 5)"),
|
||||||
Ok(Prefix(
|
Ok(Expr::Prefix(Neg,
|
||||||
crate::ast::Prefix::Neg,
|
Infix(4.into(), Mul, 5.into()).into()
|
||||||
Expr(4.into(), Mul, 5.into()).into()
|
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Parens
|
// Parens
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("(1 + 2) * 3"),
|
Expr::from_str("(1 + 2) * 3"),
|
||||||
Ok(Expr(Expr(1.into(), Add, 2.into()).into(), Mul, 3.into()))
|
Ok(
|
||||||
|
Infix(
|
||||||
|
Infix(1.into(), Add, 2.into()).into(),
|
||||||
|
Mul,
|
||||||
|
3.into()
|
||||||
|
)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -894,55 +914,48 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_addresses() {
|
fn parse_calls() {
|
||||||
// assert_eq!(Node::from_str("&foo"), Ok(Node::Address("foo".into())));
|
use Val::Number;
|
||||||
}
|
|
||||||
|
|
||||||
// #[test]
|
let blah = Expr::Suffix(
|
||||||
// fn parse_calls() {
|
"blah".into(),
|
||||||
// use Val::Number;
|
Arglist(vec![])
|
||||||
//
|
);
|
||||||
// let blah = Call {
|
|
||||||
// name: "blah".into(),
|
// Can Node parse a call?
|
||||||
// args: vec![],
|
assert_eq!(Expr::from_str("blah()"), Ok(blah.clone()));
|
||||||
// };
|
|
||||||
//
|
// Can Statement parse a call?
|
||||||
// // Can Node parse a call?
|
assert_eq!(Statement::from_str("blah();"), Ok(Statement::Expr(blah)));
|
||||||
// assert_eq!(Node::from_str("blah()"), Ok(Node::Call(blah.clone())));
|
|
||||||
//
|
// Calls with args
|
||||||
// // Can Statement parse a call?
|
assert_eq!(
|
||||||
// assert_eq!(Statement::from_str("blah();"), Ok(Statement::Call(blah)));
|
Expr::from_str("blah(1, 2)"),
|
||||||
//
|
Ok(Expr::Suffix(
|
||||||
// // Calls with args
|
"blah".into(),
|
||||||
// // assert_eq!(
|
Arglist(vec![1.into(), 2.into()])))
|
||||||
// // Call::from_str("blah(1, 2)"),
|
);
|
||||||
// // Ok(Call {
|
|
||||||
// // name: "blah".into(),
|
//Calls with strings
|
||||||
// // args: vec![Rvalue::Expr(Number(1)), Rvalue::Expr(Number(2))]
|
assert_eq!(
|
||||||
// // })
|
Expr::from_str("blah(\"foo\", 2)"),
|
||||||
// // );
|
Ok(Expr::Suffix(
|
||||||
//
|
"blah".into(),
|
||||||
// // Calls with strings
|
Arglist(vec!["foo".into(), 2.into()])))
|
||||||
// // assert_eq!(
|
);
|
||||||
// // Call::from_str("blah(\"foo\", 2)"),
|
}
|
||||||
// // Ok(Call {
|
|
||||||
// // name: "blah".into(),
|
|
||||||
// // args: vec![Rvalue::String("foo".into()), Rvalue::Expr(Number(2))]
|
|
||||||
// // })
|
|
||||||
// // );
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_return() {
|
fn parse_return() {
|
||||||
// assert_eq!(
|
assert_eq!(
|
||||||
// Statement::from_str("return;"),
|
Statement::from_str("return;"),
|
||||||
// Ok(Statement::Return(Return(None)))
|
Ok(Statement::Return(Return(None)))
|
||||||
// );
|
);
|
||||||
//
|
|
||||||
// assert_eq!(
|
assert_eq!(
|
||||||
// Statement::from_str("return 17;"),
|
Statement::from_str("return 17;"),
|
||||||
// Ok(Statement::Return(Return(Some(Node::Number(17)))))
|
Ok(Statement::Return(Return(Some(17.into()))))
|
||||||
// );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -958,10 +971,7 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Assignment::from_str("foo[45] = 7"),
|
Assignment::from_str("foo[45] = 7"),
|
||||||
Ok(Assignment {
|
Ok(Assignment {
|
||||||
lvalue: Lvalue::ArrayRef(ArrayRef {
|
lvalue: Lvalue::ArrayRef("foo".into(), 45.into()),
|
||||||
name: "foo".into(),
|
|
||||||
subscript: 45.into(),
|
|
||||||
}),
|
|
||||||
rvalue: Rvalue::Expr(7.into()),
|
rvalue: Rvalue::Expr(7.into()),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -64,15 +64,15 @@ operator = _{
|
|||||||
| ne
|
| ne
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = { val ~ (operator ~ val)* }
|
expr = { prefix* ~ val ~ suffix* ~ (operator ~ prefix* ~ val ~ suffix*)* }
|
||||||
val = { prefix* ~ (number | name | "(" ~ expr ~ ")") ~ suffix* }
|
val = { number | name | "(" ~ expr ~ ")" }
|
||||||
|
|
||||||
suffix = { subscript | arglist | member }
|
suffix = { subscript | arglist | member }
|
||||||
subscript = { "[" ~ expr ~ "]" }
|
subscript = { "[" ~ expr ~ "]" }
|
||||||
arglist = { "(" ~ (rvalue ~ ("," ~ rvalue)*)? ~ ")" }
|
arglist = { "(" ~ (rvalue ~ ("," ~ rvalue)*)? ~ ")" }
|
||||||
member = { "." ~ name }
|
member = { "." ~ name }
|
||||||
|
|
||||||
statement = { asm | ((return_stmt | assignment | expr | var_decl) ~ ";") | conditional | while_loop | repeat_loop }
|
statement = { asm | ((return_stmt | var_decl | assignment | expr) ~ ";") | conditional | while_loop | repeat_loop }
|
||||||
|
|
||||||
asm = { "asm" ~ asm_args? ~ "{" ~ asm_body ~ "}" }
|
asm = { "asm" ~ asm_args? ~ "{" ~ asm_body ~ "}" }
|
||||||
asm_args = { "(" ~ expr ~ ("," ~ expr)* ~ ")" }
|
asm_args = { "(" ~ expr ~ ("," ~ expr)* ~ ")" }
|
||||||
|
|||||||
Reference in New Issue
Block a user