summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2017-11-05 01:25:39 +0100
committerAraq <rumpf_a@web.de>2017-11-05 01:26:04 +0100
commit742f43e57211c22fe1faa0c7ef991b9b0a1eadc9 (patch)
tree46bce5f9cf13f1f6f8dd45fc461615f779deb648
parent9212aa9c0c7fe29c15485b9e0a841aca8359acfb (diff)
downloadNim-742f43e57211c22fe1faa0c7ef991b9b0a1eadc9.tar.gz
fixes #6609; 'if' expressions support multiple statements; minor breaking change
-rw-r--r--changelog.md15
-rw-r--r--compiler/parser.nim70
-rw-r--r--lib/packages/docutils/rstgen.nim3
-rw-r--r--lib/system/sysstr.nim2
-rw-r--r--tests/parser/tletcolon.nim18
5 files changed, 91 insertions, 17 deletions
diff --git a/changelog.md b/changelog.md
index eebd47fb8..5947c49e5 100644
--- a/changelog.md
+++ b/changelog.md
@@ -39,5 +39,18 @@
 - Added ``typetraits.$`` as an alias for ``typetraits.name``.
 - ``os.getEnv`` now takes an optional ``default`` parameter that tells ``getEnv``
   what to return if the environment variable does not exist.
-- Removed PDCurses wrapper from the stdlib and published it as a separate 
+- Removed PDCurses wrapper from the stdlib and published it as a separate
   Nimble package.
+- The parsing rules of ``if`` expressions were changed so that multiple
+  statements are allowed in the branches. We found few code examples that
+  now fail because of this change, but here is one:
+
+.. code-block:: nim
+
+  t[ti] = if exp_negative: '-' else: '+'; inc(ti)
+
+This now needs to be written as:
+
+.. code-block:: nim
+
+  t[ti] = (if exp_negative: '-' else: '+'); inc(ti)
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 113922189..e3bb68da4 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -785,21 +785,58 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
   #|          'else' colcom expr
   #| ifExpr = 'if' condExpr
   #| whenExpr = 'when' condExpr
-  result = newNodeP(kind, p)
-  while true:
-    getTok(p)                 # skip `if`, `elif`
-    var branch = newNodeP(nkElifExpr, p)
+  when true:
+    result = newNodeP(kind, p)
+    while true:
+      getTok(p)                 # skip `if`, `when`, `elif`
+      var branch = newNodeP(nkElifExpr, p)
+      optInd(p, branch)
+      addSon(branch, parseExpr(p))
+      colcom(p, branch)
+      addSon(branch, parseStmt(p))
+      skipComment(p, branch)
+      addSon(result, branch)
+      if p.tok.tokType != tkElif: break # or not sameOrNoInd(p): break
+    if p.tok.tokType == tkElse: # and sameOrNoInd(p):
+      var branch = newNodeP(nkElseExpr, p)
+      eat(p, tkElse)
+      colcom(p, branch)
+      addSon(branch, parseStmt(p))
+      addSon(result, branch)
+  else:
+    var
+      b: PNode
+      wasIndented = false
+    result = newNodeP(kind, p)
+
+    getTok(p)
+    let branch = newNodeP(nkElifExpr, p)
     addSon(branch, parseExpr(p))
     colcom(p, branch)
+    let oldInd = p.currInd
+    if realInd(p):
+      p.currInd = p.tok.indent
+      wasIndented = true
+      echo result.info, " yes ", p.currInd
     addSon(branch, parseExpr(p))
-    optInd(p, branch)
-    addSon(result, branch)
-    if p.tok.tokType != tkElif: break
-  var branch = newNodeP(nkElseExpr, p)
-  eat(p, tkElse)
-  colcom(p, branch)
-  addSon(branch, parseExpr(p))
-  addSon(result, branch)
+    result.add branch
+    while sameInd(p) or not wasIndented:
+      case p.tok.tokType
+      of tkElif:
+        b = newNodeP(nkElifExpr, p)
+        getTok(p)
+        optInd(p, b)
+        addSon(b, parseExpr(p))
+      of tkElse:
+        b = newNodeP(nkElseExpr, p)
+        getTok(p)
+      else: break
+      colcom(p, b)
+      addSon(b, parseStmt(p))
+      addSon(result, b)
+      if b.kind == nkElseExpr: break
+    if wasIndented:
+      p.currInd = oldInd
 
 proc parsePragma(p: var TParser): PNode =
   #| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
@@ -2036,8 +2073,13 @@ proc parseStmt(p: var TParser): PNode =
         if a.kind != nkEmpty:
           addSon(result, a)
         else:
-          parMessage(p, errExprExpected, p.tok)
-          getTok(p)
+          # This is done to make the new 'if' expressions work better.
+          # XXX Eventually we need to be more strict here.
+          if p.tok.tokType notin {tkElse, tkElif}:
+            parMessage(p, errExprExpected, p.tok)
+            getTok(p)
+          else:
+            break
         if not p.hasProgress and p.tok.tokType == tkEof: break
   else:
     # the case statement is only needed for better error messages:
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index 13016bfc0..6fed40141 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -798,7 +798,8 @@ proc renderImage(d: PDoc, n: PRstNode, result: var string) =
   if arg.valid:
     let htmlOut = if isObject:
         "<object data=\"$1\" type=\"image/svg+xml\"$2 >" & content & "</object>"
-        else: "<img src=\"$1\"$2 />"
+      else:
+        "<img src=\"$1\"$2 />"
     dispA(d.target, result, htmlOut, "\\includegraphics$2{$1}",
           [arg, options])
   if len(n) >= 3: renderRstToOut(d, n.sons[2], result)
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 0627ef2fb..d9586b00d 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -509,7 +509,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
 
   # insert exponent
   t[ti] = 'E'; inc(ti)
-  t[ti] = if exp_negative: '-' else: '+'; inc(ti)
+  t[ti] = (if exp_negative: '-' else: '+'); inc(ti)
   inc(ti, 3)
 
   # insert adjusted exponent
diff --git a/tests/parser/tletcolon.nim b/tests/parser/tletcolon.nim
index 6b86535c8..eab7a8edd 100644
--- a/tests/parser/tletcolon.nim
+++ b/tests/parser/tletcolon.nim
@@ -32,3 +32,21 @@ let other = x:
     echo "no"
 let outer = y(5):
   echo "yes"
+
+
+# bug #6609
+type
+  TextureInternalFormat = enum RED, RGB, RGBA
+
+const channels = 4
+
+let format =
+    if channels == 1:
+        TextureInternalFormat.RED
+    elif channels == 3:
+        TextureInternalFormat.RGB
+    elif channels == 4:
+        TextureInternalFormat.RGBA
+    else:
+        echo "Texture Format Unknown, assuming RGB"  #This echo causes an error
+        TextureInternalFormat.RGB