* refs #15667 improve invalid indentation errors * also show line info where = is missing * add test * add more tests
This commit is contained in:
parent
1822ed384a
commit
08262206d3
3 changed files with 74 additions and 4 deletions
|
|
@ -163,6 +163,7 @@ proc prettyTok*(tok: Token): string =
|
||||||
else: $tok
|
else: $tok
|
||||||
|
|
||||||
proc printTok*(conf: ConfigRef; tok: Token) =
|
proc printTok*(conf: ConfigRef; tok: Token) =
|
||||||
|
# xxx factor with toLocation
|
||||||
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" & $tok.tokType & " " & $tok)
|
msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" & $tok.tokType & " " & $tok)
|
||||||
|
|
||||||
proc initToken*(L: var Token) =
|
proc initToken*(L: var Token) =
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,9 @@ type
|
||||||
hasProgress: bool # some while loop requires progress ensurance
|
hasProgress: bool # some while loop requires progress ensurance
|
||||||
lex*: Lexer # The lexer that is used for parsing
|
lex*: Lexer # The lexer that is used for parsing
|
||||||
tok*: Token # The current token
|
tok*: Token # The current token
|
||||||
|
lineStartPrevious*: int
|
||||||
|
lineNumberPrevious*: int
|
||||||
|
bufposPrevious*: int
|
||||||
inPragma*: int # Pragma level
|
inPragma*: int # Pragma level
|
||||||
inSemiStmtList*: int
|
inSemiStmtList*: int
|
||||||
emptyNode: PNode
|
emptyNode: PNode
|
||||||
|
|
@ -77,7 +80,7 @@ proc eat*(p: var Parser, tokType: TokType)
|
||||||
proc skipInd*(p: var Parser)
|
proc skipInd*(p: var Parser)
|
||||||
proc optPar*(p: var Parser)
|
proc optPar*(p: var Parser)
|
||||||
proc optInd*(p: var Parser, n: PNode)
|
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 setBaseFlags*(n: PNode, base: NumericalBase)
|
||||||
proc parseSymbol*(p: var Parser, mode = smNormal): PNode
|
proc parseSymbol*(p: var Parser, mode = smNormal): PNode
|
||||||
proc parseTry(p: var Parser; isExpr: bool): PNode
|
proc parseTry(p: var Parser; isExpr: bool): PNode
|
||||||
|
|
@ -100,6 +103,9 @@ template prettySection(body) =
|
||||||
proc getTok(p: var Parser) =
|
proc getTok(p: var Parser) =
|
||||||
## Get the next token from the parser's lexer, and store it in the parser's
|
## Get the next token from the parser's lexer, and store it in the parser's
|
||||||
## `tok` member.
|
## `tok` member.
|
||||||
|
p.lineNumberPrevious = p.lex.lineNumber
|
||||||
|
p.lineStartPrevious = p.lex.lineStart
|
||||||
|
p.bufposPrevious = p.lex.bufpos
|
||||||
rawGetTok(p.lex, p.tok)
|
rawGetTok(p.lex, p.tok)
|
||||||
p.hasProgress = true
|
p.hasProgress = true
|
||||||
when defined(nimpretty):
|
when defined(nimpretty):
|
||||||
|
|
@ -223,9 +229,13 @@ proc parLineInfo(p: Parser): TLineInfo =
|
||||||
## Retrieve the line information associated with the parser's current state.
|
## Retrieve the line information associated with the parser's current state.
|
||||||
result = getLineInfo(p.lex, p.tok)
|
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.indent > p.currInd:
|
||||||
if p.tok.tokType == tkComment: rawSkipComment(p, n)
|
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: parMessage(p, errInvalidIndentation)
|
||||||
else:
|
else:
|
||||||
skipComment(p, n)
|
skipComment(p, n)
|
||||||
|
|
@ -1773,13 +1783,14 @@ proc parseRoutine(p: var Parser, kind: TNodeKind): PNode =
|
||||||
else: result.add(p.emptyNode)
|
else: result.add(p.emptyNode)
|
||||||
# empty exception tracking:
|
# empty exception tracking:
|
||||||
result.add(p.emptyNode)
|
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)
|
getTok(p)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
result.add(parseStmt(p))
|
result.add(parseStmt(p))
|
||||||
else:
|
else:
|
||||||
result.add(p.emptyNode)
|
result.add(p.emptyNode)
|
||||||
indAndComment(p, result)
|
indAndComment(p, result, maybeMissEquals)
|
||||||
|
|
||||||
proc newCommentStmt(p: var Parser): PNode =
|
proc newCommentStmt(p: var Parser): PNode =
|
||||||
#| commentStmt = COMMENT
|
#| commentStmt = COMMENT
|
||||||
|
|
|
||||||
58
tests/parser/t15667.nim
Normal file
58
tests/parser/t15667.nim
Normal file
|
|
@ -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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue