fix issue #20922 by handling missing expr in exprList for tkOf (#20930)

* fix issue #20922 by handling missing expr in `exprList` for `tkOf`

* fix line numbers in test case

* rewrite exprList requiring expr, add optionalExprList for except

As suggested by @metagn.

* update test case to reflect new code

* update grammar.txt

* update line numbers in test case taking into account nimout

Given the number of errors that are produced it seems easier to do it
this way instead of using `tt.Error`.
This commit is contained in:
Vindaar
2022-12-08 10:59:13 +01:00
committed by GitHub
parent e669835665
commit 0a1d4ba842
3 changed files with 73 additions and 8 deletions

View File

@@ -451,6 +451,24 @@ proc exprList(p: var Parser, endTok: TokType, result: PNode) =
getTok(p)
optInd(p, result)
# progress guaranteed
var a = parseExpr(p)
result.add(a)
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
if p.tok.tokType != tkComma: break
getTok(p)
optInd(p, a)
var a = parseExpr(p)
result.add(a)
when defined(nimpretty):
dec p.em.doIndentMore
proc optionalExprList(p: var Parser, endTok: TokType, result: PNode) =
#| optionalExprList = expr ^* comma
when defined(nimpretty):
inc p.em.doIndentMore
getTok(p)
optInd(p, result)
# progress guaranteed
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
var a = parseExpr(p)
result.add(a)
@@ -1436,7 +1454,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
#| postExprBlocks = ':' stmt? ( IND{=} doBlock
#| | IND{=} 'of' exprList ':' stmt
#| | IND{=} 'elif' expr ':' stmt
#| | IND{=} 'except' exprList ':' stmt
#| | IND{=} 'except' optionalExprList ':' stmt
#| | IND{=} 'finally' ':' stmt
#| | IND{=} 'else' ':' stmt )*
result = x
@@ -1494,7 +1512,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
nextBlock.add parseExpr(p)
of tkExcept:
nextBlock = newNodeP(nkExceptBranch, p)
exprList(p, tkColon, nextBlock)
optionalExprList(p, tkColon, nextBlock)
of tkFinally:
nextBlock = newNodeP(nkFinally, p)
getTok(p)
@@ -1746,10 +1764,10 @@ proc parseCase(p: var Parser): PNode =
proc parseTry(p: var Parser; isExpr: bool): PNode =
#| tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
#| (IND{=}? 'except' exprList colcom stmt)*
#| (IND{=}? 'except' optionalExprList colcom stmt)*
#| (IND{=}? 'finally' colcom stmt)?
#| tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
#| (optInd 'except' exprList colcom stmt)*
#| (optInd 'except' optionalExprList colcom stmt)*
#| (optInd 'finally' colcom stmt)?
result = newNodeP(nkTryStmt, p)
getTok(p)
@@ -1760,7 +1778,7 @@ proc parseTry(p: var Parser; isExpr: bool): PNode =
case p.tok.tokType
of tkExcept:
b = newNodeP(nkExceptBranch, p)
exprList(p, tkColon, b)
optionalExprList(p, tkColon, b)
of tkFinally:
b = newNodeP(nkFinally, p)
getTok(p)

View File

@@ -30,6 +30,7 @@ symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
exprColonEqExpr = expr (':'|'=' expr)?
exprEqExpr = expr ('=' expr)?
exprList = expr ^+ comma
optionalExprList = expr ^* comma
exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
qualifiedIdent = symbol ('.' optInd symbol)?
setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}'
@@ -109,7 +110,7 @@ typeDefValue = ((tupleDecl | enumDecl | objectDecl | conceptDecl |
postExprBlocks = ':' stmt? ( IND{=} doBlock
| IND{=} 'of' exprList ':' stmt
| IND{=} 'elif' expr ':' stmt
| IND{=} 'except' exprList ':' stmt
| IND{=} 'except' optionalExprList ':' stmt
| IND{=} 'finally' ':' stmt
| IND{=} 'else' ':' stmt )*
exprStmt = simpleExpr postExprBlocks?
@@ -148,10 +149,10 @@ caseStmt = 'case' expr ':'? COMMENT?
(IND{>} ofBranches DED
| IND{=} ofBranches)
tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
(IND{=}? 'except' exprList colcom stmt)*
(IND{=}? 'except' optionalExprList colcom stmt)*
(IND{=}? 'finally' colcom stmt)?
tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
(optInd 'except' exprList colcom stmt)*
(optInd 'except' optionalExprList colcom stmt)*
(optInd 'finally' colcom stmt)?
blockStmt = 'block' symbol? colcom stmt
blockExpr = 'block' symbol? colcom stmt

46
tests/parser/t20922.nim Normal file
View File

@@ -0,0 +1,46 @@
discard """
cmd: "nim check $options --verbosity:0 $file"
action: "reject"
nimout: '''
t20922.nim(37, 5) Error: expression expected, but found ':'
Error: in expression ' '+'': identifier expected, but found ''
t20922.nim(37, 7) Error: attempting to call undeclared routine: '<Error>'
Error: in expression ' '+'': identifier expected, but found ''
t20922.nim(37, 7) Error: attempting to call undeclared routine: '<Error>'
t20922.nim(37, 7) Error: expression '' cannot be called
t20922.nim(37, 7) Error: expression '' has no type (or is ambiguous)
t20922.nim(37, 7) Error: VM problem: dest register is not set
t20922.nim(45, 7) Error: expression expected, but found ':'
t20922.nim(46, 5) Error: ':' or '=' expected, but got 'keyword of'
t20922.nim(45, 9) Error: undeclared identifier: 'x'
t20922.nim(45, 9) Error: expression 'x' has no type (or is ambiguous)
Error: in expression ' x': identifier expected, but found ''
t20922.nim(45, 9) Error: attempting to call undeclared routine: '<Error>'
Error: in expression ' x': identifier expected, but found ''
t20922.nim(45, 9) Error: attempting to call undeclared routine: '<Error>'
t20922.nim(45, 9) Error: expression '' cannot be called
t20922.nim(45, 9) Error: expression '' has no type (or is ambiguous)
t20922.nim(45, 9) Error: VM problem: dest register is not set
t20922.nim(33, 6) Hint: 'mapInstrToToken' is declared but not used [XDeclaredButNotUsed]
t20922.nim(43, 3) Hint: 'Foo' is declared but not used [XDeclaredButNotUsed]
'''
"""
# original test case issue #20922
type Token = enum
incDataPtr,
incDataPtrByte
proc mapInstrToToken(instr: char): Token =
case instr:
of '>':
incDataPtr
of: '+':
incDataPtrByte
# same issue with `of` in object branches (different parser procs calling `exprList`)
type
Bar = enum A, B
Foo = object
case kind: Bar
of: x: int
of B: y: float