123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 |
- ## Simple tool to check for obvious mistakes in Nim's
- ## grammar.txt file.
- import std / [strutils, sets]
- import ".." / compiler / [
- llstream, ast, 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]()
- if stream != nil:
- declaredSyms.incl "section" # special case for 'section(RULE)' in the grammar
- var
- L: TLexer
- tok: TToken
- 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 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())
|