summary refs log tree commit diff stats
path: root/compiler/parser.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/parser.nim')
-rw-r--r--compiler/parser.nim94
1 files changed, 82 insertions, 12 deletions
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 517297a87..f9f7f7fad 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -315,9 +315,7 @@ proc indexExprList(p: var TParser, first: PNode, k: TNodeKind,
   optPar(p)
   eat(p, endToken)
 
-proc exprColonEqExpr(p: var TParser): PNode =
-  #| exprColonEqExpr = expr (':'|'=' expr)?
-  var a = parseExpr(p)
+proc colonOrEquals(p: var TParser, a: PNode): PNode =
   if p.tok.tokType == tkColon:
     result = newNodeP(nkExprColonExpr, p)
     getTok(p)
@@ -333,6 +331,11 @@ proc exprColonEqExpr(p: var TParser): PNode =
   else:
     result = a
 
+proc exprColonEqExpr(p: var TParser): PNode =
+  #| exprColonEqExpr = expr (':'|'=' expr)?
+  var a = parseExpr(p)
+  result = colonOrEquals(p, a)
+
 proc exprList(p: var TParser, endTok: TTokType, result: PNode) = 
   #| exprList = expr ^+ comma
   getTok(p)
@@ -443,9 +446,76 @@ proc parseGStrLit(p: var TParser, a: PNode): PNode =
     getTok(p)
   else:
     result = a
-  
-proc identOrLiteral(p: var TParser): PNode = 
-  #| generalizedLit ::= GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
+
+type
+  TPrimaryMode = enum pmNormal, pmTypeDesc, pmTypeDef, pmSkipSuffix
+
+proc complexOrSimpleStmt(p: var TParser): PNode
+proc simpleExpr(p: var TParser, mode = pmNormal): PNode
+
+proc semiStmtList(p: var TParser, result: PNode) =
+  if p.tok.tokType == tkSemicolon:
+    # '(;' enforces 'stmt' context:
+    getTok(p)
+    optInd(p, result)
+  result.add(complexOrSimpleStmt(p))
+  while p.tok.tokType == tkSemicolon:
+    getTok(p)
+    optInd(p, result)
+    result.add(complexOrSimpleStmt(p))
+  result.kind = nkStmtListExpr
+
+proc parsePar(p: var TParser): PNode =
+  #| parKeyw = 'discard' | 'include' | 'if' | 'while' | 'case' | 'try'
+  #|         | 'finally' | 'except' | 'for' | 'block' | 'const' | 'let'
+  #|         | 'when' | 'var' | 'bind' | 'mixin'
+  #| par = '(' optInd (&parKeyw complexOrSimpleStmt ^+ ';' 
+  #|                  | simpleExpr ('=' expr (';' complexOrSimpleStmt ^+ ';' )? )?
+  #|                             | (':' expr)? (',' (exprColonEqExpr comma?)*)?  )?
+  #|         optPar ')'
+  #
+  # unfortunately it's ambiguous: (expr: expr) vs (exprStmt); however a 
+  # leading ';' could be used to enforce a 'stmt' context ...
+  result = newNodeP(nkPar, p)
+  getTok(p)
+  optInd(p, result)
+  if p.tok.tokType in {tkDiscard, tkInclude, tkIf, tkWhile, tkCase, 
+                       tkTry, tkFinally, tkExcept, tkFor, tkBlock, 
+                       tkConst, tkLet, tkWhen, tkVar, tkBind, 
+                       tkMixin, tkSemicolon}:
+    semiStmtList(p, result)
+  elif p.tok.tokType != tkParRi:
+    var a = simpleExpr(p)
+    if p.tok.tokType == tkEquals:
+      # special case: allow assignments
+      getTok(p)
+      optInd(p, result)
+      let b = parseExpr(p)
+      let asgn = newNodeI(nkAsgn, a.info, 2)
+      asgn.sons[0] = a
+      asgn.sons[1] = b
+      result.add(asgn)
+    elif p.tok.tokType == tkSemicolon:
+      # stmt context:
+      result.add(a)
+      semiStmtList(p, result)
+    else:
+      a = colonOrEquals(p, a)
+      result.add(a)
+      if p.tok.tokType == tkComma:
+        getTok(p)
+        skipComment(p, a)
+        while p.tok.tokType != tkParRi and p.tok.tokType != tkEof:
+          var a = exprColonEqExpr(p)
+          addSon(result, a)
+          if p.tok.tokType != tkComma: break 
+          getTok(p)
+          skipComment(p, a)
+  optPar(p)
+  eat(p, tkParRi)
+
+proc identOrLiteral(p: var TParser, mode: TPrimaryMode): PNode = 
+  #| generalizedLit = GENERALIZED_STR_LIT | GENERALIZED_TRIPLESTR_LIT
   #| identOrLiteral = generalizedLit | symbol 
   #|                | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
   #|                | UINT_LIT | UINT8_LIT | UINT16_LIT | UINT32_LIT | UINT64_LIT
@@ -453,7 +523,7 @@ proc identOrLiteral(p: var TParser): PNode =
   #|                | STR_LIT | RSTR_LIT | TRIPLESTR_LIT
   #|                | CHAR_LIT
   #|                | NIL
-  #|                | tupleConstr | arrayConstr | setOrTableConstr
+  #|                | par | arrayConstr | setOrTableConstr
   #|                | castExpr
   #| tupleConstr = '(' optInd (exprColonEqExpr comma?)* optPar ')'
   #| arrayConstr = '[' optInd (exprColonEqExpr comma?)* optPar ']'
@@ -537,7 +607,10 @@ proc identOrLiteral(p: var TParser): PNode =
     getTok(p)
   of tkParLe:
     # () constructor
-    result = exprColonEqExprList(p, nkPar, tkParRi)
+    if mode in {pmTypeDesc, pmTypeDef}:
+      result = exprColonEqExprList(p, nkPar, tkParRi)
+    else:
+      result = parsePar(p)
   of tkCurlyLe:
     # {} constructor
     result = setOrTableConstr(p)
@@ -583,9 +656,6 @@ proc primarySuffix(p: var TParser, r: PNode): PNode =
       result = indexExprList(p, result, nkCurlyExpr, tkCurlyRi)
     else: break
 
-type
-  TPrimaryMode = enum pmNormal, pmTypeDesc, pmTypeDef, pmSkipSuffix
-
 proc primary(p: var TParser, mode: TPrimaryMode): PNode
 
 proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode =
@@ -926,7 +996,7 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
     optInd(p, result)
     addSon(result, primary(p, pmNormal))
   else:
-    result = identOrLiteral(p)
+    result = identOrLiteral(p, mode)
     if mode != pmSkipSuffix:
       result = primarySuffix(p, result)