* 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:
parent
e669835665
commit
0a1d4ba842
3 changed files with 73 additions and 8 deletions
|
|
@ -451,6 +451,24 @@ proc exprList(p: var Parser, endTok: TokType, result: PNode) =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
# progress guaranteed
|
# 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):
|
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
||||||
var a = parseExpr(p)
|
var a = parseExpr(p)
|
||||||
result.add(a)
|
result.add(a)
|
||||||
|
|
@ -1436,7 +1454,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||||
#| postExprBlocks = ':' stmt? ( IND{=} doBlock
|
#| postExprBlocks = ':' stmt? ( IND{=} doBlock
|
||||||
#| | IND{=} 'of' exprList ':' stmt
|
#| | IND{=} 'of' exprList ':' stmt
|
||||||
#| | IND{=} 'elif' expr ':' stmt
|
#| | IND{=} 'elif' expr ':' stmt
|
||||||
#| | IND{=} 'except' exprList ':' stmt
|
#| | IND{=} 'except' optionalExprList ':' stmt
|
||||||
#| | IND{=} 'finally' ':' stmt
|
#| | IND{=} 'finally' ':' stmt
|
||||||
#| | IND{=} 'else' ':' stmt )*
|
#| | IND{=} 'else' ':' stmt )*
|
||||||
result = x
|
result = x
|
||||||
|
|
@ -1494,7 +1512,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
|
||||||
nextBlock.add parseExpr(p)
|
nextBlock.add parseExpr(p)
|
||||||
of tkExcept:
|
of tkExcept:
|
||||||
nextBlock = newNodeP(nkExceptBranch, p)
|
nextBlock = newNodeP(nkExceptBranch, p)
|
||||||
exprList(p, tkColon, nextBlock)
|
optionalExprList(p, tkColon, nextBlock)
|
||||||
of tkFinally:
|
of tkFinally:
|
||||||
nextBlock = newNodeP(nkFinally, p)
|
nextBlock = newNodeP(nkFinally, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
@ -1746,10 +1764,10 @@ proc parseCase(p: var Parser): PNode =
|
||||||
|
|
||||||
proc parseTry(p: var Parser; isExpr: bool): PNode =
|
proc parseTry(p: var Parser; isExpr: bool): PNode =
|
||||||
#| tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
|
#| tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
|
||||||
#| (IND{=}? 'except' exprList colcom stmt)*
|
#| (IND{=}? 'except' optionalExprList colcom stmt)*
|
||||||
#| (IND{=}? 'finally' colcom stmt)?
|
#| (IND{=}? 'finally' colcom stmt)?
|
||||||
#| tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
|
#| tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
|
||||||
#| (optInd 'except' exprList colcom stmt)*
|
#| (optInd 'except' optionalExprList colcom stmt)*
|
||||||
#| (optInd 'finally' colcom stmt)?
|
#| (optInd 'finally' colcom stmt)?
|
||||||
result = newNodeP(nkTryStmt, p)
|
result = newNodeP(nkTryStmt, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
@ -1760,7 +1778,7 @@ proc parseTry(p: var Parser; isExpr: bool): PNode =
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkExcept:
|
of tkExcept:
|
||||||
b = newNodeP(nkExceptBranch, p)
|
b = newNodeP(nkExceptBranch, p)
|
||||||
exprList(p, tkColon, b)
|
optionalExprList(p, tkColon, b)
|
||||||
of tkFinally:
|
of tkFinally:
|
||||||
b = newNodeP(nkFinally, p)
|
b = newNodeP(nkFinally, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
|
||||||
exprColonEqExpr = expr (':'|'=' expr)?
|
exprColonEqExpr = expr (':'|'=' expr)?
|
||||||
exprEqExpr = expr ('=' expr)?
|
exprEqExpr = expr ('=' expr)?
|
||||||
exprList = expr ^+ comma
|
exprList = expr ^+ comma
|
||||||
|
optionalExprList = expr ^* comma
|
||||||
exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
|
exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
|
||||||
qualifiedIdent = symbol ('.' optInd symbol)?
|
qualifiedIdent = symbol ('.' optInd symbol)?
|
||||||
setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}'
|
setOrTableConstr = '{' ((exprColonEqExpr comma)* | ':' ) '}'
|
||||||
|
|
@ -109,7 +110,7 @@ typeDefValue = ((tupleDecl | enumDecl | objectDecl | conceptDecl |
|
||||||
postExprBlocks = ':' stmt? ( IND{=} doBlock
|
postExprBlocks = ':' stmt? ( IND{=} doBlock
|
||||||
| IND{=} 'of' exprList ':' stmt
|
| IND{=} 'of' exprList ':' stmt
|
||||||
| IND{=} 'elif' expr ':' stmt
|
| IND{=} 'elif' expr ':' stmt
|
||||||
| IND{=} 'except' exprList ':' stmt
|
| IND{=} 'except' optionalExprList ':' stmt
|
||||||
| IND{=} 'finally' ':' stmt
|
| IND{=} 'finally' ':' stmt
|
||||||
| IND{=} 'else' ':' stmt )*
|
| IND{=} 'else' ':' stmt )*
|
||||||
exprStmt = simpleExpr postExprBlocks?
|
exprStmt = simpleExpr postExprBlocks?
|
||||||
|
|
@ -148,10 +149,10 @@ caseStmt = 'case' expr ':'? COMMENT?
|
||||||
(IND{>} ofBranches DED
|
(IND{>} ofBranches DED
|
||||||
| IND{=} ofBranches)
|
| IND{=} ofBranches)
|
||||||
tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
|
tryStmt = 'try' colcom stmt &(IND{=}? 'except'|'finally')
|
||||||
(IND{=}? 'except' exprList colcom stmt)*
|
(IND{=}? 'except' optionalExprList colcom stmt)*
|
||||||
(IND{=}? 'finally' colcom stmt)?
|
(IND{=}? 'finally' colcom stmt)?
|
||||||
tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
|
tryExpr = 'try' colcom stmt &(optInd 'except'|'finally')
|
||||||
(optInd 'except' exprList colcom stmt)*
|
(optInd 'except' optionalExprList colcom stmt)*
|
||||||
(optInd 'finally' colcom stmt)?
|
(optInd 'finally' colcom stmt)?
|
||||||
blockStmt = 'block' symbol? colcom stmt
|
blockStmt = 'block' symbol? colcom stmt
|
||||||
blockExpr = 'block' symbol? colcom stmt
|
blockExpr = 'block' symbol? colcom stmt
|
||||||
|
|
|
||||||
46
tests/parser/t20922.nim
Normal file
46
tests/parser/t20922.nim
Normal 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue