From 5aad0db0f765b0905facde6876e088d0e579e311 Mon Sep 17 00:00:00 2001 From: Makhnev Petr <51853996+i582@users.noreply.github.com> Date: Tue, 24 Jan 2023 12:08:35 +0400 Subject: [PATCH] parser: improve error for prefix inc/dec statement `--a`/`++mp["id"]` (#17090) --- vlib/v/parser/expr.v | 47 ++++++++++++++++++- vlib/v/parser/tests/postfix_inc.out | 5 -- vlib/v/parser/tests/prefix_dec_bare_err.out | 5 ++ ...{postfix_inc.vv => prefix_dec_bare_err.vv} | 2 +- vlib/v/parser/tests/prefix_dec_err.out | 5 ++ vlib/v/parser/tests/prefix_dec_err.vv | 3 ++ vlib/v/parser/tests/prefix_dec_expr_err.out | 5 ++ vlib/v/parser/tests/prefix_dec_expr_err.vv | 3 ++ vlib/v/parser/tests/prefix_inc_err.out | 5 ++ vlib/v/parser/tests/prefix_inc_err.vv | 3 ++ 10 files changed, 76 insertions(+), 7 deletions(-) delete mode 100644 vlib/v/parser/tests/postfix_inc.out create mode 100644 vlib/v/parser/tests/prefix_dec_bare_err.out rename vlib/v/parser/tests/{postfix_inc.vv => prefix_dec_bare_err.vv} (80%) create mode 100644 vlib/v/parser/tests/prefix_dec_err.out create mode 100644 vlib/v/parser/tests/prefix_dec_err.vv create mode 100644 vlib/v/parser/tests/prefix_dec_expr_err.out create mode 100644 vlib/v/parser/tests/prefix_dec_expr_err.vv create mode 100644 vlib/v/parser/tests/prefix_inc_err.out create mode 100644 vlib/v/parser/tests/prefix_inc_err.vv diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index fe119da95..dbf084f5b 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -422,6 +422,14 @@ pub fn (mut p Parser) check_expr(precedence int) !ast.Expr { return node } } + .inc, .dec { + same_line_with_next := p.tok.line_nr == p.peek_tok.line_nr + next_tok_name := p.peek_tok.kind == .name + + if next_tok_name && same_line_with_next { + p.prefix_inc_dec_error() + } + } else { if p.tok.kind == .key_struct && p.peek_tok.kind == .lcbr { // Anonymous struct @@ -535,10 +543,33 @@ pub fn (mut p Parser) expr_with_left(left ast.Expr, precedence int, is_stmt_iden p.tok.pos()) } } - if p.tok.kind in [.inc, .dec] && p.prev_tok.line_nr != p.tok.line_nr { + + inc_dec_tok := p.tok.kind in [.inc, .dec] + same_line_with_prev := p.tok.line_nr == p.prev_tok.line_nr + same_line_with_next := p.tok.line_nr == p.peek_tok.line_nr + next_tok_name := p.peek_tok.kind == .name + + // 1. name + // 2. ++ + // ^^ current token + if inc_dec_tok && !same_line_with_prev && !next_tok_name { p.error_with_pos('${p.tok} must be on the same line as the previous token', p.tok.pos()) } + + // a++ a-- + // ^^ current token + // a[i]++ a-- + // ^^ current token + // check if op attached to previous name + prev_name_or_rsbr := p.prev_tok.kind in [.name, .rsbr] + // 1. ++name + // ^^ current token + if inc_dec_tok && same_line_with_next && next_tok_name + && (!prev_name_or_rsbr || !same_line_with_prev) { + p.prefix_inc_dec_error() + } + if mut node is ast.IndexExpr { node.recursive_mapset_is_setter(true) } @@ -708,3 +739,17 @@ fn (mut p Parser) recast_as_pointer(mut cast_expr ast.CastExpr, pos token.Pos) { cast_expr.typname = p.table.sym(cast_expr.typ).name cast_expr.pos = pos.extend(cast_expr.pos) } + +// prefix_inc_dec_error reports an error for a prefix increment or decrement. +// prefix increments and decrements are not allowed in V. +fn (mut p Parser) prefix_inc_dec_error() { + op := if p.tok.kind == .inc { '++' } else { '--' } + op_pos := p.tok.pos() + + p.next() + expr := p.expr(0) // expression `mp["name"]` after `--` in `--mp["name"]` + full_expr_pos := op_pos.extend(expr.pos()) // position of full `--mp["name"]` + + p.error_with_pos('prefix `${op}${expr}` is unsupported, use suffix form `${expr}${op}`', + full_expr_pos) +} diff --git a/vlib/v/parser/tests/postfix_inc.out b/vlib/v/parser/tests/postfix_inc.out deleted file mode 100644 index 189a4132a..000000000 --- a/vlib/v/parser/tests/postfix_inc.out +++ /dev/null @@ -1,5 +0,0 @@ -vlib/v/parser/tests/postfix_inc.vv:3:1: error: token `++` must be on the same line as the previous token - 1 | mut v := 4 - 2 | _ = v - 3 | ++v - | ~~ diff --git a/vlib/v/parser/tests/prefix_dec_bare_err.out b/vlib/v/parser/tests/prefix_dec_bare_err.out new file mode 100644 index 000000000..154cde849 --- /dev/null +++ b/vlib/v/parser/tests/prefix_dec_bare_err.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/prefix_dec_bare_err.vv:3:1: error: token `--` must be on the same line as the previous token + 1 | mut v := 4 + 2 | _ = v + 3 | -- + | ~~ \ No newline at end of file diff --git a/vlib/v/parser/tests/postfix_inc.vv b/vlib/v/parser/tests/prefix_dec_bare_err.vv similarity index 80% rename from vlib/v/parser/tests/postfix_inc.vv rename to vlib/v/parser/tests/prefix_dec_bare_err.vv index 3f2fd0633..5922e4267 100644 --- a/vlib/v/parser/tests/postfix_inc.vv +++ b/vlib/v/parser/tests/prefix_dec_bare_err.vv @@ -1,3 +1,3 @@ mut v := 4 _ = v -++v +-- diff --git a/vlib/v/parser/tests/prefix_dec_err.out b/vlib/v/parser/tests/prefix_dec_err.out new file mode 100644 index 000000000..5d719d7cb --- /dev/null +++ b/vlib/v/parser/tests/prefix_dec_err.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/prefix_dec_err.vv:3:1: error: prefix `--v` is unsupported, use suffix form `v--` + 1 | mut v := 4 + 2 | _ = v + 3 | --v + | ~~~ diff --git a/vlib/v/parser/tests/prefix_dec_err.vv b/vlib/v/parser/tests/prefix_dec_err.vv new file mode 100644 index 000000000..35fa85ee0 --- /dev/null +++ b/vlib/v/parser/tests/prefix_dec_err.vv @@ -0,0 +1,3 @@ +mut v := 4 +_ = v +--v diff --git a/vlib/v/parser/tests/prefix_dec_expr_err.out b/vlib/v/parser/tests/prefix_dec_expr_err.out new file mode 100644 index 000000000..d43dcc1a2 --- /dev/null +++ b/vlib/v/parser/tests/prefix_dec_expr_err.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/prefix_dec_expr_err.vv:3:9: error: prefix `--v` is unsupported, use suffix form `v--` + 1 | mut v := 4 + 2 | _ = v + 3 | println(--v) + | ~~~ diff --git a/vlib/v/parser/tests/prefix_dec_expr_err.vv b/vlib/v/parser/tests/prefix_dec_expr_err.vv new file mode 100644 index 000000000..696c05958 --- /dev/null +++ b/vlib/v/parser/tests/prefix_dec_expr_err.vv @@ -0,0 +1,3 @@ +mut v := 4 +_ = v +println(--v) diff --git a/vlib/v/parser/tests/prefix_inc_err.out b/vlib/v/parser/tests/prefix_inc_err.out new file mode 100644 index 000000000..1f0781391 --- /dev/null +++ b/vlib/v/parser/tests/prefix_inc_err.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/prefix_inc_err.vv:3:1: error: prefix `--mp['a']` is unsupported, use suffix form `mp['a']--` + 1 | mut mp := map[string]int{} + 2 | mp["a"] = 1 + 3 | --mp["a"] + | ~~~~~~~~~ diff --git a/vlib/v/parser/tests/prefix_inc_err.vv b/vlib/v/parser/tests/prefix_inc_err.vv new file mode 100644 index 000000000..2cc392546 --- /dev/null +++ b/vlib/v/parser/tests/prefix_inc_err.vv @@ -0,0 +1,3 @@ +mut mp := map[string]int{} +mp["a"] = 1 +--mp["a"] -- 2.39.5