From f3faf4e888c6b8a2320fe2ae7f3e404381ff14c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20=C4=8Euri=C5=A1?= Date: Sat, 6 Apr 2024 10:49:40 +0200 Subject: [PATCH] Change nested expression statement parsing logic --- src/lib.rs | 29 +++-- src/parser/grammar/expressions.rs | 2 +- src/parser/syntax_kind/generated.rs | 3 + src/syntax/ast/expr_ext.rs | 48 +++++++- src/syntax/ast/generated/nodes.rs | 184 +++++++++++++--------------- src/syntax/ast/operators.rs | 41 ++++++- src/syntax/tests/ast_src.rs | 3 + tests/test19.out | 2 +- tests/test20.out | 4 +- tests/test21.out | 2 +- tests/test22.out | 4 +- tests/test31.out | 2 +- tests/test33.out | 2 +- tests/test35.out | 2 +- tests/test36.out | 2 +- tests/test40.out | 2 +- tests/test41.out | 2 +- tests/test47.out | 4 +- yara.ungram | 32 ++--- 19 files changed, 227 insertions(+), 143 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 06db228..40d34cf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -155,23 +155,36 @@ fn api_walktrough() { // On the left hand side we have a LITERAL token let lhs = boolean_expr.lhs().unwrap(); - let lhs_literal = lhs.variable_token().unwrap(); - assert!(lhs_literal.kind() == SyntaxKind::VARIABLE); - assert_eq!(lhs_literal.text(), "$a"); + let lhs_literal = match &lhs { + Expression::BooleanTerm(l) => l, + _ => unreachable!(), + }; + assert!(lhs_literal.variable_token().unwrap().kind() == SyntaxKind::VARIABLE); + assert_eq!(lhs_literal.variable_token().unwrap().text(), "$a"); // On the right hand side we have a `BOOLEAN_EXPT` node let rhs = boolean_expr.rhs().unwrap(); // It contains prefix expression which is essentially a `BOOLEAN_TERM` node // in this case we have `NOT` node and nested `VARIABLE` node - let rhs_term = rhs.lhs().unwrap(); - assert!(rhs_term.not_token().is_some()); + let rhs_literal = match &rhs { + Expression::BooleanExpr(r) => r, + _ => unreachable!(), + }; + + let lhs_of_rhs = rhs_literal.lhs().unwrap(); + + let lhs = match &lhs_of_rhs { + Expression::BooleanTerm(l) => l, + _ => unreachable!(), + }; + + assert!(lhs.not_token().is_some()); assert!( - rhs_term.boolean_term().unwrap().bool_lit_token().unwrap().kind() - == SyntaxKind::BOOL_LIT + lhs.boolean_term().unwrap().bool_lit_token().unwrap().kind() == SyntaxKind::BOOL_LIT ); - assert_eq!(rhs_term.boolean_term().unwrap().bool_lit_token().unwrap().text(), "true"); + assert_eq!(lhs.boolean_term().unwrap().bool_lit_token().unwrap().text(), "true"); //Last but not least, in any point we can obtain the syntax node //for example let's obtain the syntax node for `EXPRESSION_STMT` diff --git a/src/parser/grammar/expressions.rs b/src/parser/grammar/expressions.rs index cb703cf..6f6c831 100644 --- a/src/parser/grammar/expressions.rs +++ b/src/parser/grammar/expressions.rs @@ -524,7 +524,7 @@ fn expr(p: &mut Parser, m: Option, bp: u8) -> Option { Associativity::Right => op_bp, }; expr(p, None, op_bp); - lhs = m.complete(p, EXPRESSION); + lhs = m.complete(p, EXPR_BODY); } Some(lhs) } diff --git a/src/parser/syntax_kind/generated.rs b/src/parser/syntax_kind/generated.rs index 91c65cc..09485ba 100644 --- a/src/parser/syntax_kind/generated.rs +++ b/src/parser/syntax_kind/generated.rs @@ -139,6 +139,9 @@ pub enum SyntaxKind { FUNCTION_CALL_EXPR, IN_RANGE, EXPR_INDEX, + TERM, + EXPR_BODY, + NESTED_EXPR, #[doc(hidden)] __LAST, } diff --git a/src/syntax/ast/expr_ext.rs b/src/syntax/ast/expr_ext.rs index 82a82e3..aae87ef 100644 --- a/src/syntax/ast/expr_ext.rs +++ b/src/syntax/ast/expr_ext.rs @@ -6,7 +6,7 @@ use crate::{ syntax::ast::{ self, - operators::{BinaryOp, LogicOp, UnaryOp}, + operators::{BinaryOp, ExprOp, LogicOp}, support, AstNode, AstToken, }, SyntaxToken, T, @@ -26,6 +26,44 @@ use crate::{ // } //} // +impl ast::ExprBody { + pub fn op_details(&self) -> Option<(SyntaxToken, BinaryOp)> { + self.syntax().children_with_tokens().filter_map(|it| it.into_token()).find_map(|c| { + let bin_op = match c.kind() { + T![+] => BinaryOp::ExprOp(ExprOp::Add), + T![-] => BinaryOp::ExprOp(ExprOp::Sub), + T![*] => BinaryOp::ExprOp(ExprOp::Mul), + T![backslash] => BinaryOp::ExprOp(ExprOp::Div), + T![%] => BinaryOp::ExprOp(ExprOp::Mod), + T![&] => BinaryOp::ExprOp(ExprOp::BitAnd), + T![|] => BinaryOp::ExprOp(ExprOp::BitOr), + T![^] => BinaryOp::ExprOp(ExprOp::BitXor), + T![<<] => BinaryOp::ExprOp(ExprOp::Shl), + T![>>] => BinaryOp::ExprOp(ExprOp::Shr), + T![.] => BinaryOp::ExprOp(ExprOp::Dot), + _ => return None, + }; + Some((c, bin_op)) + }) + } + + pub fn op_kind(&self) -> Option { + self.op_details().map(|t| t.1) + } + + pub fn op_token(&self) -> Option { + self.op_details().map(|t| t.0) + } + + pub fn lhs(&self) -> Option { + support::children(self.syntax()).next() + } + + pub fn rhs(&self) -> Option { + support::children(self.syntax()).nth(1) + } +} + impl ast::XorRange { pub fn lhs(&self) -> SyntaxToken { self.syntax() @@ -51,7 +89,7 @@ impl ast::HexJump { self.syntax() .children_with_tokens() .filter(|e| !e.kind().is_trivia()) - .nth(0) + .next() .and_then(|e| e.into_token()) .unwrap() } @@ -86,12 +124,12 @@ impl ast::BooleanExpr { self.op_details().map(|t| t.0) } - pub fn lhs(&self) -> Option { + pub fn lhs(&self) -> Option { support::children(self.syntax()).next() } - pub fn rhs(&self) -> Option { - support::children(self.syntax()).next() + pub fn rhs(&self) -> Option { + support::children(self.syntax()).nth(1) } pub fn sub_exprs(&self) -> (Option, Option) { diff --git a/src/syntax/ast/generated/nodes.rs b/src/syntax/ast/generated/nodes.rs index 3260c02..f07e0da 100644 --- a/src/syntax/ast/generated/nodes.rs +++ b/src/syntax/ast/generated/nodes.rs @@ -553,55 +553,6 @@ impl VariableAnchor { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Expr { - pub(crate) syntax: SyntaxNode, -} -impl Expr { - pub fn term(&self) -> Option { - support::child(&self.syntax) - } - pub fn plus_token(&self) -> Option { - support::token(&self.syntax, T![+]) - } - pub fn hyphen_token(&self) -> Option { - support::token(&self.syntax, T![-]) - } - pub fn star_token(&self) -> Option { - support::token(&self.syntax, T![*]) - } - pub fn backslash_token(&self) -> Option { - support::token(&self.syntax, T![backslash]) - } - pub fn percentage_token(&self) -> Option { - support::token(&self.syntax, T![%]) - } - pub fn ampersand_token(&self) -> Option { - support::token(&self.syntax, T![&]) - } - pub fn pipe_token(&self) -> Option { - support::token(&self.syntax, T![|]) - } - pub fn caret_token(&self) -> Option { - support::token(&self.syntax, T![^]) - } - pub fn shl_token(&self) -> Option { - support::token(&self.syntax, T![<<]) - } - pub fn shr_token(&self) -> Option { - support::token(&self.syntax, T![>>]) - } - pub fn tilde_token(&self) -> Option { - support::token(&self.syntax, T![~]) - } - pub fn dot_token(&self) -> Option { - support::token(&self.syntax, T![.]) - } - pub fn expr(&self) -> Option { - support::child(&self.syntax) - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct OfExpr { pub(crate) syntax: SyntaxNode, @@ -705,7 +656,7 @@ impl PrimaryExpr { pub fn hyphen_token(&self) -> Option { support::token(&self.syntax, T![-]) } - pub fn term(&self) -> Option { + pub fn expr(&self) -> Option { support::child(&self.syntax) } pub fn tilde_token(&self) -> Option { @@ -714,9 +665,6 @@ impl PrimaryExpr { pub fn l_paren_token(&self) -> Option { support::token(&self.syntax, T!['(']) } - pub fn expr(&self) -> Option { - support::child(&self.syntax) - } pub fn r_paren_token(&self) -> Option { support::token(&self.syntax, T![')']) } @@ -757,6 +705,12 @@ impl FunctionCallExpr { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ExprBody { + pub(crate) syntax: SyntaxNode, +} +impl ExprBody {} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct VariableCount { pub(crate) syntax: SyntaxNode, @@ -924,6 +878,16 @@ impl BooleanExprTuple { } } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct NestedExpr { + pub(crate) syntax: SyntaxNode, +} +impl NestedExpr { + pub fn expr(&self) -> Option { + support::child(&self.syntax) + } +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct VariableWildcard { pub(crate) syntax: SyntaxNode, @@ -944,16 +908,17 @@ pub enum Expression { } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum Term { +pub enum Expr { PrimaryExpr(PrimaryExpr), IndexingExpr(IndexingExpr), FunctionCallExpr(FunctionCallExpr), + ExprBody(ExprBody), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Iterable { Range(Range), - Expr(Expr), + NestedExpr(NestedExpr), ExprTuple(ExprTuple), } @@ -1397,9 +1362,9 @@ impl AstNode for VariableAnchor { &self.syntax } } -impl AstNode for Expr { +impl AstNode for OfExpr { fn can_cast(kind: SyntaxKind) -> bool { - kind == EXPR + kind == OF_EXPR } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -1412,9 +1377,9 @@ impl AstNode for Expr { &self.syntax } } -impl AstNode for OfExpr { +impl AstNode for ForExpr { fn can_cast(kind: SyntaxKind) -> bool { - kind == OF_EXPR + kind == FOR_EXPR } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -1427,9 +1392,9 @@ impl AstNode for OfExpr { &self.syntax } } -impl AstNode for ForExpr { +impl AstNode for PrimaryExpr { fn can_cast(kind: SyntaxKind) -> bool { - kind == FOR_EXPR + kind == PRIMARY_EXPR } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -1442,9 +1407,9 @@ impl AstNode for ForExpr { &self.syntax } } -impl AstNode for PrimaryExpr { +impl AstNode for IndexingExpr { fn can_cast(kind: SyntaxKind) -> bool { - kind == PRIMARY_EXPR + kind == INDEXING_EXPR } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -1457,9 +1422,9 @@ impl AstNode for PrimaryExpr { &self.syntax } } -impl AstNode for IndexingExpr { +impl AstNode for FunctionCallExpr { fn can_cast(kind: SyntaxKind) -> bool { - kind == INDEXING_EXPR + kind == FUNCTION_CALL_EXPR } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -1472,9 +1437,9 @@ impl AstNode for IndexingExpr { &self.syntax } } -impl AstNode for FunctionCallExpr { +impl AstNode for ExprBody { fn can_cast(kind: SyntaxKind) -> bool { - kind == FUNCTION_CALL_EXPR + kind == EXPR_BODY } fn cast(syntax: SyntaxNode) -> Option { if Self::can_cast(syntax.kind()) { @@ -1652,6 +1617,21 @@ impl AstNode for BooleanExprTuple { &self.syntax } } +impl AstNode for NestedExpr { + fn can_cast(kind: SyntaxKind) -> bool { + kind == NESTED_EXPR + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} impl AstNode for VariableWildcard { fn can_cast(kind: SyntaxKind) -> bool { kind == VARIABLE_WILDCARD @@ -1696,39 +1676,46 @@ impl AstNode for Expression { } } } -impl From for Term { - fn from(node: PrimaryExpr) -> Term { - Term::PrimaryExpr(node) +impl From for Expr { + fn from(node: PrimaryExpr) -> Expr { + Expr::PrimaryExpr(node) + } +} +impl From for Expr { + fn from(node: IndexingExpr) -> Expr { + Expr::IndexingExpr(node) } } -impl From for Term { - fn from(node: IndexingExpr) -> Term { - Term::IndexingExpr(node) +impl From for Expr { + fn from(node: FunctionCallExpr) -> Expr { + Expr::FunctionCallExpr(node) } } -impl From for Term { - fn from(node: FunctionCallExpr) -> Term { - Term::FunctionCallExpr(node) +impl From for Expr { + fn from(node: ExprBody) -> Expr { + Expr::ExprBody(node) } } -impl AstNode for Term { +impl AstNode for Expr { fn can_cast(kind: SyntaxKind) -> bool { - matches!(kind, PRIMARY_EXPR | INDEXING_EXPR | FUNCTION_CALL_EXPR) + matches!(kind, PRIMARY_EXPR | INDEXING_EXPR | FUNCTION_CALL_EXPR | EXPR_BODY) } fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { - PRIMARY_EXPR => Term::PrimaryExpr(PrimaryExpr { syntax }), - INDEXING_EXPR => Term::IndexingExpr(IndexingExpr { syntax }), - FUNCTION_CALL_EXPR => Term::FunctionCallExpr(FunctionCallExpr { syntax }), + PRIMARY_EXPR => Expr::PrimaryExpr(PrimaryExpr { syntax }), + INDEXING_EXPR => Expr::IndexingExpr(IndexingExpr { syntax }), + FUNCTION_CALL_EXPR => Expr::FunctionCallExpr(FunctionCallExpr { syntax }), + EXPR_BODY => Expr::ExprBody(ExprBody { syntax }), _ => return None, }; Some(res) } fn syntax(&self) -> &SyntaxNode { match self { - Term::PrimaryExpr(it) => &it.syntax, - Term::IndexingExpr(it) => &it.syntax, - Term::FunctionCallExpr(it) => &it.syntax, + Expr::PrimaryExpr(it) => &it.syntax, + Expr::IndexingExpr(it) => &it.syntax, + Expr::FunctionCallExpr(it) => &it.syntax, + Expr::ExprBody(it) => &it.syntax, } } } @@ -1737,9 +1724,9 @@ impl From for Iterable { Iterable::Range(node) } } -impl From for Iterable { - fn from(node: Expr) -> Iterable { - Iterable::Expr(node) +impl From for Iterable { + fn from(node: NestedExpr) -> Iterable { + Iterable::NestedExpr(node) } } impl From for Iterable { @@ -1749,12 +1736,12 @@ impl From for Iterable { } impl AstNode for Iterable { fn can_cast(kind: SyntaxKind) -> bool { - matches!(kind, RANGE | EXPR | EXPR_TUPLE) + matches!(kind, RANGE | NESTED_EXPR | EXPR_TUPLE) } fn cast(syntax: SyntaxNode) -> Option { let res = match syntax.kind() { RANGE => Iterable::Range(Range { syntax }), - EXPR => Iterable::Expr(Expr { syntax }), + NESTED_EXPR => Iterable::NestedExpr(NestedExpr { syntax }), EXPR_TUPLE => Iterable::ExprTuple(ExprTuple { syntax }), _ => return None, }; @@ -1763,7 +1750,7 @@ impl AstNode for Iterable { fn syntax(&self) -> &SyntaxNode { match self { Iterable::Range(it) => &it.syntax, - Iterable::Expr(it) => &it.syntax, + Iterable::NestedExpr(it) => &it.syntax, Iterable::ExprTuple(it) => &it.syntax, } } @@ -1790,7 +1777,7 @@ impl std::fmt::Display for Expression { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for Term { +impl std::fmt::Display for Expr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) } @@ -1945,11 +1932,6 @@ impl std::fmt::Display for VariableAnchor { std::fmt::Display::fmt(self.syntax(), f) } } -impl std::fmt::Display for Expr { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::fmt::Display::fmt(self.syntax(), f) - } -} impl std::fmt::Display for OfExpr { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -1975,6 +1957,11 @@ impl std::fmt::Display for FunctionCallExpr { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for ExprBody { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for VariableCount { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) @@ -2030,6 +2017,11 @@ impl std::fmt::Display for BooleanExprTuple { std::fmt::Display::fmt(self.syntax(), f) } } +impl std::fmt::Display for NestedExpr { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self.syntax(), f) + } +} impl std::fmt::Display for VariableWildcard { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(self.syntax(), f) diff --git a/src/syntax/ast/operators.rs b/src/syntax/ast/operators.rs index 48671e7..f550ab7 100644 --- a/src/syntax/ast/operators.rs +++ b/src/syntax/ast/operators.rs @@ -4,14 +4,10 @@ use std::fmt; -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum UnaryOp { - Not, -} - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum BinaryOp { LogicOp(LogicOp), + ExprOp(ExprOp), } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] @@ -20,6 +16,21 @@ pub enum LogicOp { Or, } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum ExprOp { + Add, + Sub, + Mul, + Div, + Mod, + BitAnd, + BitOr, + BitXor, + Shl, + Shr, + Dot, +} + impl fmt::Display for LogicOp { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let res = match self { @@ -30,10 +41,30 @@ impl fmt::Display for LogicOp { } } +impl fmt::Display for ExprOp { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let res = match self { + ExprOp::Add => "+", + ExprOp::Sub => "-", + ExprOp::Mul => "*", + ExprOp::Div => "\\", + ExprOp::Mod => "%", + ExprOp::BitAnd => "&", + ExprOp::BitOr => "|", + ExprOp::BitXor => "^", + ExprOp::Shl => "<<", + ExprOp::Shr => ">>", + ExprOp::Dot => ".", + }; + f.write_str(res) + } +} + impl fmt::Display for BinaryOp { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { BinaryOp::LogicOp(op) => fmt::Display::fmt(op, f), + BinaryOp::ExprOp(op) => fmt::Display::fmt(op, f), } } } diff --git a/src/syntax/tests/ast_src.rs b/src/syntax/tests/ast_src.rs index dba7168..ec0799c 100644 --- a/src/syntax/tests/ast_src.rs +++ b/src/syntax/tests/ast_src.rs @@ -141,6 +141,9 @@ pub(crate) const KINDS_SRC: KindsSrc = KindsSrc { "FUNCTION_CALL_EXPR", "IN_RANGE", "EXPR_INDEX", + "TERM", + "EXPR_BODY", + "NESTED_EXPR", ], }; diff --git a/tests/test19.out b/tests/test19.out index 71a4d7b..15ba758 100644 --- a/tests/test19.out +++ b/tests/test19.out @@ -41,7 +41,7 @@ SOURCE_FILE@0..154 WHITESPACE@132..133 " " BOOLEAN_EXPR@133..138 BOOLEAN_TERM@133..138 - EXPRESSION@133..138 + EXPR_BODY@133..138 PRIMARY_EXPR@133..134 INT_LIT@133..134 "9" WHITESPACE@134..135 " " diff --git a/tests/test20.out b/tests/test20.out index 09f2648..bd79fe2 100644 --- a/tests/test20.out +++ b/tests/test20.out @@ -40,13 +40,13 @@ SOURCE_FILE@0..150 WHITESPACE@132..133 " " BOOLEAN_EXPR@133..147 BOOLEAN_TERM@133..147 - EXPRESSION@133..147 + EXPR_BODY@133..147 PRIMARY_EXPR@133..134 INT_LIT@133..134 "9" WHITESPACE@134..135 " " PLUS@135..136 "+" WHITESPACE@136..137 " " - EXPRESSION@137..147 + EXPR_BODY@137..147 PRIMARY_EXPR@137..138 INT_LIT@137..138 "0" WHITESPACE@138..139 " " diff --git a/tests/test21.out b/tests/test21.out index 40a1fa8..a495713 100644 --- a/tests/test21.out +++ b/tests/test21.out @@ -16,7 +16,7 @@ SOURCE_FILE@0..55 EXPRESSION_STMT@41..52 BOOLEAN_TERM@41..52 EXPRESSION@41..52 - EXPRESSION@41..46 + EXPR_BODY@41..46 PRIMARY_EXPR@41..42 INT_LIT@41..42 "9" WHITESPACE@42..43 " " diff --git a/tests/test22.out b/tests/test22.out index cc7a1d3..991ded8 100644 --- a/tests/test22.out +++ b/tests/test22.out @@ -45,7 +45,7 @@ SOURCE_FILE@0..144 BOOLEAN_EXPR@83..107 BOOLEAN_TERM@83..94 EXPRESSION@83..94 - EXPRESSION@83..88 + EXPR_BODY@83..88 PRIMARY_EXPR@83..84 INT_LIT@83..84 "9" WHITESPACE@84..85 " " @@ -80,7 +80,7 @@ SOURCE_FILE@0..144 BOOLEAN_EXPR@118..141 BOOLEAN_TERM@118..141 EXPRESSION@118..141 - EXPRESSION@118..126 + EXPR_BODY@118..126 PRIMARY_EXPR@118..121 FLOAT_LIT@118..121 "1.1" WHITESPACE@121..122 " " diff --git a/tests/test31.out b/tests/test31.out index 461b418..6b36457 100644 --- a/tests/test31.out +++ b/tests/test31.out @@ -39,7 +39,7 @@ SOURCE_FILE@0..107 BOOLEAN_TERM@99..104 PRIMARY_EXPR@99..104 L_PAREN@99..100 "(" - EXPRESSION@100..103 + EXPR_BODY@100..103 PRIMARY_EXPR@100..101 INT_LIT@100..101 "1" PLUS@101..102 "+" diff --git a/tests/test33.out b/tests/test33.out index 57e32f6..5c4c268 100644 --- a/tests/test33.out +++ b/tests/test33.out @@ -43,7 +43,7 @@ SOURCE_FILE@0..162 QUANTIFIER@99..104 PRIMARY_EXPR@99..104 L_PAREN@99..100 "(" - EXPRESSION@100..103 + EXPR_BODY@100..103 PRIMARY_EXPR@100..101 INT_LIT@100..101 "1" PLUS@101..102 "+" diff --git a/tests/test35.out b/tests/test35.out index 5deb27d..4d86e59 100644 --- a/tests/test35.out +++ b/tests/test35.out @@ -53,7 +53,7 @@ SOURCE_FILE@0..122 BOOLEAN_TERM@112..119 PRIMARY_EXPR@112..119 L_PAREN@112..113 "(" - EXPRESSION@113..118 + EXPR_BODY@113..118 PRIMARY_EXPR@113..114 INT_LIT@113..114 "9" WHITESPACE@114..115 " " diff --git a/tests/test36.out b/tests/test36.out index 22c71ca..50ee957 100644 --- a/tests/test36.out +++ b/tests/test36.out @@ -56,7 +56,7 @@ SOURCE_FILE@0..124 BOOLEAN_TERM@114..121 PRIMARY_EXPR@114..121 L_PAREN@114..115 "(" - EXPRESSION@115..120 + EXPR_BODY@115..120 PRIMARY_EXPR@115..116 INT_LIT@115..116 "9" WHITESPACE@116..117 " " diff --git a/tests/test40.out b/tests/test40.out index 1dfc779..53dddd8 100644 --- a/tests/test40.out +++ b/tests/test40.out @@ -14,7 +14,7 @@ SOURCE_FILE@0..68 EXPRESSION_STMT@35..66 BOOLEAN_TERM@35..66 EXPRESSION@35..66 - EXPRESSION@35..49 + EXPR_BODY@35..49 INDEXING_EXPR@35..45 PRIMARY_EXPR@35..42 IDENTIFIER@35..38 "foo" diff --git a/tests/test41.out b/tests/test41.out index e829325..54b11e8 100644 --- a/tests/test41.out +++ b/tests/test41.out @@ -13,7 +13,7 @@ SOURCE_FILE@0..53 WHITESPACE@26..35 "\n " EXPRESSION_STMT@35..51 BOOLEAN_TERM@35..51 - EXPRESSION@35..51 + EXPR_BODY@35..51 FUNCTION_CALL_EXPR@35..47 PRIMARY_EXPR@35..42 IDENTIFIER@35..38 "foo" diff --git a/tests/test47.out b/tests/test47.out index 82e57ea..caad33e 100644 --- a/tests/test47.out +++ b/tests/test47.out @@ -46,7 +46,7 @@ SOURCE_FILE@0..95 WHITESPACE@61..62 " " EQ@62..64 "==" WHITESPACE@64..65 " " - EXPRESSION@65..74 + EXPR_BODY@65..74 PRIMARY_EXPR@65..66 INT_LIT@65..66 "1" WHITESPACE@66..67 " " @@ -63,7 +63,7 @@ SOURCE_FILE@0..95 WHITESPACE@74..75 " " EQ@75..77 "==" WHITESPACE@77..78 " " - EXPRESSION@78..87 + EXPR_BODY@78..87 PRIMARY_EXPR@78..79 INT_LIT@78..79 "2" WHITESPACE@79..80 " " diff --git a/yara.ungram b/yara.ungram index 681e1a7..5608e08 100644 --- a/yara.ungram +++ b/yara.ungram @@ -110,11 +110,11 @@ Expression = | BooleanTerm BooleanExpr = - lhs:BooleanExpr + lhs:Expression op:( 'and'| 'or' ) - rhs:BooleanExpr + rhs:Expression BooleanTerm = 'variable' VariableAnchor? @@ -133,18 +133,18 @@ BooleanTerm = | ForExpr Expr = - Term -| Term - ( - '+' | '-' | '*' | 'backslash' | '%' | - '&' | '|' | '^' | '<<' | '>>' | '~' | '.' - ) - Expr - -Term = PrimaryExpr | IndexingExpr | FunctionCallExpr +| ExprBody + +ExprBody = + lhs:Expr + op:( + '+' | '-' | '*' | 'backslash' | '%' | + '&' | '|' | '^' | '<<' | '>>' | '.' + ) + rhs:Expr PrimaryExpr = 'float_lit' @@ -156,8 +156,8 @@ PrimaryExpr = | 'filesize' | 'entrypoint' | RegexPattern -| '-' Term -| '~' Term +| '-' Expr +| '~' Expr | '(' Expr ')' | (IdentifierNode ('.' IdentifierNode)*) @@ -209,7 +209,11 @@ Quantifier = | PrimaryExpr '%'? Iterable = - Range | Expr | ExprTuple + Range +| NestedExpr +| ExprTuple + +NestedExpr = Expr PatternIdentTuple = '(' (VariableWildcard (',' VariableWildcard)*) ')'