Support for stmtListExpr in parser after major keywords. Scaled down version. (#10852)

* Support for stmtListExpr in parser after major keywords
* fixes #4035
This commit is contained in:
cooldome
2019-03-18 10:09:49 +00:00
committed by Andreas Rumpf
parent c19cd14fc9
commit 862897dc0f
4 changed files with 54 additions and 12 deletions

View File

@@ -29,6 +29,16 @@
- `getImpl` on a `var` or `let` symbol will now return the full `IdentDefs`
tree from the symbol declaration instead of just the initializer portion.
- it is now possible to use statement list expressions after keywords with
indentation: raise, return, discard, yield. This helps parsing code produced
by Nim template expansion where stmtListExpr can appear in place of any expression.
Example:
```nim
raise
var e = new(Exception)
e.msg = "My Exception msg"
e
```
- To use multi-methods, explicit `--multimethods:on` is now needed.

View File

@@ -238,6 +238,7 @@ proc newIdentNodeP(ident: PIdent, p: TParser): PNode =
proc parseExpr(p: var TParser): PNode
proc parseStmt(p: var TParser): PNode
proc parseStmtListExpr(p: var TParser): PNode
proc parseTypeDesc(p: var TParser): PNode
proc parseParamList(p: var TParser, retColon = true): PNode
@@ -806,7 +807,8 @@ proc parseOperators(p: var TParser, headNode: PNode,
var a = newNodeP(nkInfix, p)
var opNode = newIdentNodeP(p.tok.ident, p) # skip operator:
getTok(p)
optInd(p, a)
flexComment(p, a)
optPar(p)
# read sub-expression with higher priority:
var b = simpleExprAux(p, opPrec + leftAssoc, modeB)
addSon(a, opNode)
@@ -1479,12 +1481,12 @@ proc parseFromStmt(p: var TParser): PNode =
#expectNl(p)
proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
#| returnStmt = 'return' optInd expr?
#| raiseStmt = 'raise' optInd expr?
#| yieldStmt = 'yield' optInd expr?
#| discardStmt = 'discard' optInd expr?
#| breakStmt = 'break' optInd expr?
#| continueStmt = 'break' optInd expr?
#| returnStmt = 'return' stmtListExpr?
#| raiseStmt = 'raise' stmtListExpr?
#| yieldStmt = 'yield' stmtListExpr?
#| discardStmt = 'discard' stmtListExpr?
#| breakStmt = 'break' stmtListExpr?
#| continueStmt = 'break' stmtListExpr?
result = newNodeP(kind, p)
getTok(p)
if p.tok.tokType == tkComment:
@@ -1494,9 +1496,7 @@ proc parseReturnOrRaise(p: var TParser, kind: TNodeKind): PNode =
# NL terminates:
addSon(result, p.emptyNode)
else:
var e = parseExpr(p)
e = postExprBlocks(p, e)
addSon(result, e)
addSon(result, parseStmtListExpr(p))
proc parseIfOrWhen(p: var TParser, kind: TNodeKind): PNode =
#| condStmt = expr colcom stmt COMMENT?
@@ -2249,6 +2249,17 @@ proc parseStmt(p: var TParser): PNode =
getTok(p)
if err and p.tok.tokType == tkEof: break
proc parseStmtListExpr(p: var TParser): PNode =
#| stmtListExpr = (IND{>} stmt) / expr
if p.tok.indent > p.currInd:
result = parseStmt(p)
result.kind = nkStmtListExpr
if result.len == 1:
result = result[0]
else:
result = parseExpr(p)
result = postExprBlocks(p, result)
proc parseAll(p: var TParser): PNode =
## Parses the rest of the input stream held by the parser into a PNode.
result = newNodeP(nkStmtList, p)

View File

@@ -1,5 +1,5 @@
discard """
outputsub: '''Error: invalid indentation 45'''
outputsub: '''Error: expression expected, but found '[EOF]' -- 45'''
"""
# feature request #1473
@@ -9,6 +9,7 @@ macro test(text: string): untyped =
try:
result = parseExpr(text.strVal)
except ValueError:
echo text
result = newLit getCurrentExceptionMsg()
const
@@ -17,4 +18,4 @@ const
b = test("valid")
c = test("\"") # bug #2504
echo a, " ", b
echo a, " -- ", b

View File

@@ -0,0 +1,20 @@
discard """
output: '''10'''
"""
proc xx(a: int): int =
let y = 0
return
var x = 0
x + y
proc b(x: int): int =
raise
var e: ref Exception
new(e)
e.msg = "My Exception msg"
e
##issue 4035
echo(5 +
5)