Prefix operators
This commit is contained in:
@@ -38,7 +38,7 @@ pub struct Member {
|
|||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct Const {
|
pub struct Const {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub value: Option<i32>,
|
pub value: Option<i32>, // todo: this should take a Node
|
||||||
pub string: Option<String>,
|
pub string: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +150,12 @@ pub enum Operator {
|
|||||||
Rshift,
|
Rshift,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
pub enum Prefix {
|
||||||
|
Neg,
|
||||||
|
Not,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub enum Node {
|
pub enum Node {
|
||||||
Number(i32),
|
Number(i32),
|
||||||
@@ -158,6 +164,7 @@ pub enum Node {
|
|||||||
Name(String),
|
Name(String),
|
||||||
Address(String),
|
Address(String),
|
||||||
Expr(BoxNode, Operator, BoxNode),
|
Expr(BoxNode, Operator, BoxNode),
|
||||||
|
Prefix(Prefix, BoxNode),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i32> for Node {
|
impl From<i32> for Node {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ name_char = { ASCII_ALPHA_LOWER | ASCII_ALPHA_UPPER | "_" | "$" }
|
|||||||
name = @{ name_char ~ (name_char | ASCII_DIGIT)* }
|
name = @{ name_char ~ (name_char | ASCII_DIGIT)* }
|
||||||
|
|
||||||
dec_number = @{ ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* }
|
dec_number = @{ ASCII_NONZERO_DIGIT ~ ASCII_DIGIT* }
|
||||||
|
// Literal numbers use this rule, but in exprs it's the prefix operator. The difference
|
||||||
|
// is that some things (const initialization) only accept literal numbers.
|
||||||
neg_number = ${ "-" ~ dec_number }
|
neg_number = ${ "-" ~ dec_number }
|
||||||
hex_number = ${ "0x" ~ ASCII_HEX_DIGIT+ }
|
hex_number = ${ "0x" ~ ASCII_HEX_DIGIT+ }
|
||||||
bin_number = ${ "0b" ~ ASCII_BIN_DIGIT+ }
|
bin_number = ${ "0b" ~ ASCII_BIN_DIGIT+ }
|
||||||
@@ -38,6 +40,7 @@ eq = { "==" }
|
|||||||
ne = { "!=" }
|
ne = { "!=" }
|
||||||
lshift = { "<<" }
|
lshift = { "<<" }
|
||||||
rshift = { ">>" }
|
rshift = { ">>" }
|
||||||
|
prefix = { "-" | "!" }
|
||||||
|
|
||||||
operator = _{
|
operator = _{
|
||||||
add | sub |
|
add | sub |
|
||||||
@@ -47,7 +50,7 @@ operator = _{
|
|||||||
lshift | rshift |
|
lshift | rshift |
|
||||||
lt | le | gt | ge |
|
lt | le | gt | ge |
|
||||||
eq | ne }
|
eq | ne }
|
||||||
expr = { val ~ (operator ~ val)* }
|
expr = { prefix? ~ val ~ (operator ~ prefix? ~ val)* }
|
||||||
val = { // These are what get evaluated and left on the stack:
|
val = { // These are what get evaluated and left on the stack:
|
||||||
number | // Literal numbers
|
number | // Literal numbers
|
||||||
("(" ~ expr ~ ")") | // Nested parenthesized exprs
|
("(" ~ expr ~ ")") | // Nested parenthesized exprs
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ lazy_static::lazy_static! {
|
|||||||
.op(Op::infix(lshift, Left) | Op::infix(rshift, Left))
|
.op(Op::infix(lshift, Left) | Op::infix(rshift, Left))
|
||||||
.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))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,6 +468,7 @@ impl AstNode for Node {
|
|||||||
rule => unreachable!("Expr::parse expected atom, found {:?}", rule),
|
rule => unreachable!("Expr::parse expected atom, found {:?}", rule),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.map_prefix(|op, rhs| Node::Prefix(Prefix::from_pair(op), rhs.into()))
|
||||||
.map_infix(|lhs, op, rhs| Node::Expr(lhs.into(), Operator::from_pair(op), rhs.into()))
|
.map_infix(|lhs, op, rhs| Node::Expr(lhs.into(), Operator::from_pair(op), rhs.into()))
|
||||||
.parse(pair.into_inner())
|
.parse(pair.into_inner())
|
||||||
}
|
}
|
||||||
@@ -501,6 +503,18 @@ 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,
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
impl AstNode for ArrayRef {
|
impl AstNode for ArrayRef {
|
||||||
@@ -765,6 +779,7 @@ mod test {
|
|||||||
Ok(Expr(Expr(2.into(), Mul, 3.into()).into(), Add, 4.into()))
|
Ok(Expr(Expr(2.into(), Mul, 3.into()).into(), Add, 4.into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Various operators
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("1 || 2 && 3"),
|
Node::from_str("1 || 2 && 3"),
|
||||||
Ok(Expr(1.into(), Or, Expr(2.into(), And, 3.into()).into()))
|
Ok(Expr(1.into(), Or, Expr(2.into(), And, 3.into()).into()))
|
||||||
@@ -799,6 +814,23 @@ mod test {
|
|||||||
Ok(Expr(1.into(), Lshift, 6.into()))
|
Ok(Expr(1.into(), Lshift, 6.into()))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Node::from_str("!a - -3"),
|
||||||
|
Ok(Expr(
|
||||||
|
Prefix(crate::ast::Prefix::Not, Name("a".into()).into()).into(),
|
||||||
|
Sub,
|
||||||
|
Prefix(crate::ast::Prefix::Neg, 3.into()).into()
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Node::from_str("-(4 * 5)"),
|
||||||
|
Ok(Prefix(
|
||||||
|
crate::ast::Prefix::Neg,
|
||||||
|
Expr(4.into(), Mul, 5.into()).into()
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
// Parens
|
// Parens
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Node::from_str("(1 + 2) * 3"),
|
Node::from_str("(1 + 2) * 3"),
|
||||||
|
|||||||
Reference in New Issue
Block a user