Skip to content

Commit 4cbf77c

Browse files
committed
parser: vls mode
1 parent 0628bf3 commit 4cbf77c

3 files changed

Lines changed: 38 additions & 2 deletions

File tree

‎vlib/v/parser/parser.v‎

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ mut:
113113
script_mode_start_token token.Token
114114
generic_type_level int // to avoid infinite recursion segfaults due to compiler bugs in ensure_type_exists
115115
main_already_defined bool // TODO move to checker
116+
is_vls bool
116117
pub mut:
117118
scanner &scanner.Scanner = unsafe { nil }
118119
table &ast.Table = unsafe { nil }
@@ -177,6 +178,7 @@ pub fn parse_text(text string, path string, mut table ast.Table, comments_mode s
177178
scanner: scanner.new_scanner(text, comments_mode, pref_)
178179
table: table
179180
pref: pref_
181+
is_vls: pref_.is_vls
180182
scope: &ast.Scope{
181183
start_pos: 0
182184
parent: table.global_scope
@@ -555,6 +557,10 @@ fn (mut p Parser) parse_block_no_scope(is_top_level bool) []ast.Stmt {
555557
stmts << p.stmt(is_top_level)
556558
count++
557559
if count % 100000 == 0 {
560+
if p.is_vls {
561+
// Stuck in VLS mode, exit
562+
return []
563+
}
558564
eprintln('parsed ${count} statements so far from fn ${p.cur_fn_name} ...')
559565
}
560566
if count > 1000000 {
@@ -1043,6 +1049,13 @@ fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
10431049
pos: spos.extend(p.tok.pos())
10441050
}
10451051
} 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+
}
10461059
return p.unexpected(got: 'name `${p.tok.lit}`')
10471060
} else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr
10481061
&& 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 {
21252138
util.show_compiler_message(kind, pos: pos, file_path: p.file_path, message: s)
21262139
exit(1)
21272140
}
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 {
21292142
if p.pref.is_verbose {
21302143
print_backtrace()
21312144
kind = 'parser error:'
@@ -2278,7 +2291,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
22782291
&& node !in [ast.CallExpr, ast.PostfixExpr, ast.ComptimeCall, ast.SelectorExpr, ast.DumpExpr] {
22792292
is_complex_infix_expr := node is ast.InfixExpr
22802293
&& 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 {
22822295
return p.error_with_pos('expression evaluated but not used', node.pos())
22832296
}
22842297
}
@@ -3338,6 +3351,16 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
33383351
mut field_name := ''
33393352
// check if the name is on the same line as the dot
33403353
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+
}
33413364
field_name = p.check_name()
33423365
} else {
33433366
p.name_error = true

‎vlib/v/parser/struct.v‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,17 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind, is_option
512512
has_prev_newline = p.has_prev_newline()
513513
has_break_line = has_prev_newline || p.has_prev_line_comment_or_label()
514514
field_name = p.check_name()
515+
if p.is_vls {
516+
// In VLS mode allow unfinished struct inits without the ending }
517+
// `Foo{
518+
// field: name.`
519+
520+
if p.tok.kind != .colon {
521+
unsafe {
522+
goto end
523+
}
524+
}
525+
}
515526
p.check(.colon)
516527
expr = p.expr(0)
517528
end_comments = p.eat_comments(same_line: true)
@@ -554,6 +565,7 @@ fn (mut p Parser) struct_init(typ_str string, kind ast.StructInitKind, is_option
554565
p.check(.rcbr)
555566
}
556567
p.is_amp = saved_is_amp
568+
end:
557569
return ast.StructInit{
558570
unresolved: typ.has_flag(.generic)
559571
typ_str: typ_str

‎vlib/v/pref/pref.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ pub mut:
255255
relaxed_gcc14 bool = true // turn on the generated pragmas, that make gcc versions > 14 a lot less pedantic. The default is to have those pragmas in the generated C output, so that gcc-14 can be used on Arch etc.
256256
//
257257
subsystem Subsystem // the type of the window app, that is going to be generated; has no effect on !windows
258+
is_vls bool
258259
}
259260

260261
pub struct LineInfo {

0 commit comments

Comments
 (0)