v: fix postfix unary `++` `--` operators & some cleanup

pull/3280/head
joe-conigliaro 2019-12-31 01:06:56 +11:00 committed by Alexander Medvednikov
parent 26ee09c9bb
commit d07953b0f0
5 changed files with 52 additions and 31 deletions

View File

@ -111,7 +111,7 @@ fn (g mut Gen) expr(node ast.Expr) {
}
ast.UnaryExpr {
g.expr(it.left)
g.write(' $it.op ')
g.write(it.op.str())
}
ast.StringLiteral {
g.write('tos3("$it.val")')

View File

@ -1,4 +1,5 @@
int main() {
int a = 10;
a++;
return 0;
}

View File

@ -1,3 +1,4 @@
fn main() {
a := 10
a++
}

View File

@ -28,8 +28,7 @@ pub fn parse_stmt(text string, table &table.Table) ast.Stmt {
scanner: s
table: table
}
p.next()
p.next()
p.read_first_token()
return p.stmt()
}
@ -304,13 +303,10 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
p.check(.rpar)
}
else {
p.next()
if p.tok.is_unary() {
expr,_ := p.expr(token.highest_prec)
node = ast.UnaryExpr{
// left: p.expr(token.highest_prec)
left: expr
op: p.tok.kind
}
}
else {
@ -323,7 +319,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
prev_tok := p.tok
p.next()
mut t2 := types.Type{}
// left denotation (infix)
// left denotation (infix / postfix)
if prev_tok.is_right_assoc() {
mut expr := ast.Expr{}
expr,t2 = p.expr(prev_tok.precedence() - 1)
@ -334,24 +330,33 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
}
// println(t2.name + 'OOO')
if !types.check(&typ, &t2) {
println('tok: $prev_tok.str()')
p.error('cannot convert `$t2.name` to `$typ.name`')
}
}
else if prev_tok.is_left_assoc() {
mut expr := ast.Expr{}
expr,t2 = p.expr(prev_tok.precedence())
op := prev_tok.kind
if op in [.gt, .lt, .ge, .le] {
typ = types.bool_type
}
else {
typ = t2
}
// println(t2.name + '222')
node = ast.BinaryExpr{
left: node
op: prev_tok.kind
right: expr
// postfix (`++` | `--`)
if prev_tok.kind in [.inc, .dec] {
node = ast.UnaryExpr{
left: node
op: prev_tok.kind
}
} else {
mut expr := ast.Expr{}
expr,t2 = p.expr(prev_tok.precedence())
op := prev_tok.kind
if prev_tok.is_relational() {
typ = types.bool_type
}
else {
typ = t2
}
// println(t2.name + '222')
node = ast.BinaryExpr{
left: node
op: prev_tok.kind
right: expr
}
}
}
}

View File

@ -306,30 +306,34 @@ pub fn (t Token) str() string {
// Representation of highest and lowest precedence
pub const (
lowest_prec = 0
highest_prec = 7
highest_prec = 8
)
// Precedence returns a tokens precedence if defined, otherwise lowest_prec
pub fn (tok Token) precedence() int {
match tok.kind {
// `++` | `--`
.inc, .dec {
return 7
}
// `*` | `/` | `%` | `<<` | `>>` | `&`
.mul, .div, .left_shift, .righ_shift, .amp {
return 7
return 6
}
// `+` | `-` | `|` | `^`
.plus, .minus, .pipe, .xor {
return 6
return 5
}
// `==` | `!=` | `<` | `<=` | `>` | `>=`
.eq, .ne, .lt, .le, .gt, .ge {
return 5
return 4
}
// `&&`
.and {
return 4
return 3
}
// `||`
.logical_or {
return 3
return 2
}
// /.plus_assign {
// /return 2
@ -358,10 +362,14 @@ pub fn (tok Token) is_unary() bool {
pub fn (tok Token) is_left_assoc() bool {
return tok.kind in [
// .number,
// `++` | `--`
.inc, .dec,
// `*` | `/` | `%`
.mul, .div, .mod,
// `^` | `||` | `&` < > <= >=
.xor, .logical_or, .and, .gt, .lt, .le, .ge,
// `^` | `||` | `&`
.xor, .logical_or, .and,
// `<` | `<=` | `>` | `>=`
.lt, .le, .gt, .ge,
// `,`
.comma]
}
@ -369,8 +377,8 @@ 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 {
return tok.kind in [
// `+` | `-` | `!` | `++` | `--`
.plus, .minus, .not, .inc, .dec,
// `+` | `-` | `!`
.plus, .minus, .not,
// `=` | `+=` | `-=` | `*=` | `/=`
.assign, .plus_assign, .minus_assign, .mult_assign, .div_assign,
// `%=` | `>>=` | `<<=`
@ -378,3 +386,9 @@ pub fn (tok Token) is_right_assoc() bool {
// `&=` | `^=` | `|=`
.and_assign, .xor_assign, .or_assign]
}
pub fn (tok Token) is_relational() bool {
return tok.kind in [
// `<` | `<=` | `>` | `>=`
.lt, .le, .gt, .ge]
}