From fe8a6abb41c1f4c09694ffb1f5487a8879c0e60e Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Thu, 26 Dec 2019 13:40:18 +1100 Subject: [PATCH] compiler2: update operator precedence and associativity (#3218) --- vlib/compiler2/ast/ast.v | 56 +++++++++++++++-------------- vlib/compiler2/parser/parser_test.v | 5 ++- vlib/compiler2/token/token.v | 37 +++++++++++++++---- 3 files changed, 64 insertions(+), 34 deletions(-) diff --git a/vlib/compiler2/ast/ast.v b/vlib/compiler2/ast/ast.v index 9deab68fcb..2201d7ba9a 100644 --- a/vlib/compiler2/ast/ast.v +++ b/vlib/compiler2/ast/ast.v @@ -13,10 +13,12 @@ struct Foo {} // pub type Expr = Foo | IfExpr | BinaryExpr | IntegerExpr pub type Expr = Foo | IfExpr | BinaryExpr | ScalarExpr | UnaryExpr -// pub struct IntegerExpr { -// pub: -// val int -// } +/* +pub struct IntegerExpr { +pub: + val int +} +*/ /* pub enum Expr { @@ -92,28 +94,30 @@ pub fn (x Expr) str() string { } } -// enum BinaryOp { -// sum -// difference -// product -// quotient -// remainder -// bitwise_and -// bitwise_or -// bitwise_xor -// left_shift -// right_shift +/* +enum BinaryOp { + sum + difference + product + quotient + remainder + bitwise_and + bitwise_or + bitwise_xor + left_shift + right_shift -// equality -// inequality -// less_than -// less_than_or_equal -// more_than -// more_than_or_equal + equality + inequality + less_than + less_than_or_equal + more_than + more_than_or_equal -// in_check + in_check -// //These are suffixed with `bool` to prevent conflict with the keyword `or` -// and_bool -// or_bool -// } + //These are suffixed with `bool` to prevent conflict with the keyword `or` + and_bool + or_bool +} +*/ diff --git a/vlib/compiler2/parser/parser_test.v b/vlib/compiler2/parser/parser_test.v index 72d5d0ff57..3597ed6667 100644 --- a/vlib/compiler2/parser/parser_test.v +++ b/vlib/compiler2/parser/parser_test.v @@ -12,12 +12,15 @@ fn test_parser() { println('\n') text_expr := [ + '1 += 2', + '1.2 + 3.4', '4 + 4', '1 + 2 * 5', '(2 * 3) / 2', '3 + (7 * 6)', '2 ^ 8 * (7 * 6)', - '(2) + (17*2-30) * (5)+2 - (8/2)*4' + '20 + (10 * 15) / 5', // 50 + '(2) + (17*2-30) * (5)+2 - (8/2)*4' // 8 ] for s in text_expr { // print using str method diff --git a/vlib/compiler2/token/token.v b/vlib/compiler2/token/token.v index 5946ad91f3..de5b538ce4 100644 --- a/vlib/compiler2/token/token.v +++ b/vlib/compiler2/token/token.v @@ -313,10 +313,16 @@ const ( // Precedence returns a tokens precedence if defined, otherwise lowest_prec pub fn (tok Token) precedence() int { match tok { - .plus, .minus { return 4 } - .mul, .div { return 4 } - .xor { return 6 } - .mod {return 7 } + // `*` | `/` | `%` | `<<` | `>>` | `&` + .mul, .div, .left_shift, .righ_shift, .amp { return 7 } + // `+` | `-` | `|` | `^` + .plus, .minus, .pipe, .xor { return 6 } + // `==` | `!=` | `<` | `<=` | `>` | `>=` + .eq, .ne, .lt, .le, .gt, .ge { return 5 } + // `&&` + .and { return 4 } + // `||` + .logical_or { return 3 } else { return lowest_prec } } } @@ -332,15 +338,25 @@ pub fn (tok Token) is_scalar() bool { // is_unary returns true if the token can be in a unary expression pub fn (tok Token) is_unary() bool { match tok { - .plus, .minus { return true } + // `+` | `-` | `!` | `~` | `*` | `&` + .plus, .minus, .not, .bit_not, .mul, .amp { return true } else { return false } } } +// NOTE: do we need this for all tokens (is_left_assoc / is_right_assoc), +// or only ones with the same precedence? + // is_left_assoc returns true if the token is left associative pub fn (tok Token) is_left_assoc() bool { match tok { - .number, .plus, .minus, .mul, .div, .mod { return true } + // .number, + // `*` | `/` | `%` + .mul, .div, .mod, + // `^` | `||` | `&` + .xor, .logical_or, .and, + // `,` + .comma { return true } else { return false } } } @@ -348,7 +364,14 @@ pub fn (tok Token) is_left_assoc() bool { // is_right_assoc returns true if the token is right associative pub fn (tok Token) is_right_assoc() bool { match tok { - .xor { return true } + // `+` | `-` | `!` | `++` | `--` + .plus, .minus, .not, .inc, .dec, + // `=` | `+=` | `-=` | `*=` | `/=` + .assign, .plus_assign, .minus_assign, .mult_assign, .div_assign, + // `%=` | `>>=` | `<<=` + .mod_assign, .righ_shift_assign, .left_shift_assign, + // `&=` | `^=` | `|=` + .and_assign, .xor_assign, .or_assign { return true } else { return false } } }