summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/lexer.nim1
-rw-r--r--compiler/parser.nim19
-rw-r--r--tests/parser/t15667.nim58
3 files changed, 74 insertions, 4 deletions
diff --git a/compiler/lexer.nim b/compiler/lexer.nim
index 7c7ac4177..59b983060 100644
--- a/compiler/lexer.nim
+++ b/compiler/lexer.nim
@@ -163,6 +163,7 @@ proc prettyTok*(tok: Token): string =
   else: $tok
 
 proc printTok*(conf: ConfigRef; tok: Token) =
+  # xxx factor with toLocation
   msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" & $tok.tokType & " " & $tok)
 
 proc initToken*(L: var Token) =
diff --git a/compiler/parser.nim b/compiler/parser.nim
index d103d161a..fd9d06de5 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -44,6 +44,9 @@ type
     hasProgress: bool         # some while loop requires progress ensurance
     lex*: Lexer               # The lexer that is used for parsing
     tok*: Token               # The current token
+    lineStartPrevious*: int
+    lineNumberPrevious*: int
+    bufposPrevious*: int
     inPragma*: int            # Pragma level
     inSemiStmtList*: int
     emptyNode: PNode
@@ -77,7 +80,7 @@ proc eat*(p: var Parser, tokType: TokType)
 proc skipInd*(p: var Parser)
 proc optPar*(p: var Parser)
 proc optInd*(p: var Parser, n: PNode)
-proc indAndComment*(p: var Parser, n: PNode)
+proc indAndComment*(p: var Parser, n: PNode, maybeMissEquals = false)
 proc setBaseFlags*(n: PNode, base: NumericalBase)
 proc parseSymbol*(p: var Parser, mode = smNormal): PNode
 proc parseTry(p: var Parser; isExpr: bool): PNode
@@ -100,6 +103,9 @@ template prettySection(body) =
 proc getTok(p: var Parser) =
   ## Get the next token from the parser's lexer, and store it in the parser's
   ## `tok` member.
+  p.lineNumberPrevious = p.lex.lineNumber
+  p.lineStartPrevious = p.lex.lineStart
+  p.bufposPrevious = p.lex.bufpos
   rawGetTok(p.lex, p.tok)
   p.hasProgress = true
   when defined(nimpretty):
@@ -223,9 +229,13 @@ proc parLineInfo(p: Parser): TLineInfo =
   ## Retrieve the line information associated with the parser's current state.
   result = getLineInfo(p.lex, p.tok)
 
-proc indAndComment(p: var Parser, n: PNode) =
+proc indAndComment(p: var Parser, n: PNode, maybeMissEquals = false) =
   if p.tok.indent > p.currInd:
     if p.tok.tokType == tkComment: rawSkipComment(p, n)
+    elif maybeMissEquals:
+      let col = p.bufposPrevious - p.lineStartPrevious
+      var info = newLineInfo(p.lex.fileIdx, p.lineNumberPrevious, col)
+      parMessage(p, "invalid indentation, maybe you forgot a '=' at $1 ?" % [p.lex.config$info])
     else: parMessage(p, errInvalidIndentation)
   else:
     skipComment(p, n)
@@ -1773,13 +1783,14 @@ proc parseRoutine(p: var Parser, kind: TNodeKind): PNode =
   else: result.add(p.emptyNode)
   # empty exception tracking:
   result.add(p.emptyNode)
-  if p.tok.tokType == tkEquals and p.validInd:
+  let maybeMissEquals = p.tok.tokType != tkEquals
+  if (not maybeMissEquals) and p.validInd:
     getTok(p)
     skipComment(p, result)
     result.add(parseStmt(p))
   else:
     result.add(p.emptyNode)
-  indAndComment(p, result)
+  indAndComment(p, result, maybeMissEquals)
 
 proc newCommentStmt(p: var Parser): PNode =
   #| commentStmt = COMMENT
diff --git a/tests/parser/t15667.nim b/tests/parser/t15667.nim
new file mode 100644
index 000000000..d15178789
--- /dev/null
+++ b/tests/parser/t15667.nim
@@ -0,0 +1,58 @@
+discard """
+  cmd: "nim check $options $file"
+  action: "reject"
+  nimout: '''
+t15667.nim(23, 5) Error: invalid indentation, maybe you forgot a '=' at t15667.nim(22, 13) ?
+t15667.nim(28, 5) Error: invalid indentation, maybe you forgot a '=' at t15667.nim(26, 13) ?
+t15667.nim(33, 5) Error: invalid indentation, maybe you forgot a '=' at t15667.nim(31, 25) ?
+t15667.nim(42, 5) Error: invalid indentation, maybe you forgot a '=' at t15667.nim(38, 12) ?
+t15667.nim(56, 5) Error: invalid indentation, maybe you forgot a '=' at t15667.nim(55, 13) ?
+'''
+"""
+
+
+
+
+
+
+
+
+# line 20
+block:
+  proc fn1()
+    discard
+
+block:
+  proc fn2()
+    #
+    discard
+
+block:
+  proc fn3() {.exportc.}
+    #
+    discard
+
+block: # complex example
+  proc asdfasdfsd() {. exportc, 
+      inline
+         .}     # foo
+    #[
+    bar
+    ]#
+    discard
+
+block: # xxx this doesn't work yet (only a bare `invalid indentation` error)
+  proc fn5()
+    ##
+    discard
+
+block: # ditto
+  proc fn6*()
+    ## foo bar
+    runnableExamples: discard
+
+block:
+  proc fn8()
+    runnableExamples:
+      discard
+    discard