More refactoring and addresses working
This commit is contained in:
+12
-11
@@ -86,13 +86,19 @@ pub struct Lvalue {
|
|||||||
|
|
||||||
impl From<&str> for Lvalue {
|
impl From<&str> for Lvalue {
|
||||||
fn from(name: &str) -> Self {
|
fn from(name: &str) -> Self {
|
||||||
Self { name: String::from(name), subscripts: vec![] }
|
Self {
|
||||||
|
name: String::from(name),
|
||||||
|
subscripts: vec![],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<String> for Lvalue {
|
impl From<String> for Lvalue {
|
||||||
fn from(name: String) -> Self {
|
fn from(name: String) -> Self {
|
||||||
Self { name, subscripts: vec![] }
|
Self {
|
||||||
|
name,
|
||||||
|
subscripts: vec![],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,13 +159,6 @@ pub enum Operator {
|
|||||||
Rshift,
|
Rshift,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
|
||||||
pub enum Prefix {
|
|
||||||
Neg,
|
|
||||||
Not,
|
|
||||||
Address
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Suffix {
|
pub enum Suffix {
|
||||||
Subscript(BoxExpr),
|
Subscript(BoxExpr),
|
||||||
@@ -172,9 +171,11 @@ pub enum Expr {
|
|||||||
Number(i32),
|
Number(i32),
|
||||||
Name(String),
|
Name(String),
|
||||||
Expr(BoxExpr),
|
Expr(BoxExpr),
|
||||||
Prefix(Prefix, BoxExpr),
|
Not(BoxExpr),
|
||||||
|
Neg(BoxExpr),
|
||||||
|
Address(Lvalue),
|
||||||
Suffix(BoxExpr, Suffix),
|
Suffix(BoxExpr, Suffix),
|
||||||
Infix(BoxExpr, Operator, BoxExpr)
|
Infix(BoxExpr, Operator, BoxExpr),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
|
|||||||
+58
-17
@@ -317,7 +317,9 @@ 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");
|
||||||
|
|
||||||
if !self.subscripts.is_empty() { todo!("Arrays and structs aren't implemented yet") }
|
if !self.subscripts.is_empty() {
|
||||||
|
todo!("Arrays and structs aren't implemented yet")
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(var) = lookup(&self.name, global_scope, &sig.local_scope) {
|
if let Some(var) = lookup(&self.name, global_scope, &sig.local_scope) {
|
||||||
match var {
|
match var {
|
||||||
@@ -409,20 +411,23 @@ impl Compilable for Expr {
|
|||||||
(*e.0).process(state, Some(sig))?;
|
(*e.0).process(state, Some(sig))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Expr::Prefix(pre, e) => {
|
Expr::Neg(e) => {
|
||||||
(*e.0).process(state, Some(sig))?;
|
(*e.0).process(state, Some(sig))?;
|
||||||
match pre {
|
|
||||||
Prefix::Neg => {
|
|
||||||
// To arithmetically negate something, invert and increment (2s complement)
|
// To arithmetically negate something, invert and increment (2s complement)
|
||||||
sig.emit("xor -1");
|
sig.emit("xor -1");
|
||||||
sig.emit("add 1");
|
sig.emit("add 1");
|
||||||
}
|
|
||||||
Prefix::Not => sig.emit("not"),
|
|
||||||
Prefix::Address => { todo!() }
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Expr::Suffix(_, _) => {todo!()}
|
Expr::Not(e) => {
|
||||||
|
(*e.0).process(state, Some(sig))?;
|
||||||
|
sig.emit("not");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
// Handling addresses is very easy because processing an lvalue leaves the address on the stack
|
||||||
|
Expr::Address(lvalue) => lvalue.process(state, Some(sig)),
|
||||||
|
Expr::Suffix(_, _) => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
Expr::Infix(lhs, op, rhs) => {
|
Expr::Infix(lhs, op, rhs) => {
|
||||||
// Recurse on expressions, handling operators
|
// Recurse on expressions, handling operators
|
||||||
(*lhs.0).process(state, Some(&mut sig))?;
|
(*lhs.0).process(state, Some(&mut sig))?;
|
||||||
@@ -519,21 +524,32 @@ fn to_flag(val: bool) -> i32 {
|
|||||||
pub fn eval_const(expr: Expr, scope: &Scope) -> Result<i32, CompileError> {
|
pub fn eval_const(expr: Expr, scope: &Scope) -> Result<i32, CompileError> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Number(n) => Ok(n), // That was easy
|
Expr::Number(n) => Ok(n), // That was easy
|
||||||
Expr::Name(n) => if let Some(Variable::Literal(val)) = scope.get(&n) {
|
Expr::Name(n) => {
|
||||||
|
if let Some(Variable::Literal(val)) = scope.get(&n) {
|
||||||
Ok(*val)
|
Ok(*val)
|
||||||
} else {
|
} else {
|
||||||
Err(CompileError(0, 0, format!("Unknown const {}", n)))
|
Err(CompileError(0, 0, format!("Unknown const {}", n)))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Expr::Expr(e) => eval_const(*e.0, scope),
|
Expr::Expr(e) => eval_const(*e.0, scope),
|
||||||
Expr::Prefix(pre, e) => {
|
Expr::Neg(e) => {
|
||||||
let val = eval_const(*e.0, scope)?;
|
let val = eval_const(*e.0, scope)?;
|
||||||
match pre {
|
Ok(-val)
|
||||||
Prefix::Neg => Ok(-val),
|
|
||||||
Prefix::Not => Ok(if val != 0 { 0 } else { 1 }),
|
|
||||||
Prefix::Address => Err(CompileError(0, 0, String::from("Addresses are not know at compile time")))
|
|
||||||
}
|
}
|
||||||
|
Expr::Not(e) => {
|
||||||
|
let val = eval_const(*e.0, scope)?;
|
||||||
|
Ok(if val != 0 { 0 } else { 1 })
|
||||||
}
|
}
|
||||||
Expr::Suffix(_, _) => Err(CompileError(0, 0, String::from("Constants must be statically defined"))),
|
Expr::Address(_) => Err(CompileError(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
String::from("Addresses are not known at compile time"),
|
||||||
|
)),
|
||||||
|
Expr::Suffix(_, _) => Err(CompileError(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
String::from("Constants must be statically defined"),
|
||||||
|
)),
|
||||||
Expr::Infix(lhs, op, rhs) => {
|
Expr::Infix(lhs, op, rhs) => {
|
||||||
let lhs = eval_const(*lhs.0, scope)?;
|
let lhs = eval_const(*lhs.0, scope)?;
|
||||||
let rhs = eval_const(*rhs.0, scope)?;
|
let rhs = eval_const(*rhs.0, scope)?;
|
||||||
@@ -705,7 +721,32 @@ mod test {
|
|||||||
"push _gensym_4",
|
"push _gensym_4",
|
||||||
"loadw frame",
|
"loadw frame",
|
||||||
"add 3", // the address of y (frame + 3) and put gensym_4 in it
|
"add 3", // the address of y (frame + 3) and put gensym_4 in it
|
||||||
"storew"].join("\n")
|
"storew"
|
||||||
|
]
|
||||||
|
.join("\n")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_addresses() {
|
||||||
|
let mut state = State::default();
|
||||||
|
parse("fn blah() { var x = 3; var y = &x; }")
|
||||||
|
.unwrap()
|
||||||
|
.process(&mut state, None)
|
||||||
|
.expect("Failed to compile");
|
||||||
|
let body = body_as_string(state.functions.get("blah").unwrap());
|
||||||
|
assert_eq!(
|
||||||
|
body,
|
||||||
|
vec![
|
||||||
|
"push 3",
|
||||||
|
"loadw frame",
|
||||||
|
"storew", // the assignment for x
|
||||||
|
"loadw frame", // The addr of x
|
||||||
|
"loadw frame",
|
||||||
|
"add 3", // the address of y (frame + 3) and put the addr of x (frame) in it
|
||||||
|
"storew"
|
||||||
|
]
|
||||||
|
.join("\n")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -270,11 +270,7 @@ impl AstNode for Function {
|
|||||||
|
|
||||||
let body = Block::from_pair(inner.next().unwrap());
|
let body = Block::from_pair(inner.next().unwrap());
|
||||||
|
|
||||||
Self {
|
Self { name, args, body }
|
||||||
name,
|
|
||||||
args,
|
|
||||||
body,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,11 +333,13 @@ impl AstNode for Lvalue {
|
|||||||
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 name = String::from(pairs.next().unwrap().as_str());
|
let name = String::from(pairs.next().unwrap().as_str());
|
||||||
let subscripts: Vec<_> = pairs.map(|p| match p.as_rule() {
|
let subscripts: Vec<_> = pairs
|
||||||
|
.map(|p| match p.as_rule() {
|
||||||
Rule::subscript => Suffix::Subscript(Expr::from_pair(p.first()).into()),
|
Rule::subscript => Suffix::Subscript(Expr::from_pair(p.first()).into()),
|
||||||
Rule::member => Suffix::Member(String::from(p.as_str())),
|
Rule::member => Suffix::Member(p.first_as_string()),
|
||||||
_ => unreachable!()
|
_ => unreachable!(),
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
Self { name, subscripts }
|
Self { name, subscripts }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,22 +449,20 @@ impl AstNode for Expr {
|
|||||||
// The output of all this is an Expr, containing a tree of other Exprs of
|
// The output of all this is an Expr, containing a tree of other Exprs of
|
||||||
// various forms.
|
// various forms.
|
||||||
PRATT_PARSER
|
PRATT_PARSER
|
||||||
.map_primary(|term| {
|
.map_primary(|term| match term.as_rule() {
|
||||||
match term.as_rule() {
|
|
||||||
Rule::number => Expr::Number(term.into_number()),
|
Rule::number => Expr::Number(term.into_number()),
|
||||||
Rule::name => Expr::Name(String::from(term.as_str())),
|
Rule::name => Expr::Name(String::from(term.as_str())),
|
||||||
Rule::expr => Expr::from_pair(term).into(),
|
Rule::expr => Expr::from_pair(term),
|
||||||
_ => unreachable!()
|
Rule::lvalue => Expr::Address(Lvalue::from_pair(term)),
|
||||||
}
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
.map_infix(|lhs, op, rhs|
|
.map_infix(|lhs, op, rhs| Expr::Infix(lhs.into(), Operator::from_pair(op), rhs.into()))
|
||||||
Expr::Infix(lhs.into(), Operator::from_pair(op), rhs.into())
|
.map_prefix(|prefix, expr| match prefix.as_str() {
|
||||||
)
|
"-" => Expr::Neg(expr.into()),
|
||||||
.map_prefix(|prefix, expr|
|
"!" => Expr::Not(expr.into()),
|
||||||
Expr::Prefix(Prefix::from_pair(prefix), expr.into())
|
_ => unreachable!(),
|
||||||
)
|
})
|
||||||
.map_postfix(|expr, suffix|
|
.map_postfix(|expr, suffix| Expr::Suffix(expr.into(), Suffix::from_pair(suffix)))
|
||||||
Expr::Suffix(expr.into(), Suffix::from_pair(suffix)))
|
|
||||||
.parse(pair.into_inner())
|
.parse(pair.into_inner())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -506,19 +502,6 @@ impl AstNode for Operator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstNode for Prefix {
|
|
||||||
const RULE: Rule = Rule::prefix;
|
|
||||||
|
|
||||||
fn from_pair(pair: Pair) -> Self {
|
|
||||||
match pair.as_str() {
|
|
||||||
"!" => Self::Not,
|
|
||||||
"-" => Self::Neg,
|
|
||||||
"&" => Self::Address,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl AstNode for Suffix {
|
impl AstNode for Suffix {
|
||||||
@@ -530,7 +513,7 @@ impl AstNode for Suffix {
|
|||||||
Rule::subscript => Self::Subscript(Expr::from_pair(first.first()).into()),
|
Rule::subscript => Self::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 => Self::Arglist(first.into_inner().map(Rvalue::from_pair).collect()),
|
Rule::arglist => Self::Arglist(first.into_inner().map(Rvalue::from_pair).collect()),
|
||||||
rule => unreachable!("Expected a subscript, member, or arglist, got a {:?}", rule)
|
rule => unreachable!("Expected a subscript, member, or arglist, got a {:?}", rule),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -615,7 +598,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(Expr::Prefix(Prefix::Neg, 7.into()).into()),
|
value: Some(Expr::Neg(7.into()).into()),
|
||||||
string: None,
|
string: None,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -658,7 +641,7 @@ mod test {
|
|||||||
name: "bar".into(),
|
name: "bar".into(),
|
||||||
typename: None,
|
typename: None,
|
||||||
size: Some(100.into()),
|
size: Some(100.into()),
|
||||||
}, ],
|
},],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -670,7 +653,7 @@ mod test {
|
|||||||
name: "bar".into(),
|
name: "bar".into(),
|
||||||
typename: Some("Thing".into()),
|
typename: Some("Thing".into()),
|
||||||
size: Some(100.into()),
|
size: Some(100.into()),
|
||||||
}, ],
|
},],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -732,16 +715,12 @@ mod test {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_exprs() {
|
fn parse_exprs() {
|
||||||
use Operator::*;
|
|
||||||
use Prefix::*;
|
|
||||||
use Suffix::*;
|
|
||||||
use Expr::Infix;
|
use Expr::Infix;
|
||||||
|
use Operator::*;
|
||||||
|
use Suffix::*;
|
||||||
|
|
||||||
// A very, very basic expression
|
// A very, very basic expression
|
||||||
assert_eq!(
|
assert_eq!(Expr::from_str("23"), Ok(Expr::Number(23)));
|
||||||
Expr::from_str("23"),
|
|
||||||
Ok(Expr::Number(23))
|
|
||||||
);
|
|
||||||
|
|
||||||
// Two vals with an operator
|
// Two vals with an operator
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -756,14 +735,13 @@ mod test {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Simple prefix
|
// Simple prefix
|
||||||
assert_eq!(Expr::from_str("-5"),
|
assert_eq!(Expr::from_str("-5"), Ok(Expr::Neg(5.into())));
|
||||||
Ok(Expr::Prefix(Neg, 5.into())));
|
|
||||||
|
|
||||||
// Multiple prefixes
|
// Multiple prefixes
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("!&foo"),
|
Expr::from_str("!-foo"),
|
||||||
Ok(Expr::Prefix(Not,
|
Ok(Expr::Not(Expr::Neg("foo".into()).into()))
|
||||||
Expr::Prefix(Address, "foo".into()).into())));
|
);
|
||||||
|
|
||||||
// Simple suffix
|
// Simple suffix
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -776,7 +754,8 @@ mod test {
|
|||||||
Expr::from_str("foo[10].bar"),
|
Expr::from_str("foo[10].bar"),
|
||||||
Ok(Expr::Suffix(
|
Ok(Expr::Suffix(
|
||||||
Expr::Suffix("foo".into(), Subscript(10.into())).into(),
|
Expr::Suffix("foo".into(), Subscript(10.into())).into(),
|
||||||
Member("bar".into())))
|
Member("bar".into())
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
// Higher precedence levels
|
// Higher precedence levels
|
||||||
@@ -785,10 +764,7 @@ mod test {
|
|||||||
Ok(Infix(1.into(), Add, Infix(2.into(), Mul, 3.into()).into()))
|
Ok(Infix(1.into(), Add, Infix(2.into(), Mul, 3.into()).into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(Expr::from_str("2 * 3"), Ok(Infix(2.into(), Mul, 3.into())));
|
||||||
Expr::from_str("2 * 3"),
|
|
||||||
Ok(Infix(2.into(), Mul, 3.into()))
|
|
||||||
);
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("2 * 3 + 4"),
|
Expr::from_str("2 * 3 + 4"),
|
||||||
@@ -803,22 +779,30 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("2 && &blah"),
|
Expr::from_str("2 && &blah"),
|
||||||
Ok(Infix(2.into(), And, Expr::Prefix(Address, "blah".into()).into()))
|
Ok(Infix(2.into(), And, Expr::Address("blah".into()).into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("2 & &blah"),
|
Expr::from_str("2 & &blah"),
|
||||||
Ok(Infix(2.into(), BitAnd, Expr::Prefix(Address, "blah".into()).into()))
|
Ok(Infix(2.into(), BitAnd, Expr::Address("blah".into()).into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("1 | 2 ^ 3"),
|
Expr::from_str("1 | 2 ^ 3"),
|
||||||
Ok(Infix(1.into(), BitOr, Infix(2.into(), Xor, 3.into()).into()))
|
Ok(Infix(
|
||||||
|
1.into(),
|
||||||
|
BitOr,
|
||||||
|
Infix(2.into(), Xor, 3.into()).into()
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("x == y > z"),
|
Expr::from_str("x == y > z"),
|
||||||
Ok(Infix("x".into(), Eq, Infix("y".into(), Gt, "z".into()).into()))
|
Ok(Infix(
|
||||||
|
"x".into(),
|
||||||
|
Eq,
|
||||||
|
Infix("y".into(), Gt, "z".into()).into()
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -828,35 +812,57 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("!a - -3"),
|
Expr::from_str("!a - -3"),
|
||||||
Ok(Infix(Expr::Prefix(Not, "a".into()).into(), Sub, Expr::Prefix(Neg, 3.into()).into()))
|
Ok(Infix(
|
||||||
|
Expr::Not("a".into()).into(),
|
||||||
|
Sub,
|
||||||
|
Expr::Neg(3.into()).into()
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("-(4 * 5)"),
|
Expr::from_str("-(4 * 5)"),
|
||||||
Ok(Expr::Prefix(Neg,
|
Ok(Expr::Neg(Infix(4.into(), Mul, 5.into()).into()))
|
||||||
Infix(4.into(), Mul, 5.into()).into()
|
|
||||||
))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Parens
|
// Parens
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Expr::from_str("(1 + 2) * 3"),
|
Expr::from_str("(1 + 2) * 3"),
|
||||||
Ok(
|
Ok(Infix(Infix(1.into(), Add, 2.into()).into(), Mul, 3.into()))
|
||||||
Infix(
|
|
||||||
Infix(1.into(), Add, 2.into()).into(),
|
|
||||||
Mul,
|
|
||||||
3.into()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Addresses
|
||||||
|
assert_eq!(
|
||||||
|
Expr::from_str("&foo.bar"),
|
||||||
|
Ok(Expr::Address(Lvalue {
|
||||||
|
name: "foo".into(),
|
||||||
|
subscripts: vec![Suffix::Member("bar".into())]
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Expr::from_str("&foo + 7"),
|
||||||
|
Ok(Expr::Infix(
|
||||||
|
Expr::Address("foo".into()).into(),
|
||||||
|
Add,
|
||||||
|
7.into()
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
// This is godawful but legal _as long as it parses like this._ The arglist suffix on the end
|
||||||
|
// goes on the "&foo" expression as a whole, so, it "calls" the address of foo. Essentially:
|
||||||
|
// "push foo; call" rather than "loadw foo; call"
|
||||||
|
assert_eq!(
|
||||||
|
Expr::from_str("&foo()"),
|
||||||
|
Ok(Expr::Suffix(
|
||||||
|
Expr::Address("foo".into()).into(),
|
||||||
|
Suffix::Arglist(vec![])
|
||||||
|
))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_calls() {
|
fn parse_calls() {
|
||||||
let blah = Expr::Suffix(
|
let blah = Expr::Suffix("blah".into(), Suffix::Arglist(vec![]));
|
||||||
"blah".into(),
|
|
||||||
Suffix::Arglist(vec![])
|
|
||||||
);
|
|
||||||
|
|
||||||
// Can Node parse a call?
|
// Can Node parse a call?
|
||||||
assert_eq!(Expr::from_str("blah()"), Ok(blah.clone()));
|
assert_eq!(Expr::from_str("blah()"), Ok(blah.clone()));
|
||||||
@@ -869,7 +875,8 @@ mod test {
|
|||||||
Expr::from_str("blah(1, 2)"),
|
Expr::from_str("blah(1, 2)"),
|
||||||
Ok(Expr::Suffix(
|
Ok(Expr::Suffix(
|
||||||
"blah".into(),
|
"blah".into(),
|
||||||
Suffix::Arglist(vec![1.into(), 2.into()])))
|
Suffix::Arglist(vec![1.into(), 2.into()])
|
||||||
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
//Calls with strings
|
//Calls with strings
|
||||||
@@ -877,7 +884,8 @@ mod test {
|
|||||||
Expr::from_str("blah(\"foo\", 2)"),
|
Expr::from_str("blah(\"foo\", 2)"),
|
||||||
Ok(Expr::Suffix(
|
Ok(Expr::Suffix(
|
||||||
"blah".into(),
|
"blah".into(),
|
||||||
Suffix::Arglist(vec!["foo".into(), 2.into()])))
|
Suffix::Arglist(vec!["foo".into(), 2.into()])
|
||||||
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -907,7 +915,10 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Assignment::from_str("foo[45] = 7"),
|
Assignment::from_str("foo[45] = 7"),
|
||||||
Ok(Assignment {
|
Ok(Assignment {
|
||||||
lvalue: Lvalue { name: String::from("foo"), subscripts: vec![Suffix::Subscript(45.into())] },
|
lvalue: Lvalue {
|
||||||
|
name: String::from("foo"),
|
||||||
|
subscripts: vec![Suffix::Subscript(45.into())]
|
||||||
|
},
|
||||||
rvalue: Rvalue::Expr(7.into()),
|
rvalue: Rvalue::Expr(7.into()),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ eq = { "==" }
|
|||||||
ne = { "!=" }
|
ne = { "!=" }
|
||||||
lshift = { "<<" }
|
lshift = { "<<" }
|
||||||
rshift = { ">>" }
|
rshift = { ">>" }
|
||||||
prefix = { "-" | "!" | "&" }
|
prefix = { "-" | "!" }
|
||||||
|
|
||||||
operator = _{
|
operator = _{
|
||||||
add
|
add
|
||||||
@@ -65,7 +65,7 @@ operator = _{
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr = { prefix* ~ term ~ suffix* ~ (operator ~ prefix* ~ term ~ suffix*)* }
|
expr = { prefix* ~ term ~ suffix* ~ (operator ~ prefix* ~ term ~ suffix*)* }
|
||||||
term = _{ number | name | "(" ~ expr ~ ")" }
|
term = _{ number | name | "(" ~ expr ~ ")" | "&" ~ lvalue }
|
||||||
|
|
||||||
suffix = { modifier | arglist }
|
suffix = { modifier | arglist }
|
||||||
modifier = _{ subscript | member }
|
modifier = _{ subscript | member }
|
||||||
|
|||||||
Reference in New Issue
Block a user