1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556 |
- ## 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
- initToken(tok)
- 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())
|