|
113 | 113 | script_mode_start_token token.Token |
114 | 114 | generic_type_level int // to avoid infinite recursion segfaults due to compiler bugs in ensure_type_exists |
115 | 115 | main_already_defined bool // TODO move to checker |
| 116 | + is_vls bool |
116 | 117 | pub mut: |
117 | 118 | scanner &scanner.Scanner = unsafe { nil } |
118 | 119 | table &ast.Table = unsafe { nil } |
@@ -177,6 +178,7 @@ pub fn parse_text(text string, path string, mut table ast.Table, comments_mode s |
177 | 178 | scanner: scanner.new_scanner(text, comments_mode, pref_) |
178 | 179 | table: table |
179 | 180 | pref: pref_ |
| 181 | + is_vls: pref_.is_vls |
180 | 182 | scope: &ast.Scope{ |
181 | 183 | start_pos: 0 |
182 | 184 | parent: table.global_scope |
@@ -555,6 +557,10 @@ fn (mut p Parser) parse_block_no_scope(is_top_level bool) []ast.Stmt { |
555 | 557 | stmts << p.stmt(is_top_level) |
556 | 558 | count++ |
557 | 559 | if count % 100000 == 0 { |
| 560 | + if p.is_vls { |
| 561 | + // Stuck in VLS mode, exit |
| 562 | + return [] |
| 563 | + } |
558 | 564 | eprintln('parsed ${count} statements so far from fn ${p.cur_fn_name} ...') |
559 | 565 | } |
560 | 566 | if count > 1000000 { |
@@ -1043,6 +1049,13 @@ fn (mut p Parser) stmt(is_top_level bool) ast.Stmt { |
1043 | 1049 | pos: spos.extend(p.tok.pos()) |
1044 | 1050 | } |
1045 | 1051 | } else if p.peek_tok.kind == .name { |
| 1052 | + if p.is_vls { |
| 1053 | + // So that a line with a simple `var_name` works |
| 1054 | + p.next() |
| 1055 | + return ast.ExprStmt{ |
| 1056 | + expr: p.ident(.v) |
| 1057 | + } |
| 1058 | + } |
1046 | 1059 | return p.unexpected(got: 'name `${p.tok.lit}`') |
1047 | 1060 | } else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr |
1048 | 1061 | && p.peek_tok.kind in [.rcbr, .eof] && !p.scope.mark_var_as_used(p.tok.lit) { |
@@ -2125,7 +2138,7 @@ fn (mut p Parser) error_with_pos(s string, pos token.Pos) ast.NodeError { |
2125 | 2138 | util.show_compiler_message(kind, pos: pos, file_path: p.file_path, message: s) |
2126 | 2139 | exit(1) |
2127 | 2140 | } |
2128 | | - if p.pref.output_mode == .stdout && !p.pref.check_only { |
| 2141 | + if p.pref.output_mode == .stdout && !p.pref.check_only && !p.is_vls { |
2129 | 2142 | if p.pref.is_verbose { |
2130 | 2143 | print_backtrace() |
2131 | 2144 | kind = 'parser error:' |
@@ -2278,7 +2291,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt { |
2278 | 2291 | && node !in [ast.CallExpr, ast.PostfixExpr, ast.ComptimeCall, ast.SelectorExpr, ast.DumpExpr] { |
2279 | 2292 | is_complex_infix_expr := node is ast.InfixExpr |
2280 | 2293 | && node.op in [.left_shift, .right_shift, .unsigned_right_shift, .arrow] |
2281 | | - if !is_complex_infix_expr { |
| 2294 | + if !is_complex_infix_expr && !p.is_vls { |
2282 | 2295 | return p.error_with_pos('expression evaluated but not used', node.pos()) |
2283 | 2296 | } |
2284 | 2297 | } |
@@ -3338,6 +3351,16 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr { |
3338 | 3351 | mut field_name := '' |
3339 | 3352 | // check if the name is on the same line as the dot |
3340 | 3353 | if p.prev_tok.pos().line_nr == name_pos.line_nr || p.tok.kind != .name { |
| 3354 | + if p.is_vls { |
| 3355 | + if p.tok.kind in [.rpar, .rcbr] { |
| 3356 | + // Simplify the dot expression for VLS, so that the parser doesn't error |
| 3357 | + // `println(x.)` => `println(x)` |
| 3358 | + // `x. }` => `x }` etc |
| 3359 | + return left |
| 3360 | + } else if name_pos.line_nr != p.tok.line_nr { |
| 3361 | + return left |
| 3362 | + } |
| 3363 | + } |
3341 | 3364 | field_name = p.check_name() |
3342 | 3365 | } else { |
3343 | 3366 | p.name_error = true |
|
0 commit comments