# # # The Nim Compiler # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # # This module handles the reading of the config file. import llstream, commands, os, strutils, msgs, lexer, options, idents, wordrecg, strtabs, lineinfos, pathutils # ---------------- configuration file parser ----------------------------- # we use Nim's scanner here to save space and work proc ppGetTok(L: var TLexer, tok: var TToken) = # simple filter rawGetTok(L, tok) while tok.tokType in {tkComment}: rawGetTok(L, tok) proc parseExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool proc parseAtom(L: var TLexer, tok: var TToken; config: ConfigRef): bool = if tok.tokType == tkParLe: ppGetTok(L, tok) result = parseExpr(L, tok, config) if tok.tokType == tkParRi: ppGetTok(L, tok) else: lexMessage(L, errGenerated, "expected closing ')'") elif tok.tokType == tkNot: ppGetTok(L, tok) result = not parseAtom(L, tok, config) else: result = isDefined(config, tok.ident.s) ppGetTok(L, tok) proc parseAndExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool = result = parseAtom(L, tok, config) while tok.tokType == tkAnd: ppGetTok(L, tok) # skip "and" var b = parseAtom(L, tok, config) result = result and b proc parseExpr(L: var TLexer, tok: var TToken; config: ConfigRef): bool = result = parseAndExpr(L, tok, config) while tok.tokType == tkOr: ppGetTok(L, tok) # skip "or" var b = parseAndExpr(L, tok, config) result = result or b proc evalppIf(L: var TLexer, tok: var TToken; config: ConfigRef): bool = ppGetTok(L, tok) # skip 'if' or 'elif' result = parseExpr(L, tok, config) if tok.tokType == tkColon: ppGetTok(L, tok) else: lexMessage(L, errGenerated, "expected ':'") #var condStack: seq[bool] = @[] proc doEnd(L: var TLexer, tok: var TToken; condStack: var seq[bool]) = if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if") ppGetTok(L, tok) # skip 'end' setLen(condStack, high(condStack)) type TJumpDest = enum jdEndif, jdElseEndif proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: ConfigRef; condStack: var seq[bool]) proc doElse(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) = if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if") ppGetTok(L, tok) if tok.tokType == tkColon: ppGetTok(L, tok) if condStack[high(condStack)]: jumpToDirective(L, tok, jdEndif, config, condStack) proc doElif(L: var TLexer, tok: var TToken; config: ConfigRef; condStack: var seq[bool]) = if high(condStack) < 0: lexMessage(L, errGenerated, "expected @if") var res = evalppIf(L, tok, config) if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif, config, condStack) else: condStack[high(condStack)] = true proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest; config: ConfigRef; condStack: var seq[bool]) = var nestedIfs = 0 while true: if tok.ident != nil and tok.ident.s == "@": ppGetTok(L, tok) case whichKeyword(tok.ident) of wIf: inc(nestedIfs) of wElse: if dest == jdElseEndif and nestedIfs == 0: doElse(L, tok, config, condStack) break of wElif: if dest == jdElseEndif and nestedIfs == 0: doElif(L, tok, config, condStack) break of wEnd: if nestedIfs == 0: doEnd(L, tok, condStack) break if nestedIfs > 0: dec(nestedIfs) else: discard ppGetTok(L, tok) elif tok.tokType == tkEof: lexMessag
#
#
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# Headers for procs that the code generator depends on ("compilerprocs")
type
LibHandle = pointer # private type