Skip to content

Commit

Permalink
parser: fix operator precedence
Browse files Browse the repository at this point in the history
`1 + 2 *3` is currently evaluated as `(1+2)*3` while it should be `1 +
(2*3)`. This is because the additive and multiplicative operators we're
mixed in the same rule.

Tests are only implemented in runtime right now as doing this in the
parser is a bit tedious to write and it doesn't actually guaranteed the
correct output.

Fixes #2095
  • Loading branch information
fbs committed Dec 21, 2021
1 parent 2b7e38a commit 1b8b64e
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ and this project adheres to
#### Deprecated
#### Removed
#### Fixed

- Fix precedence of multiplicative operations
- [#2096](https//github.com/iovisor/bpftrace/pull/2096)

#### Tools
#### Documentation

Expand Down
24 changes: 14 additions & 10 deletions src/parser.yy
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ void yyerror(bpftrace::Driver &driver, const char *s);
%type <ast::AttachPoint *> attach_point
%type <ast::AttachPointList *> attach_points
%type <ast::Call *> call
%type <ast::Expression *> and_expr arith_expr primary_expr cast_expr conditional_expr equality_expr expr logical_and_expr
%type <ast::Expression *> and_expr addi_expr primary_expr cast_expr conditional_expr equality_expr expr logical_and_expr muli_expr
%type <ast::Expression *> logical_or_expr map_or_var or_expr postfix_expr relational_expr shift_expr tuple_access_expr unary_expr xor_expr
%type <ast::ExpressionList *> vargs
%type <ast::Integer *> int
Expand Down Expand Up @@ -442,18 +442,22 @@ relational_expr:
;

shift_expr:
arith_expr { $$ = $1; }
| shift_expr LEFT arith_expr { $$ = new ast::Binop($1, ast::Operator::LEFT, $3, @2); }
| shift_expr RIGHT arith_expr { $$ = new ast::Binop($1, ast::Operator::RIGHT, $3, @2); }
addi_expr { $$ = $1; }
| shift_expr LEFT addi_expr { $$ = new ast::Binop($1, ast::Operator::LEFT, $3, @2); }
| shift_expr RIGHT addi_expr { $$ = new ast::Binop($1, ast::Operator::RIGHT, $3, @2); }
;

arith_expr:
muli_expr:
cast_expr { $$ = $1; }
| arith_expr PLUS cast_expr { $$ = new ast::Binop($1, ast::Operator::PLUS, $3, @2); }
| arith_expr MINUS cast_expr { $$ = new ast::Binop($1, ast::Operator::MINUS, $3, @2); }
| arith_expr MUL cast_expr { $$ = new ast::Binop($1, ast::Operator::MUL, $3, @2); }
| arith_expr DIV cast_expr { $$ = new ast::Binop($1, ast::Operator::DIV, $3, @2); }
| arith_expr MOD cast_expr { $$ = new ast::Binop($1, ast::Operator::MOD, $3, @2); }
| muli_expr MUL cast_expr { $$ = new ast::Binop($1, ast::Operator::MUL, $3, @2); }
| muli_expr DIV cast_expr { $$ = new ast::Binop($1, ast::Operator::DIV, $3, @2); }
| muli_expr MOD cast_expr { $$ = new ast::Binop($1, ast::Operator::MOD, $3, @2); }
;

addi_expr:
muli_expr { $$ = $1; }
| addi_expr PLUS muli_expr { $$ = new ast::Binop($1, ast::Operator::PLUS, $3, @2); }
| addi_expr MINUS muli_expr { $$ = new ast::Binop($1, ast::Operator::MINUS, $3, @2); }
;

cast_expr:
Expand Down
19 changes: 19 additions & 0 deletions tests/runtime/precedence
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
NAME operator_precedence_1
PROG BEGIN { print(1 + 2 * 3 ); exit() }
EXPECT 7
TIMEOUT 5

NAME operator_precedence_2
PROG BEGIN { print(1 + 2 * 3 + 1); exit() }
EXPECT 8
TIMEOUT 5

NAME operator_precedence_3
PROG BEGIN { print(1 + 2 * 3 + 1 * 10); exit() }
EXPECT 17
TIMEOUT 5

NAME operator_precedence_3
PROG BEGIN { print(1 + 2 / 2 * 3); exit() }
EXPECT 4
TIMEOUT 5

0 comments on commit 1b8b64e

Please sign in to comment.