diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37ccd5c5cc..9935fc44a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -610,3 +610,4 @@ jobs: ./v test-parser examples/hanoi.v ./v test-parser examples/fibonacci.v ./v test-parser examples/cli.v + ./v test-parser examples/json.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 99b6f7c6ea..90fdc05cc0 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -264,7 +264,7 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool { } fn (mut c Checker) check_valid_snake_case(name string, identifier string, pos token.Position) { - if !c.pref.is_vweb && (name[0] == `_` || name.contains('._')) { + if !c.pref.is_vweb && name.len > 0 && (name[0] == `_` || name.contains('._')) { c.error('$identifier `$name` cannot start with `_`', pos) } if !c.pref.experimental && !c.pref.translated && util.contains_capital(name) { @@ -280,7 +280,7 @@ fn stripped_name(name string) string { fn (mut c Checker) check_valid_pascal_case(name string, identifier string, pos token.Position) { sname := stripped_name(name) - if !sname[0].is_capital() && !c.pref.translated { + if sname.len > 0 && !sname[0].is_capital() && !c.pref.translated { c.error('$identifier `$name` must begin with capital letter', pos) } } @@ -1391,7 +1391,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { // println(fn_name) // } if fn_name == 'json.encode' { - } else if fn_name == 'json.decode' { + } else if fn_name == 'json.decode' && call_expr.args.len > 0 { expr := call_expr.args[0].expr if expr !is ast.Type { typ := typeof(expr) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index aece0ca551..3cb57d84fa 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -199,6 +199,10 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // or should it be a property of the arg, like this ptr/mut becomes indistinguishable rec_type_pos = p.tok.position() rec_type = p.parse_type_with_mut(rec_mut) + if rec_type.idx() == 0 { + // error is set in parse_type + return ast.FnDecl{} + } rec_type_pos = rec_type_pos.extend(p.prev_tok.position()) if is_amp && rec_mut { p.error('use `(mut f Foo)` or `(f &Foo)` instead of `(mut f &Foo)`') diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index 5111017ce6..141a576875 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -21,6 +21,10 @@ pub fn (mut p Parser) parse_array_type() table.Type { // array p.check(.rsbr) elem_type := p.parse_type() + if elem_type.idx() == 0 { + // error is set in parse_type + return 0 + } mut nr_dims := 1 // detect attr not_attr := p.peek_tok.kind != .name && p.peek_tok2.kind !in [.semicolon, .rsbr] @@ -165,6 +169,10 @@ pub fn (mut p Parser) parse_type() table.Type { if p.tok.kind != .lcbr { pos := p.tok.position() typ = p.parse_any_type(language, nr_muls > 0, true) + if typ.idx() == 0 { + // error is set in parse_type + return 0 + } if typ == table.void_type { p.error_with_pos('use `?` instead of `?void`', pos) return 0 diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 3caf58b8c4..ea32f97a32 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -194,6 +194,10 @@ fn (mut p Parser) struct_decl() ast.StructDecl { } } typ = p.parse_type() + if typ.idx() == 0 { + // error is set in parse_type + return ast.StructDecl{} + } type_pos = p.prev_tok.position() field_pos = field_start_pos.extend(type_pos) }