From 8268df7e1d12658c3deee9f5463ec4f6c987b628 Mon Sep 17 00:00:00 2001 From: zakuro Date: Sat, 30 Jul 2022 01:28:34 +0900 Subject: [PATCH] parser: create and use `Parser.unexpected` to unify all unexpected token error messages (#15259) --- vlib/v/parser/assign.v | 3 +- vlib/v/parser/expr.v | 11 ++++--- vlib/v/parser/fn.v | 3 +- vlib/v/parser/lock.v | 5 ++- vlib/v/parser/parse_type.v | 2 +- vlib/v/parser/parser.v | 66 +++++++++++++++++++++++++++++--------- vlib/v/parser/sql.v | 6 ++-- 7 files changed, 64 insertions(+), 32 deletions(-) diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index b1efe16cdc..6951aa35e6 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -357,8 +357,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme for r in right { has_cross_var = p.check_cross_variables(left, r) if op !in [.assign, .decl_assign] { - return p.error_with_pos('unexpected $op.str(), expecting := or = or comma', - pos) + return p.unexpected_with_pos(pos, got: op.str(), expecting: ':= or = or comma') } if has_cross_var { break diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index 0826aa6abe..ad58cd19bd 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -12,7 +12,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { if token.is_decl(p.tok.kind) && p.disallow_declarations_in_script_mode() { return ast.empty_expr } - p.error_with_pos('invalid expression: unexpected $p.tok', p.tok.pos()) + p.unexpected(prepend_msg: 'invalid expression:') } } @@ -91,7 +91,9 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr { return p.if_expr(true) } else { - return p.error_with_pos('unexpected `$`', p.peek_tok.pos()) + return p.unexpected_with_pos(p.peek_tok.pos(), + got: '`$`' + ) } } } @@ -294,8 +296,7 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr { st := p.parse_type() p.check(.comma) if p.tok.kind != .name { - return p.error_with_pos('unexpected `$p.tok.lit`, expecting struct field', - p.tok.pos()) + return p.unexpected(got: '`$p.tok.lit`', additional_msg: 'expecting struct field') } field := p.tok.lit p.next() @@ -365,7 +366,7 @@ pub fn (mut p Parser) check_expr(precedence int) ?ast.Expr { if p.tok.kind != .eof && !(p.tok.kind == .rsbr && p.inside_asm) { // eof should be handled where it happens return none - // return p.error_with_pos('invalid expression: unexpected $p.tok', p.tok.pos()) + // return p.unexpected(prepend_msg: 'invalid expression: ') } } } diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 7a64effee1..63dbc12782 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -712,8 +712,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn { no_body := p.tok.kind != .lcbr same_line = p.tok.line_nr == p.prev_tok.line_nr if no_body && same_line { - p.error_with_pos('unexpected $p.tok after anonymous function signature, expecting `{`', - p.tok.pos()) + p.unexpected(got: '$p.tok after anonymous function signature', expecting: '`{`') } mut label_names := []string{} mut func := ast.Fn{ diff --git a/vlib/v/parser/lock.v b/vlib/v/parser/lock.v index 11a95534d5..1c828337fa 100644 --- a/vlib/v/parser/lock.v +++ b/vlib/v/parser/lock.v @@ -10,8 +10,7 @@ fn (mut p Parser) lockable() ast.Expr { mut pos := p.tok.pos() for { if p.tok.kind != .name { - p.error_with_pos('unexpected `$p.tok.lit` (field/variable name expected)', - p.tok.pos()) + p.unexpected(got: '`$p.tok.lit`', expecting: 'field or variable name') } names << p.tok.lit positions << pos @@ -74,7 +73,7 @@ fn (mut p Parser) lock_expr() ast.LockExpr { for { is_rlock := p.tok.kind == .key_rlock if !is_rlock && p.tok.kind != .key_lock { - p.error_with_pos('unexpected `$p.tok`, expected `lock` or `rlock`', p.tok.pos()) + p.unexpected(expecting: '`lock` or `rlock`') } p.next() if p.tok.kind == .lcbr { diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index f8fcda3164..8cabef9025 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -529,7 +529,7 @@ pub fn (mut p Parser) parse_any_type(language ast.Language, is_ptr bool, check_d if p.tok.kind == .lpar && !p.inside_sum_type { // multiple return if is_ptr { - p.error('parse_type: unexpected `&` before multiple returns') + p.unexpected(prepend_msg: 'parse_type:', got: '`&` before multiple returns') return 0 } return p.parse_multi_return_type() diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 3e9368d8b6..fd75162251 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -577,10 +577,40 @@ fn (mut p Parser) check(expected token.Kind) { if token.is_key(s) || (s.len > 0 && !s[0].is_letter()) { s = '`$s`' } - p.error('unexpected $p.tok, expecting $s') + p.unexpected(expecting: s) } } +[params] +struct ParamsForUnexpected { + got string + expecting string + prepend_msg string + additional_msg string +} + +fn (mut p Parser) unexpected(params ParamsForUnexpected) ast.NodeError { + return p.unexpected_with_pos(p.tok.pos(), params) +} + +fn (mut p Parser) unexpected_with_pos(pos token.Pos, params ParamsForUnexpected) ast.NodeError { + mut msg := if params.got != '' { + 'unexpected $params.got' + } else { + 'unexpected $p.tok' + } + if params.expecting != '' { + msg += ', expecting $params.expecting' + } + if params.prepend_msg != '' { + msg = '$params.prepend_msg ' + msg + } + if params.additional_msg != '' { + msg += ', $params.additional_msg' + } + return p.error_with_pos(msg, pos) +} + // JS functions can have multiple dots in their name: // JS.foo.bar.and.a.lot.more.dots() fn (mut p Parser) check_js_name() string { @@ -669,7 +699,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt { } .dollar { if p.peek_tok.kind == .eof { - return p.error('unexpected eof') + return p.unexpected(got: 'eof') } if_expr := p.if_expr(true) cur_stmt := ast.ExprStmt{ @@ -895,7 +925,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt { pos: spos.extend(p.tok.pos()) } } else if p.peek_tok.kind == .name { - return p.error_with_pos('unexpected name `$p.tok.lit`', p.tok.pos()) + return p.unexpected(got: 'name `$p.tok.lit`') } else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr && p.peek_tok.kind in [.rcbr, .eof] && !p.mark_var_as_used(p.tok.lit) { return p.error_with_pos('`$p.tok.lit` evaluated but not used', p.tok.pos()) @@ -936,7 +966,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt { } } else { - return p.error_with_pos('unexpected \$', p.tok.pos()) + return p.unexpected(got: '\$') } } } @@ -1682,7 +1712,7 @@ fn (mut p Parser) attributes() { p.next() break } - p.error('unexpected $p.tok, expecting `;`') + p.unexpected(expecting: '`;`') return } p.next() @@ -1754,7 +1784,7 @@ fn (mut p Parser) parse_attr() ast.Attr { arg = p.tok.kind.str() p.next() } else { - p.error('unexpected $p.tok, an argument is expected after `:`') + p.unexpected(additional_msg: 'an argument is expected after `:`') } } } @@ -2042,7 +2072,7 @@ pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident { if is_mut || is_static || is_volatile { p.error_with_pos('the `$modifier_kind` keyword is invalid here', mut_pos) } else { - p.error('unexpected token `$p.tok.lit`') + p.unexpected(got: 'token `$p.tok.lit`') } return ast.Ident{ scope: p.scope @@ -2408,7 +2438,9 @@ pub fn (mut p Parser) name_expr() ast.Expr { } else { // fn call if is_optional { - p.error_with_pos('unexpected $p.prev_tok', p.prev_tok.pos()) + p.unexpected_with_pos(p.prev_tok.pos(), + got: '$p.prev_tok' + ) } node = p.call_expr(language, mod) if p.tok.kind == .lpar && p.prev_tok.line_nr == p.tok.line_nr { @@ -3136,12 +3168,16 @@ fn (mut p Parser) module_decl() ast.Module { n_pos := p.tok.pos() if module_pos.line_nr == n_pos.line_nr && p.tok.kind != .comment && p.tok.kind != .eof { if p.tok.kind == .name { - p.error_with_pos('`module $name`, you can only declare one module, unexpected `$p.tok.lit`', - n_pos) + p.unexpected_with_pos(n_pos, + prepend_msg: '`module $name`, you can only declare one module,' + got: '`$p.tok.lit`' + ) return mod_node } else { - p.error_with_pos('`module $name`, unexpected `$p.tok.kind` after module name', - n_pos) + p.unexpected_with_pos(n_pos, + prepend_msg: '`module $name`,' + got: '`$p.tok.kind` after module name' + ) return mod_node } } @@ -3363,7 +3399,7 @@ fn (mut p Parser) const_decl() ast.ConstDecl { for { comments = p.eat_comments() if is_block && p.tok.kind == .eof { - p.error('unexpected eof, expecting ´)´') + p.unexpected(got: 'eof', expecting: '´)´') return ast.ConstDecl{} } if p.tok.kind == .rpar { @@ -3387,7 +3423,7 @@ fn (mut p Parser) const_decl() ast.ConstDecl { return ast.ConstDecl{} } if p.tok.kind == .eof { - p.error('unexpected eof, expecting an expression') + p.unexpected(got: 'eof', expecting: 'an expression') return ast.ConstDecl{} } expr := p.expr(0) @@ -3485,7 +3521,7 @@ fn (mut p Parser) global_decl() ast.GlobalDecl { p.next() } if is_block && p.tok.kind == .eof { - p.error('unexpected eof, expecting `)`') + p.unexpected(got: 'eof', expecting: '`)`') return ast.GlobalDecl{} } if p.tok.kind == .rpar { diff --git a/vlib/v/parser/sql.v b/vlib/v/parser/sql.v index b892e9ac39..a4fbf9f177 100644 --- a/vlib/v/parser/sql.v +++ b/vlib/v/parser/sql.v @@ -10,8 +10,7 @@ fn (mut p Parser) sql_expr() ast.Expr { pos := p.tok.pos() p.check_name() db_expr := p.check_expr(0) or { - p.error_with_pos('invalid expression: unexpected $p.tok, expecting database', - p.tok.pos()) + p.unexpected(prepend_msg: 'invalid expression:', expecting: 'database') } p.check(.lcbr) p.check(.key_select) @@ -125,8 +124,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt { // `sql db {` p.check_name() db_expr := p.check_expr(0) or { - p.error_with_pos('invalid expression: unexpected $p.tok, expecting database', - p.tok.pos()) + p.unexpected(prepend_msg: 'invalid expression:', expecting: 'database') } // println(typeof(db_expr)) p.check(.lcbr)