summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2023-06-06 07:53:21 +0300
committerGitHub <noreply@github.com>2023-06-06 06:53:21 +0200
commit2ab948ce53e3d9b80bf9b02644c8ec8991f34d0a (patch)
tree0382d24fc7fd4c09397bc56bf7dccc7ba5b19e42
parent0a212f97a5dd4d5dd1ea84f370bd27abe55a818e (diff)
downloadNim-2ab948ce53e3d9b80bf9b02644c8ec8991f34d0a.tar.gz
post expr blocks colon fix + correct grammar (#21983)
* post expr blocks colon fix + correct grammar

fixes #21982

* fix dochelpers

* this is remarkably common

* use head for unchained

* fix atlas

* final grammar fix
-rw-r--r--atlas/atlas.nim2
-rw-r--r--compiler/parser.nim28
-rw-r--r--doc/grammar.txt26
-rw-r--r--lib/packages/docutils/dochelpers.nim2
-rw-r--r--lib/pure/pegs.nim4
-rw-r--r--testament/important_packages.nim3
-rw-r--r--testament/lib/stdtest/testutils.nim2
-rw-r--r--tests/parser/tifextracolon.nim8
8 files changed, 46 insertions, 29 deletions
diff --git a/atlas/atlas.nim b/atlas/atlas.nim
index 70d0c37af..18142da70 100644
--- a/atlas/atlas.nim
+++ b/atlas/atlas.nim
@@ -679,7 +679,7 @@ proc isNewerVersion(a, b: string): bool =
     result = (amajor, aminor) > (bmajor, bminor)
 
 proc isLaterCommit(destDir, version: string): bool =
-  let oldVersion = try: readFile(destDir / ThisVersion).strip: except: "0.0"
+  let oldVersion = try: readFile(destDir / ThisVersion).strip except: "0.0"
   result = isNewerVersion(version, oldVersion)
 
 proc traverseLoop(c: var AtlasContext; g: var DepGraph; startIsDep: bool): seq[CfgPath] =
diff --git a/compiler/parser.nim b/compiler/parser.nim
index babbb87fd..734474dbf 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -436,7 +436,8 @@ proc colonOrEquals(p: var Parser, a: PNode): PNode =
     result = equals(p, a)
 
 proc exprColonEqExpr(p: var Parser): PNode =
-  #| exprColonEqExpr = expr (':'|'=' expr)?
+  #| exprColonEqExpr = expr ((':'|'=') expr
+  #|                        / doBlock extraPostExprBlock*)?
   var a = parseExpr(p)
   if p.tok.tokType == tkDo:
     result = postExprBlocks(p, a)
@@ -444,7 +445,8 @@ proc exprColonEqExpr(p: var Parser): PNode =
     result = colonOrEquals(p, a)
 
 proc exprEqExpr(p: var Parser): PNode =
-  #| exprEqExpr = expr ('=' expr)?
+  #| exprEqExpr = expr ('=' expr
+  #|                   / doBlock extraPostExprBlock*)?
   var a = parseExpr(p)
   if p.tok.tokType == tkDo:
     result = postExprBlocks(p, a)
@@ -647,7 +649,8 @@ proc parsePar(p: var Parser): PNode =
   #|           ( &parKeyw (ifExpr / complexOrSimpleStmt) ^+ ';'
   #|           | ';' (ifExpr / complexOrSimpleStmt) ^+ ';'
   #|           | pragmaStmt
-  #|           | simpleExpr ( ('=' expr (';' (ifExpr / complexOrSimpleStmt) ^+ ';' )? )
+  #|           | simpleExpr ( (doBlock extraPostExprBlock*)
+  #|                        | ('=' expr (';' (ifExpr / complexOrSimpleStmt) ^+ ';' )? )
   #|                        | (':' expr (',' exprColonEqExpr     ^+ ',' )? ) ) )
   #|           optPar ')'
   #
@@ -1336,7 +1339,7 @@ proc primary(p: var Parser, mode: PrimaryMode): PNode =
   #| simplePrimary = SIGILLIKEOP? identOrLiteral primarySuffix*
   #| commandStart = &('`'|IDENT|literal|'cast'|'addr'|'type'|'var'|'out'|
   #|                  'static'|'enum'|'tuple'|'object'|'proc')
-  #| primary = simplePrimary (commandStart expr)
+  #| primary = simplePrimary (commandStart expr (doBlock extraPostExprBlock*)?)?
   #|         / operatorB primary
   #|         / routineExpr
   #|         / rawTypeDesc
@@ -1441,7 +1444,7 @@ proc parseTypeDesc(p: var Parser, fullExpr = false): PNode =
 proc parseTypeDefValue(p: var Parser): PNode =
   #| typeDefValue = ((tupleDecl | enumDecl | objectDecl | conceptDecl |
   #|                  ('ref' | 'ptr' | 'distinct') (tupleDecl | objectDecl))
-  #|                / (simpleExpr (exprEqExpr ^+ comma postExprBlocks)?))
+  #|                / (simpleExpr (exprEqExpr ^+ comma postExprBlocks?)?))
   #|                ('not' expr)?
   case p.tok.tokType
   of tkTuple: result = parseTuple(p, true)
@@ -1478,12 +1481,13 @@ proc makeCall(n: PNode): PNode =
     result.add n
 
 proc postExprBlocks(p: var Parser, x: PNode): PNode =
-  #| postExprBlocks = ':' stmt? ( IND{=} doBlock
-  #|                            | IND{=} 'of' exprList ':' stmt
-  #|                            | IND{=} 'elif' expr ':' stmt
-  #|                            | IND{=} 'except' optionalExprList ':' stmt
-  #|                            | IND{=} 'finally' ':' stmt
-  #|                            | IND{=} 'else' ':' stmt )*
+  #| extraPostExprBlock = ( IND{=} doBlock
+  #|                      | IND{=} 'of' exprList ':' stmt
+  #|                      | IND{=} 'elif' expr ':' stmt
+  #|                      | IND{=} 'except' optionalExprList ':' stmt
+  #|                      | IND{=} 'finally' ':' stmt
+  #|                      | IND{=} 'else' ':' stmt )
+  #| postExprBlocks = (doBlock / ':' (extraPostExprBlock / stmt)) extraPostExprBlock*
   result = x
   if p.tok.indent >= 0: return
 
@@ -1500,7 +1504,7 @@ proc postExprBlocks(p: var Parser, x: PNode): PNode =
     result = makeCall(result)
     getTok(p)
     skipComment(p, result)
-    if p.tok.tokType notin {tkOf, tkElif, tkElse, tkExcept, tkFinally}:
+    if not (p.tok.tokType in {tkOf, tkElif, tkElse, tkExcept, tkFinally} and sameInd(p)):
       var stmtList = newNodeP(nkStmtList, p)
       stmtList.add parseStmt(p)
       # to keep backwards compatibility (see tests/vm/tstringnil)
diff --git a/doc/grammar.txt b/doc/grammar.txt
index 89095d65c..e498dd2b2 100644
--- a/doc/grammar.txt
+++ b/doc/grammar.txt
@@ -28,8 +28,10 @@ operatorB = OP0 | OP1 | OP2 | OP3 | OP4 | OP5 | OP6 | OP7 | OP8 | OP9 |
 symbol = '`' (KEYW|IDENT|literal|(operator|'('|')'|'['|']'|'{'|'}'|'=')+)+ '`'
        | IDENT | 'addr' | 'type' | 'static'
 symbolOrKeyword = symbol | KEYW
-exprColonEqExpr = expr (':'|'=' expr)?
-exprEqExpr = expr ('=' expr)?
+exprColonEqExpr = expr ((':'|'=') expr
+                       / doBlock extraPostExprBlock*)?
+exprEqExpr = expr ('=' expr
+                  / doBlock extraPostExprBlock*)?
 exprList = expr ^+ comma
 optionalExprList = expr ^* comma
 exprColonEqExprList = exprColonEqExpr (comma exprColonEqExpr)* (comma)?
@@ -43,7 +45,8 @@ par = '(' optInd
           ( &parKeyw (ifExpr / complexOrSimpleStmt) ^+ ';'
           | ';' (ifExpr / complexOrSimpleStmt) ^+ ';'
           | pragmaStmt
-          | simpleExpr ( ('=' expr (';' (ifExpr / complexOrSimpleStmt) ^+ ';' )? )
+          | simpleExpr ( (doBlock extraPostExprBlock*)
+                       | ('=' expr (';' (ifExpr / complexOrSimpleStmt) ^+ ';' )? )
                        | (':' expr (',' exprColonEqExpr     ^+ ',' )? ) ) )
           optPar ')'
 literal = | INT_LIT | INT8_LIT | INT16_LIT | INT32_LIT | INT64_LIT
@@ -94,7 +97,7 @@ expr = (blockExpr
 simplePrimary = SIGILLIKEOP? identOrLiteral primarySuffix*
 commandStart = &('`'|IDENT|literal|'cast'|'addr'|'type'|'var'|'out'|
                  'static'|'enum'|'tuple'|'object'|'proc')
-primary = simplePrimary (commandStart expr)
+primary = simplePrimary (commandStart expr (doBlock extraPostExprBlock*)?)?
         / operatorB primary
         / routineExpr
         / rawTypeDesc
@@ -106,14 +109,15 @@ typeDescExpr = (routineType / simpleExpr) ('not' expr)?
 typeDesc = rawTypeDesc / typeDescExpr
 typeDefValue = ((tupleDecl | enumDecl | objectDecl | conceptDecl |
                  ('ref' | 'ptr' | 'distinct') (tupleDecl | objectDecl))
-               / (simpleExpr (exprEqExpr ^+ comma postExprBlocks)?))
+               / (simpleExpr (exprEqExpr ^+ comma postExprBlocks?)?))
                ('not' expr)?
-postExprBlocks = ':' stmt? ( IND{=} doBlock
-                           | IND{=} 'of' exprList ':' stmt
-                           | IND{=} 'elif' expr ':' stmt
-                           | IND{=} 'except' optionalExprList ':' stmt
-                           | IND{=} 'finally' ':' stmt
-                           | IND{=} 'else' ':' stmt )*
+extraPostExprBlock = ( IND{=} doBlock
+                     | IND{=} 'of' exprList ':' stmt
+                     | IND{=} 'elif' expr ':' stmt
+                     | IND{=} 'except' optionalExprList ':' stmt
+                     | IND{=} 'finally' ':' stmt
+                     | IND{=} 'else' ':' stmt )
+postExprBlocks = (doBlock / ':' (extraPostExprBlock / stmt)) extraPostExprBlock*
 exprStmt = simpleExpr postExprBlocks?
          / simplePrimary (exprEqExpr ^+ comma) postExprBlocks?
          / simpleExpr '=' optInd (expr postExprBlocks?)
diff --git a/lib/packages/docutils/dochelpers.nim b/lib/packages/docutils/dochelpers.nim
index b7cdd16d2..7b257ffff 100644
--- a/lib/packages/docutils/dochelpers.nim
+++ b/lib/packages/docutils/dochelpers.nim
@@ -288,7 +288,7 @@ proc match*(generated: LangSymbol, docLink: LangSymbol): bool =
         if g.`type` == d.name:
           onlyType = true  # only types, not names, are provided in `docLink`
       if onlyType:
-        result = g.`type` == d.name:
+        result = g.`type` == d.name
       else:
         if d.`type` != "":
           result = g.`type` == d.`type`
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 86ad9c0f6..11683bbff 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -1042,7 +1042,7 @@ template eventParser*(pegAst, handlers: untyped): (proc(s: string): int) =
       # by *mkHandlerTplts*.
       template mkDoEnter(hdPostf, s, pegNode, start) =
         when declared(`enter hdPostf`):
-          `enter hdPostf`(s, pegNode, start):
+          `enter hdPostf`(s, pegNode, start)
         else:
           discard
       let hdPostf = ident(substr(strVal(pegKind), 2))
@@ -1053,7 +1053,7 @@ template eventParser*(pegAst, handlers: untyped): (proc(s: string): int) =
       # a grammar element of kind *pegKind*.
       template mkDoLeave(hdPostf, s, pegNode, start, length) =
         when declared(`leave hdPostf`):
-          `leave hdPostf`(s, pegNode, start, length):
+          `leave hdPostf`(s, pegNode, start, length)
         else:
           discard
       let hdPostf = ident(substr(strVal(pegKind), 2))
diff --git a/testament/important_packages.nim b/testament/important_packages.nim
index 6111a7c31..3230d5fab 100644
--- a/testament/important_packages.nim
+++ b/testament/important_packages.nim
@@ -91,7 +91,8 @@ pkg "lockfreequeues"
 pkg "macroutils"
 pkg "manu"
 pkg "markdown"
-pkg "measuremancer", "nimble testDeps; nimble -y test"
+pkg "measuremancer", "nimble install -y unchained@#HEAD; nimble -y test"
+# when unchained is version 0.3.7 or higher, use `nimble testDeps;`
 pkg "memo"
 pkg "msgpack4nim", "nim c -r tests/test_spec.nim"
 pkg "nake", "nim c nakefile.nim"
diff --git a/testament/lib/stdtest/testutils.nim b/testament/lib/stdtest/testutils.nim
index 12e6a56ab..66afd62af 100644
--- a/testament/lib/stdtest/testutils.nim
+++ b/testament/lib/stdtest/testutils.nim
@@ -40,7 +40,7 @@ when not defined(js) and not defined(nimscript):
         yield line
     template isMatch(lhsi, rhsi): bool =
       if allowPrefixMatch:
-        startsWith(rhsi, lhsi):
+        startsWith(rhsi, lhsi)
       else:
         lhsi == rhsi
 
diff --git a/tests/parser/tifextracolon.nim b/tests/parser/tifextracolon.nim
new file mode 100644
index 000000000..171569111
--- /dev/null
+++ b/tests/parser/tifextracolon.nim
@@ -0,0 +1,8 @@
+# issue #21982
+
+if true:
+  if true:
+    discard default int:
+else: #[tt.Error
+^ invalid indentation]#
+  discard