summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorcooldome <cdome@bk.ru>2019-03-18 10:09:49 +0000
committerAndreas Rumpf <rumpf_a@web.de>2019-03-18 11:09:49 +0100
commit862897dc0f122e374c0e4d44770ffcd8825e51e3 (patch)
treec92794e887760bc44be045a46a3182f093a027e5
parentc19cd14fc96cfdc77c98e90adeb4e1eb8b5d9b26 (diff)
downloadNim-862897dc0f122e374c0e4d44770ffcd8825e51e3.tar.gz
Support for stmtListExpr in parser after major keywords. Scaled down version. (#10852)
* Support for stmtListExpr in parser after major keywords
* fixes #4035
-rw-r--r--changelog.md10
-rw-r--r--compiler/parser.nim31
-rw-r--r--tests/macros/ttryparseexpr.nim5
-rw-r--r--tests/parser/tstmtlist_expr.nim20
4 files changed, 54 insertions, 12 deletions
diff --git a/changelog.md b/changelog.md
index 2fb80dfc5..6e3872219 100644
--- a/changelog.md
+++ b/changelog.md
@@ -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.
 
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 855fc2f4a..1acfe1b98 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -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)
diff --git a/tests/macros/ttryparseexpr.nim b/tests/macros/ttryparseexpr.nim
index 54442b662..d1084937b 100644
--- a/tests/macros/ttryparseexpr.nim
+++ b/tests/macros/ttryparseexpr.nim
@@ -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
diff --git a/tests/parser/tstmtlist_expr.nim b/tests/parser/tstmtlist_expr.nim
new file mode 100644
index 000000000..8b4bb8505
--- /dev/null
+++ b/tests/parser/tstmtlist_expr.nim
@@ -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)
\ No newline at end of file