diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index fe119da95a..dbf084f5ba 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 189a4132ab..0000000000 --- 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 0000000000..154cde8498 --- /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 3f2fd06335..5922e4267c 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 0000000000..5d719d7cb0 --- /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 0000000000..35fa85ee09 --- /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 0000000000..d43dcc1a24 --- /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 0000000000..696c059584 --- /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 0000000000..1f07813915 --- /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 0000000000..2cc3925463 --- /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"]