Unary operators

This commit is contained in:
mars 2022-03-02 14:18:40 -07:00
parent 8c2af9ab61
commit 1f66a5f94b
1 changed files with 39 additions and 1 deletions

View File

@ -339,6 +339,7 @@ type ExprPair<'a> = Box<(Expr<'a>, Expr<'a>)>;
#[derive(Debug)]
pub enum Expr<'a> {
BinaryOp(BinaryOp, ExprPair<'a>),
UnaryOp(UnaryOp, Box<Expr<'a>>),
Literal(Literal<'a>),
Local(&'a str),
Member(&'a str, Box<Expr<'a>>),
@ -350,7 +351,13 @@ pub enum Expr<'a> {
impl<'a> Expr<'a> {
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::Dot => Self::SelfMember(lexer.eat_expect_id()),
Token::ParanOpen => {
@ -373,6 +380,12 @@ impl<'a> Expr<'a> {
_ => lexer.panic_message("Unexpected token"),
};
let mut lhs = if let Some(op) = unary_op {
Self::UnaryOp(op, Box::new(lhs))
} else {
lhs
};
loop {
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)]
pub enum Literal<'a> {
BinaryInteger(&'a str),
@ -672,6 +705,11 @@ mod tests {
parse_expr("(1 + 2) * (3 / (4 + 5));")
}
#[test]
fn unary_ops() {
parse_expr("not false + -(2 + 3) * -1 / ~0xff;");
}
#[test]
fn members() {
parse_expr(".member1 * .member2;");