diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 5e681728d..2ad291aef 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -381,6 +381,9 @@ advance_token :: proc(p: ^Parser) -> tokenizer.Token { #partial switch p.curr_tok.kind { case .Comment: consume_comment_groups(p, prev) + if p.curr_tok.kind == .Semicolon && p.expr_level > 0 && p.curr_tok.text == "\n" { + advance_token(p) + } case .Semicolon: if p.expr_level > 0 && p.curr_tok.text == "\n" { advance_token(p) @@ -3622,7 +3625,9 @@ parse_binary_expr :: proc(p: ^Parser, lhs: bool, prec_in: int) -> ^ast.Expr { case .If, .When: if p.prev_tok.pos.line < op.pos.line { // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition - break loop + if p.expr_level <= 0 { + break loop + } } } diff --git a/src/parser.cpp b/src/parser.cpp index 03e9073ca..0e7ec1d60 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1529,6 +1529,9 @@ gb_internal Token advance_token(AstFile *f) { switch (f->curr_token.kind) { case Token_Comment: consume_comment_groups(f, prev); + if (f->curr_token.kind == Token_Semicolon && ignore_newlines(f) && f->curr_token.string == "\n") { + advance_token(f); + } break; case Token_Semicolon: if (ignore_newlines(f) && f->curr_token.string == "\n") { @@ -3582,7 +3585,9 @@ gb_internal Ast *parse_binary_expr(AstFile *f, bool lhs, i32 prec_in) { case Token_when: if (prev.pos.line < op.pos.line) { // NOTE(bill): Check to see if the `if` or `when` is on the same line of the `lhs` condition - goto loop_end; + if (f->expr_level <= 0) { + goto loop_end; + } } break; } diff --git a/tests/core/odin/test_parser.odin b/tests/core/odin/test_parser.odin index 3fb15d893..e60a9f8f0 100644 --- a/tests/core/odin/test_parser.odin +++ b/tests/core/odin/test_parser.odin @@ -131,3 +131,78 @@ my_func :: proc (cond: bool, a: string, b: string) -> string { testing.expect(t, ok, "bad parse") testing.expect(t, file.syntax_error_count == 0, "should contain zero errors") } + + +@test +test_parse_multiline_ternary_infix_with_comment :: proc(t: ^testing.T) { + context.allocator = context.temp_allocator + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + file := ast.File{ + fullpath = "test.odin", + src = ` + package main + + my_func :: proc (cond: bool, a: string, b: string) -> string { + out := ( + cond + ? a // This is a comment! + : b + ) + return out + } + `, + } + + p := parser.default_parser() + + p.err = proc(pos: tokenizer.Pos, format: string, args: ..any) { + message := fmt.tprintf(format, ..args) + log.errorf("%s(%d:%d): %s", pos.file, pos.line, pos.column, message) + } + + p.warn = proc(pos: tokenizer.Pos, format: string, args: ..any) { + message := fmt.tprintf(format, ..args) + log.warnf("%s(%d:%d): %s", pos.file, pos.line, pos.column, message) + } + + ok := parser.parse_file(&p, &file) + testing.expect(t, ok, "bad parse") + testing.expect(t, file.syntax_error_count == 0, "should contain zero errors") +} + +@test +test_parse_ternary_if_statements_with_comment :: proc(t: ^testing.T) { + context.allocator = context.temp_allocator + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + file := ast.File{ + fullpath = "test.odin", + src = ` + package main + + my_func :: proc (cond: bool, a: string, b: string) -> string { + out := ( + cond + if a // This is a comment! + else b + ) + return out + } + `, + } + + p := parser.default_parser() + + p.err = proc(pos: tokenizer.Pos, format: string, args: ..any) { + message := fmt.tprintf(format, ..args) + log.errorf("%s(%d:%d): %s", pos.file, pos.line, pos.column, message) + } + + p.warn = proc(pos: tokenizer.Pos, format: string, args: ..any) { + message := fmt.tprintf(format, ..args) + log.warnf("%s(%d:%d): %s", pos.file, pos.line, pos.column, message) + } + + ok := parser.parse_file(&p, &file) + testing.expect(t, ok, "bad parse") + testing.expect(t, file.syntax_error_count == 0, "should contain zero errors") +}