Unary operators
This commit is contained in:
parent
8c2af9ab61
commit
1f66a5f94b
40
src/parse.rs
40
src/parse.rs
|
@ -339,6 +339,7 @@ type ExprPair<'a> = Box<(Expr<'a>, Expr<'a>)>;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Expr<'a> {
|
pub enum Expr<'a> {
|
||||||
BinaryOp(BinaryOp, ExprPair<'a>),
|
BinaryOp(BinaryOp, ExprPair<'a>),
|
||||||
|
UnaryOp(UnaryOp, Box<Expr<'a>>),
|
||||||
Literal(Literal<'a>),
|
Literal(Literal<'a>),
|
||||||
Local(&'a str),
|
Local(&'a str),
|
||||||
Member(&'a str, Box<Expr<'a>>),
|
Member(&'a str, Box<Expr<'a>>),
|
||||||
|
@ -350,7 +351,13 @@ pub enum Expr<'a> {
|
||||||
|
|
||||||
impl<'a> Expr<'a> {
|
impl<'a> Expr<'a> {
|
||||||
pub fn build_start(tok: Token, lexer: &mut Lexer<'a>) -> (Option<Self>, Token) {
|
pub fn build_start(tok: Token, lexer: &mut Lexer<'a>) -> (Option<Self>, Token) {
|
||||||
let mut lhs = match tok {
|
let (unary_op, tok) = if let Some(op) = UnaryOp::from_token(tok) {
|
||||||
|
(Some(op), lexer.next().unwrap())
|
||||||
|
} else {
|
||||||
|
(None, tok)
|
||||||
|
};
|
||||||
|
|
||||||
|
let lhs = match tok {
|
||||||
Token::Identifier => Self::Local(lexer.slice()),
|
Token::Identifier => Self::Local(lexer.slice()),
|
||||||
Token::Dot => Self::SelfMember(lexer.eat_expect_id()),
|
Token::Dot => Self::SelfMember(lexer.eat_expect_id()),
|
||||||
Token::ParanOpen => {
|
Token::ParanOpen => {
|
||||||
|
@ -373,6 +380,12 @@ impl<'a> Expr<'a> {
|
||||||
_ => lexer.panic_message("Unexpected token"),
|
_ => lexer.panic_message("Unexpected token"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut lhs = if let Some(op) = unary_op {
|
||||||
|
Self::UnaryOp(op, Box::new(lhs))
|
||||||
|
} else {
|
||||||
|
lhs
|
||||||
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let tok = lexer.next().unwrap();
|
let tok = lexer.next().unwrap();
|
||||||
|
|
||||||
|
@ -468,6 +481,26 @@ impl BinaryOp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum UnaryOp {
|
||||||
|
BoolNot,
|
||||||
|
BitNot,
|
||||||
|
Negate,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UnaryOp {
|
||||||
|
pub fn from_token(tok: Token) -> Option<Self> {
|
||||||
|
use Token::*;
|
||||||
|
use UnaryOp::*;
|
||||||
|
match tok {
|
||||||
|
OpBoolNot => Some(BoolNot),
|
||||||
|
OpBitNot => Some(BitNot),
|
||||||
|
OpSub => Some(Negate),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Literal<'a> {
|
pub enum Literal<'a> {
|
||||||
BinaryInteger(&'a str),
|
BinaryInteger(&'a str),
|
||||||
|
@ -672,6 +705,11 @@ mod tests {
|
||||||
parse_expr("(1 + 2) * (3 / (4 + 5));")
|
parse_expr("(1 + 2) * (3 / (4 + 5));")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unary_ops() {
|
||||||
|
parse_expr("not false + -(2 + 3) * -1 / ~0xff;");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn members() {
|
fn members() {
|
||||||
parse_expr(".member1 * .member2;");
|
parse_expr(".member1 * .member2;");
|
||||||
|
|
Loading…
Reference in New Issue