Files
Nim/tools/grammar_nanny.nim
Jacek Sieka e1a0ff1b8a lexer cleanups (#23037)
* remove some dead code and leftovers from past features
* fix yaml printing of uint64 literals
2023-12-06 18:17:57 +01:00

55 lines
1.6 KiB
Nim

## Simple tool to check for obvious mistakes in Nim's
## grammar.txt file.
import std / [strutils, sets]
when defined(nimPreviewSlimSystem):
import std/syncio
import ".." / compiler / [
llstream, lexer, options, msgs, idents,
lineinfos, pathutils]
proc checkGrammarFileImpl(cache: IdentCache, config: ConfigRef) =
var f = AbsoluteFile"doc/grammar.txt"
let data = readFile(f.string).multiReplace({"IND{=}": "SAME_IND", "'": "\""})
var stream = llStreamOpen(data)
var declaredSyms = initHashSet[string]()
var usedSyms = initHashSet[string]()
usedSyms.incl "module" # 'module' is the start rule.
if stream != nil:
declaredSyms.incl "section" # special case for 'section(RULE)' in the grammar
var
L: Lexer
tok: Token
openLexer(L, f, stream, cache, config)
# load the first token:
rawGetTok(L, tok)
var word = ""
while tok.tokType != tkEof:
#printTok(config, tok)
if isKeyword(tok.tokType) or tok.tokType == tkSymbol:
word = tok.ident.s
rawGetTok(L, tok)
if tok.tokType == tkEquals:
declaredSyms.incl word
rawGetTok(L, tok)
elif not allCharsInSet(word, {'A'..'Z', '0'..'9', '_'}):
usedSyms.incl word
else:
rawGetTok(L, tok)
for u in declaredSyms:
if u notin usedSyms:
echo "Unused non-terminal: ", u
for u in usedSyms:
if u notin declaredSyms:
echo "Undeclared non-terminal: ", u
closeLexer(L)
else:
rawMessage(config, errGenerated, "cannot open file: " & f.string)
proc checkGrammarFile* =
checkGrammarFileImpl(newIdentCache(), newConfigRef())