diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index dad71c9b0..88a5a1ee3 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -325,6 +325,7 @@ If_Stmt :: struct { init: ^Stmt, cond: ^Expr, body: ^Stmt, + else_pos: tokenizer.Pos, else_stmt: ^Stmt, } @@ -490,7 +491,7 @@ unparen_expr :: proc(expr: ^Expr) -> (val: ^Expr) { } for { e, ok := val.derived.(Paren_Expr); - if !ok { + if !ok || e.expr == nil { break; } val = e.expr; diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 7bd20c699..4e6fa1cb4 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -121,7 +121,7 @@ parse_file :: proc(p: ^Parser, file: ^ast.File) -> bool { } p.file = file; - tokenizer.init(&p.tok, file.src, file.fullpath); + tokenizer.init(&p.tok, file.src, file.fullpath, p.err); if p.tok.ch <= 0 { return true; } @@ -625,6 +625,8 @@ parse_if_stmt :: proc(p: ^Parser) -> ^ast.If_Stmt { skip_possible_newline_for_literal(p); } + else_tok := p.curr_tok.pos; + if allow_token(p, .Else) { #partial switch p.curr_tok.kind { case .If: @@ -650,6 +652,7 @@ parse_if_stmt :: proc(p: ^Parser) -> ^ast.If_Stmt { if_stmt.cond = cond; if_stmt.body = body; if_stmt.else_stmt = else_stmt; + if_stmt.else_pos = else_tok; return if_stmt; } @@ -784,6 +787,7 @@ parse_case_clause :: proc(p: ^Parser, is_type_switch: bool) -> ^ast.Case_Clause cc.list = list; cc.terminator = terminator; cc.body = stmts; + cc.case_pos = tok.pos; return cc; } @@ -845,6 +849,7 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt { ts := ast.new(ast.Type_Switch_Stmt, tok.pos, body.end); ts.tag = tag; ts.body = body; + ts.switch_pos = tok.pos; return ts; } else { cond := convert_stmt_to_expr(p, tag, "switch expression"); @@ -852,6 +857,7 @@ parse_switch_stmt :: proc(p: ^Parser) -> ^ast.Stmt { ts.init = init; ts.cond = cond; ts.body = body; + ts.switch_pos = tok.pos; return ts; } } @@ -1155,7 +1161,7 @@ parse_stmt :: proc(p: ^Parser) -> ^ast.Stmt { end := end_pos(tok); if len(results) > 0 { - end = results[len(results)-1].pos; + end = results[len(results)-1].end; } rs := ast.new(ast.Return_Stmt, tok.pos, end); diff --git a/core/odin/tokenizer/token.odin b/core/odin/tokenizer/token.odin index 731e375c9..3e6b51ba6 100644 --- a/core/odin/tokenizer/token.odin +++ b/core/odin/tokenizer/token.odin @@ -317,6 +317,8 @@ is_operator :: proc(kind: Token_Kind) -> bool { return true; case .In, .Not_In: return true; + case .If: + return true; } return false; } diff --git a/core/odin/tokenizer/tokenizer.odin b/core/odin/tokenizer/tokenizer.odin index d8fedf5fd..64a060850 100644 --- a/core/odin/tokenizer/tokenizer.odin +++ b/core/odin/tokenizer/tokenizer.odin @@ -266,7 +266,7 @@ scan_escape :: proc(t: ^Tokenizer) -> bool { n: int; base, max: u32; switch t.ch { - case 'a', 'b', 'e', 'f', 'n', 't', 'v', '\\', '\'', '\"': + case 'a', 'b', 'e', 'f', 'n', 't', 'v', 'r', '\\', '\'', '\"': advance_rune(t); return true;