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 { ast.UnaryExpr {
g.expr(it.left) g.expr(it.left)
g.write(' $it.op ') g.write(it.op.str())
} }
ast.StringLiteral { ast.StringLiteral {
g.write('tos3("$it.val")') g.write('tos3("$it.val")')

View File

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

View File

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

View File

@ -28,8 +28,7 @@ pub fn parse_stmt(text string, table &table.Table) ast.Stmt {
scanner: s scanner: s
table: table table: table
} }
p.next() p.read_first_token()
p.next()
return p.stmt() return p.stmt()
} }
@ -304,13 +303,10 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
p.check(.rpar) p.check(.rpar)
} }
else { else {
p.next()
if p.tok.is_unary() { if p.tok.is_unary() {
expr,_ := p.expr(token.highest_prec) expr,_ := p.expr(token.highest_prec)
node = ast.UnaryExpr{ node = ast.UnaryExpr{
// left: p.expr(token.highest_prec)
left: expr left: expr
op: p.tok.kind
} }
} }
else { else {
@ -323,7 +319,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) {
prev_tok := p.tok prev_tok := p.tok
p.next() p.next()
mut t2 := types.Type{} mut t2 := types.Type{}
// left denotation (infix) // left denotation (infix / postfix)
if prev_tok.is_right_assoc() { if prev_tok.is_right_assoc() {
mut expr := ast.Expr{} mut expr := ast.Expr{}
expr,t2 = p.expr(prev_tok.precedence() - 1) 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') // println(t2.name + 'OOO')
if !types.check(&typ, &t2) { if !types.check(&typ, &t2) {
println('tok: $prev_tok.str()')
p.error('cannot convert `$t2.name` to `$typ.name`') p.error('cannot convert `$t2.name` to `$typ.name`')
} }
} }
else if prev_tok.is_left_assoc() { else if prev_tok.is_left_assoc() {
mut expr := ast.Expr{} // postfix (`++` | `--`)
expr,t2 = p.expr(prev_tok.precedence()) if prev_tok.kind in [.inc, .dec] {
op := prev_tok.kind node = ast.UnaryExpr{
if op in [.gt, .lt, .ge, .le] { left: node
typ = types.bool_type op: prev_tok.kind
} }
else { } else {
typ = t2 mut expr := ast.Expr{}
} expr,t2 = p.expr(prev_tok.precedence())
// println(t2.name + '222') op := prev_tok.kind
node = ast.BinaryExpr{ if prev_tok.is_relational() {
left: node typ = types.bool_type
op: prev_tok.kind }
right: expr 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 // Representation of highest and lowest precedence
pub const ( pub const (
lowest_prec = 0 lowest_prec = 0
highest_prec = 7 highest_prec = 8
) )
// Precedence returns a tokens precedence if defined, otherwise lowest_prec // Precedence returns a tokens precedence if defined, otherwise lowest_prec
pub fn (tok Token) precedence() int { pub fn (tok Token) precedence() int {
match tok.kind { match tok.kind {
// `++` | `--`
.inc, .dec {
return 7
}
// `*` | `/` | `%` | `<<` | `>>` | `&` // `*` | `/` | `%` | `<<` | `>>` | `&`
.mul, .div, .left_shift, .righ_shift, .amp { .mul, .div, .left_shift, .righ_shift, .amp {
return 7 return 6
} }
// `+` | `-` | `|` | `^` // `+` | `-` | `|` | `^`
.plus, .minus, .pipe, .xor { .plus, .minus, .pipe, .xor {
return 6 return 5
} }
// `==` | `!=` | `<` | `<=` | `>` | `>=` // `==` | `!=` | `<` | `<=` | `>` | `>=`
.eq, .ne, .lt, .le, .gt, .ge { .eq, .ne, .lt, .le, .gt, .ge {
return 5 return 4
} }
// `&&` // `&&`
.and { .and {
return 4 return 3
} }
// `||` // `||`
.logical_or { .logical_or {
return 3 return 2
} }
// /.plus_assign { // /.plus_assign {
// /return 2 // /return 2
@ -358,10 +362,14 @@ pub fn (tok Token) is_unary() bool {
pub fn (tok Token) is_left_assoc() bool { pub fn (tok Token) is_left_assoc() bool {
return tok.kind in [ return tok.kind in [
// .number, // .number,
// `++` | `--`
.inc, .dec,
// `*` | `/` | `%` // `*` | `/` | `%`
.mul, .div, .mod, .mul, .div, .mod,
// `^` | `||` | `&` < > <= >= // `^` | `||` | `&`
.xor, .logical_or, .and, .gt, .lt, .le, .ge, .xor, .logical_or, .and,
// `<` | `<=` | `>` | `>=`
.lt, .le, .gt, .ge,
// `,` // `,`
.comma] .comma]
} }
@ -369,8 +377,8 @@ pub fn (tok Token) is_left_assoc() bool {
// is_right_assoc returns true if the token is right associative // is_right_assoc returns true if the token is right associative
pub fn (tok Token) is_right_assoc() bool { pub fn (tok Token) is_right_assoc() bool {
return tok.kind in [ return tok.kind in [
// `+` | `-` | `!` | `++` | `--` // `+` | `-` | `!`
.plus, .minus, .not, .inc, .dec, .plus, .minus, .not,
// `=` | `+=` | `-=` | `*=` | `/=` // `=` | `+=` | `-=` | `*=` | `/=`
.assign, .plus_assign, .minus_assign, .mult_assign, .div_assign, .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] .and_assign, .xor_assign, .or_assign]
} }
pub fn (tok Token) is_relational() bool {
return tok.kind in [
// `<` | `<=` | `>` | `>=`
.lt, .le, .gt, .ge]
}