summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/lexer.nim38
-rw-r--r--doc/manual/lexing.txt23
-rw-r--r--lib/packages/docutils/highlite.nim41
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim4
4 files changed, 63 insertions, 43 deletions
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index 70a555e15..4c1dd366b 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -773,9 +773,6 @@ proc skipMultiLineComment(L: var TLexer; tok: var TToken; start: int;
                           isDoc: bool) =
   var pos = start
   var buf = L.buf
-  while buf[pos] == '[':
-    inc pos
-  let brackets = pos - start
   var toStrip = 0
   # detect the amount of indentation:
   if isDoc:
@@ -788,18 +785,31 @@ proc skipMultiLineComment(L: var TLexer; tok: var TToken; start: int;
       while buf[pos] == ' ':
         inc pos
         inc toStrip
+  var nesting = 0
   while true:
     case buf[pos]
+    of '#':
+      if isDoc:
+        if buf[pos+1] == '#' and buf[pos+2] == '[':
+          inc nesting
+        tok.literal.add '#'
+      elif buf[pos+1] == '[':
+        inc nesting
+      inc pos
     of ']':
-      var p = pos
-      while buf[p] == ']':
-        inc p
-      if p-pos == brackets:
-        pos = p
-        break
-      else:
-        if isDoc: tok.literal.add ']'
-        inc pos
+      if isDoc:
+        if buf[pos+1] == '#' and buf[pos+2] == '#':
+          if nesting == 0:
+            inc(pos, 3)
+            break
+          dec nesting
+        tok.literal.add ']'
+      elif buf[pos+1] == '#':
+        if nesting == 0:
+          inc(pos, 2)
+          break
+        dec nesting
+      inc pos
     of '\t':
       lexMessagePos(L, errTabulatorsAreNotAllowed, pos)
       inc(pos)
@@ -832,7 +842,7 @@ proc scanComment(L: var TLexer, tok: var TToken) =
   when not defined(nimfix):
     assert buf[pos+1] == '#'
     if buf[pos+2] == '[':
-      skipMultiLineComment(L, tok, pos+2, true)
+      skipMultiLineComment(L, tok, pos+3, true)
       return
     inc(pos, 2)
 
@@ -923,7 +933,7 @@ proc skip(L: var TLexer, tok: var TToken) =
         # do not skip documentation comment:
         if buf[pos+1] == '#': break
         if buf[pos+1] == '[':
-          skipMultiLineComment(L, tok, pos+1, false)
+          skipMultiLineComment(L, tok, pos+2, false)
           return
         while buf[pos] notin {CR, LF, nimlexbase.EndOfFile}: inc(pos)
     else:
diff --git a/doc/manual/lexing.txt b/doc/manual/lexing.txt
index a5c3dfd6d..7655964ee 100644
--- a/doc/manual/lexing.txt
+++ b/doc/manual/lexing.txt
@@ -78,33 +78,24 @@ They look like:
 .. code-block:: nim
   #[Comment here.
   Multiple lines
-  are not a problem.]
+  are not a problem.]#
 
-.. code-block:: nim
-  #[[comment here]]
-
-.. code-block:: nim
-  #[[[comment here]]]
-
-.. code-block:: nim
-  #[[[[comment here]]]]
-
-The number of opening brackets must match the number of closing brackets
-but they do not nest in the traditional sense:
+Multiline comments support nesting:
 
 .. code-block:: nim
   # Does not comment out 'p' properly:
-  #[
+  #[  #[ Multiline comment in already
+     commented out code. ]#
   proc p[T](x: T) = discard
-  ]
+  ]#
 
-Multiline documentation comments look like:
+Multiline documentation comments look like and support nesting too:
 
 .. code-block:: nim
   proc foo =
     ##[Long documentation comment
     here.
-    ]
+    ]##
 
 
 Identifiers & Keywords
diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim
index 570465e14..1bc0af1b6 100644
--- a/lib/packages/docutils/highlite.nim
+++ b/lib/packages/docutils/highlite.nim
@@ -174,19 +174,38 @@ proc nimNextToken(g: var GeneralTokenizer) =
     of '#':
       g.kind = gtComment
       inc(pos)
-      if g.buf[pos] == '#': inc(pos)
+      var isDoc = false
+      if g.buf[pos] == '#':
+        inc(pos)
+        isDoc = true
       if g.buf[pos] == '[':
         g.kind = gtLongComment
-        var brackets = 0
-        while g.buf[pos] == '[':
-          inc(pos)
-          inc(brackets)
-        while g.buf[pos] != '\0':
-          if g.buf[pos] == ']':
-            var q = pos
-            while g.buf[pos] == ']': inc(pos)
-            if pos-q == brackets: break
-          inc(pos)
+        var nesting = 0
+        while true:
+          case g.buf[pos]
+          of '\0': break
+          of '#':
+            if isDoc:
+              if g.buf[pos+1] == '#' and g.buf[pos+2] == '[':
+                inc nesting
+            elif g.buf[pos+1] == '[':
+              inc nesting
+            inc pos
+          of ']':
+            if isDoc:
+              if g.buf[pos+1] == '#' and g.buf[pos+2] == '#':
+                if nesting == 0:
+                  inc(pos, 3)
+                  break
+                dec nesting
+            elif g.buf[pos+1] == '#':
+              if nesting == 0:
+                inc(pos, 2)
+                break
+              dec nesting
+            inc pos
+          else:
+            inc pos
       else:
         while g.buf[pos] notin {'\0', '\x0A', '\x0D'}: inc(pos)
     of 'a'..'z', 'A'..'Z', '_', '\x80'..'\xFF':
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
index e64b818fa..142b190ab 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
@@ -131,10 +131,10 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} =
           emptyNode())),
       emptyNode(),
       emptyNode(),
-      newNimNode(nnkStmtList).und(#[6]
+      newNimNode(nnkStmtList).und(# [6]
         newNimNode(nnkAsgn).und(
           ^"result",                  ## result =
-          newNimNode(nnkCall).und(#[6][0][1]
+          newNimNode(nnkCall).und(# [6][0][1]
             ^"format",  ## format
             emptyNode()))))  ## "[TypeName   $1   $2]"
     formatStr = "["& $typeName.ident