diff options
-rw-r--r-- | compiler/parser.nim | 28 | ||||
-rw-r--r-- | doc/grammar.txt | 7 | ||||
-rw-r--r-- | tests/parser/t20922.nim | 46 |
3 files changed, 73 insertions, 8 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim index 0199c10af..6b3cebb7f 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -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) diff --git a/doc/grammar.txt b/doc/grammar.txt index a0ff7d9f0..88094981c 100644 --- a/doc/grammar.txt +++ b/doc/grammar.txt @@ -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 diff --git a/tests/parser/t20922.nim b/tests/parser/t20922.nim new file mode 100644 index 000000000..01af9868f --- /dev/null +++ b/tests/parser/t20922.nim @@ -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 |