improvements for NimScript support

This commit is contained in:
Araq 2015-09-03 14:11:33 +02:00
commit a373bdd0c9
3 changed files with 62 additions and 59 deletions

View file

@ -9,106 +9,106 @@
# This module handles the reading of the config file. # This module handles the reading of the config file.
import import
llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer, llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
options, idents, wordrecg, strtabs options, idents, wordrecg, strtabs
# ---------------- configuration file parser ----------------------------- # ---------------- configuration file parser -----------------------------
# we use Nim's scanner here to save space and work # we use Nim's scanner here to save space and work
proc ppGetTok(L: var TLexer, tok: var TToken) = proc ppGetTok(L: var TLexer, tok: var TToken) =
# simple filter # simple filter
rawGetTok(L, tok) rawGetTok(L, tok)
while tok.tokType in {tkComment}: rawGetTok(L, tok) while tok.tokType in {tkComment}: rawGetTok(L, tok)
proc parseExpr(L: var TLexer, tok: var TToken): bool proc parseExpr(L: var TLexer, tok: var TToken): bool
proc parseAtom(L: var TLexer, tok: var TToken): bool = proc parseAtom(L: var TLexer, tok: var TToken): bool =
if tok.tokType == tkParLe: if tok.tokType == tkParLe:
ppGetTok(L, tok) ppGetTok(L, tok)
result = parseExpr(L, tok) result = parseExpr(L, tok)
if tok.tokType == tkParRi: ppGetTok(L, tok) if tok.tokType == tkParRi: ppGetTok(L, tok)
else: lexMessage(L, errTokenExpected, "\')\'") else: lexMessage(L, errTokenExpected, "\')\'")
elif tok.ident.id == ord(wNot): elif tok.ident.id == ord(wNot):
ppGetTok(L, tok) ppGetTok(L, tok)
result = not parseAtom(L, tok) result = not parseAtom(L, tok)
else: else:
result = isDefined(tok.ident) result = isDefined(tok.ident)
ppGetTok(L, tok) ppGetTok(L, tok)
proc parseAndExpr(L: var TLexer, tok: var TToken): bool = proc parseAndExpr(L: var TLexer, tok: var TToken): bool =
result = parseAtom(L, tok) result = parseAtom(L, tok)
while tok.ident.id == ord(wAnd): while tok.ident.id == ord(wAnd):
ppGetTok(L, tok) # skip "and" ppGetTok(L, tok) # skip "and"
var b = parseAtom(L, tok) var b = parseAtom(L, tok)
result = result and b result = result and b
proc parseExpr(L: var TLexer, tok: var TToken): bool = proc parseExpr(L: var TLexer, tok: var TToken): bool =
result = parseAndExpr(L, tok) result = parseAndExpr(L, tok)
while tok.ident.id == ord(wOr): while tok.ident.id == ord(wOr):
ppGetTok(L, tok) # skip "or" ppGetTok(L, tok) # skip "or"
var b = parseAndExpr(L, tok) var b = parseAndExpr(L, tok)
result = result or b result = result or b
proc evalppIf(L: var TLexer, tok: var TToken): bool = proc evalppIf(L: var TLexer, tok: var TToken): bool =
ppGetTok(L, tok) # skip 'if' or 'elif' ppGetTok(L, tok) # skip 'if' or 'elif'
result = parseExpr(L, tok) result = parseExpr(L, tok)
if tok.tokType == tkColon: ppGetTok(L, tok) if tok.tokType == tkColon: ppGetTok(L, tok)
else: lexMessage(L, errTokenExpected, "\':\'") else: lexMessage(L, errTokenExpected, "\':\'")
var condStack: seq[bool] = @[] var condStack: seq[bool] = @[]
proc doEnd(L: var TLexer, tok: var TToken) = proc doEnd(L: var TLexer, tok: var TToken) =
if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if") if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if")
ppGetTok(L, tok) # skip 'end' ppGetTok(L, tok) # skip 'end'
setLen(condStack, high(condStack)) setLen(condStack, high(condStack))
type type
TJumpDest = enum TJumpDest = enum
jdEndif, jdElseEndif jdEndif, jdElseEndif
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest)
proc doElse(L: var TLexer, tok: var TToken) = proc doElse(L: var TLexer, tok: var TToken) =
if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if") if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if")
ppGetTok(L, tok) ppGetTok(L, tok)
if tok.tokType == tkColon: ppGetTok(L, tok) if tok.tokType == tkColon: ppGetTok(L, tok)
if condStack[high(condStack)]: jumpToDirective(L, tok, jdEndif) if condStack[high(condStack)]: jumpToDirective(L, tok, jdEndif)
proc doElif(L: var TLexer, tok: var TToken) = proc doElif(L: var TLexer, tok: var TToken) =
if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if") if high(condStack) < 0: lexMessage(L, errTokenExpected, "@if")
var res = evalppIf(L, tok) var res = evalppIf(L, tok)
if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif) if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif)
else: condStack[high(condStack)] = true else: condStack[high(condStack)] = true
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) = proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest) =
var nestedIfs = 0 var nestedIfs = 0
while true: while true:
if tok.ident != nil and tok.ident.s == "@": if tok.ident != nil and tok.ident.s == "@":
ppGetTok(L, tok) ppGetTok(L, tok)
case whichKeyword(tok.ident) case whichKeyword(tok.ident)
of wIf: of wIf:
inc(nestedIfs) inc(nestedIfs)
of wElse: of wElse:
if dest == jdElseEndif and nestedIfs == 0: if dest == jdElseEndif and nestedIfs == 0:
doElse(L, tok) doElse(L, tok)
break break
of wElif: of wElif:
if dest == jdElseEndif and nestedIfs == 0: if dest == jdElseEndif and nestedIfs == 0:
doElif(L, tok) doElif(L, tok)
break break
of wEnd: of wEnd:
if nestedIfs == 0: if nestedIfs == 0:
doEnd(L, tok) doEnd(L, tok)
break break
if nestedIfs > 0: dec(nestedIfs) if nestedIfs > 0: dec(nestedIfs)
else: else:
discard discard
ppGetTok(L, tok) ppGetTok(L, tok)
elif tok.tokType == tkEof: elif tok.tokType == tkEof:
lexMessage(L, errTokenExpected, "@end") lexMessage(L, errTokenExpected, "@end")
else: else:
ppGetTok(L, tok) ppGetTok(L, tok)
proc parseDirective(L: var TLexer, tok: var TToken) = proc parseDirective(L: var TLexer, tok: var TToken) =
ppGetTok(L, tok) # skip @ ppGetTok(L, tok) # skip @
case whichKeyword(tok.ident) case whichKeyword(tok.ident)
of wIf: of wIf:
@ -126,13 +126,13 @@ proc parseDirective(L: var TLexer, tok: var TToken) =
ppGetTok(L, tok) ppGetTok(L, tok)
else: else:
case tok.ident.s.normalize case tok.ident.s.normalize
of "putenv": of "putenv":
ppGetTok(L, tok) ppGetTok(L, tok)
var key = tokToStr(tok) var key = tokToStr(tok)
ppGetTok(L, tok) ppGetTok(L, tok)
os.putEnv(key, tokToStr(tok)) os.putEnv(key, tokToStr(tok))
ppGetTok(L, tok) ppGetTok(L, tok)
of "prependenv": of "prependenv":
ppGetTok(L, tok) ppGetTok(L, tok)
var key = tokToStr(tok) var key = tokToStr(tok)
ppGetTok(L, tok) ppGetTok(L, tok)
@ -145,17 +145,17 @@ proc parseDirective(L: var TLexer, tok: var TToken) =
os.putEnv(key, os.getEnv(key) & tokToStr(tok)) os.putEnv(key, os.getEnv(key) & tokToStr(tok))
ppGetTok(L, tok) ppGetTok(L, tok)
else: lexMessage(L, errInvalidDirectiveX, tokToStr(tok)) else: lexMessage(L, errInvalidDirectiveX, tokToStr(tok))
proc confTok(L: var TLexer, tok: var TToken) = proc confTok(L: var TLexer, tok: var TToken) =
ppGetTok(L, tok) ppGetTok(L, tok)
while tok.ident != nil and tok.ident.s == "@": while tok.ident != nil and tok.ident.s == "@":
parseDirective(L, tok) # else: give the token to the parser parseDirective(L, tok) # else: give the token to the parser
proc checkSymbol(L: TLexer, tok: TToken) = proc checkSymbol(L: TLexer, tok: TToken) =
if tok.tokType notin {tkSymbol..pred(tkIntLit), tkStrLit..tkTripleStrLit}: if tok.tokType notin {tkSymbol..pred(tkIntLit), tkStrLit..tkTripleStrLit}:
lexMessage(L, errIdentifierExpected, tokToStr(tok)) lexMessage(L, errIdentifierExpected, tokToStr(tok))
proc parseAssignment(L: var TLexer, tok: var TToken) = proc parseAssignment(L: var TLexer, tok: var TToken) =
if tok.ident.id == getIdent("-").id or tok.ident.id == getIdent("--").id: if tok.ident.id == getIdent("-").id or tok.ident.id == getIdent("--").id:
confTok(L, tok) # skip unnecessary prefix confTok(L, tok) # skip unnecessary prefix
var info = getLineInfo(L, tok) # save for later in case of an error var info = getLineInfo(L, tok) # save for later in case of an error
@ -163,13 +163,13 @@ proc parseAssignment(L: var TLexer, tok: var TToken) =
var s = tokToStr(tok) var s = tokToStr(tok)
confTok(L, tok) # skip symbol confTok(L, tok) # skip symbol
var val = "" var val = ""
while tok.tokType == tkDot: while tok.tokType == tkDot:
add(s, '.') add(s, '.')
confTok(L, tok) confTok(L, tok)
checkSymbol(L, tok) checkSymbol(L, tok)
add(s, tokToStr(tok)) add(s, tokToStr(tok))
confTok(L, tok) confTok(L, tok)
if tok.tokType == tkBracketLe: if tok.tokType == tkBracketLe:
# BUGFIX: val, not s! # BUGFIX: val, not s!
# BUGFIX: do not copy '['! # BUGFIX: do not copy '['!
confTok(L, tok) confTok(L, tok)
@ -180,7 +180,7 @@ proc parseAssignment(L: var TLexer, tok: var TToken) =
else: lexMessage(L, errTokenExpected, "']'") else: lexMessage(L, errTokenExpected, "']'")
add(val, ']') add(val, ']')
let percent = tok.ident.id == getIdent("%=").id let percent = tok.ident.id == getIdent("%=").id
if tok.tokType in {tkColon, tkEquals} or percent: if tok.tokType in {tkColon, tkEquals} or percent:
if len(val) > 0: add(val, ':') if len(val) > 0: add(val, ':')
confTok(L, tok) # skip ':' or '=' or '%' confTok(L, tok) # skip ':' or '=' or '%'
checkSymbol(L, tok) checkSymbol(L, tok)
@ -226,15 +226,7 @@ proc getSystemConfigPath(filename: string): string =
if not existsFile(result): result = "/etc/" & filename if not existsFile(result): result = "/etc/" & filename
proc loadConfigs*(cfg: string) = proc loadConfigs*(cfg: string) =
# set default value (can be overwritten): setDefaultLibpath()
if libpath == "":
# choose default libpath:
var prefix = getPrefixDir()
when defined(posix):
if prefix == "/usr": libpath = "/usr/lib/nim"
elif prefix == "/usr/local": libpath = "/usr/local/lib/nim"
else: libpath = joinPath(prefix, "lib")
else: libpath = joinPath(prefix, "lib")
if optSkipConfigFile notin gGlobalOptions: if optSkipConfigFile notin gGlobalOptions:
readConfigFile(getSystemConfigPath(cfg)) readConfigFile(getSystemConfigPath(cfg))
@ -246,10 +238,10 @@ proc loadConfigs*(cfg: string) =
if optSkipParentConfigFiles notin gGlobalOptions: if optSkipParentConfigFiles notin gGlobalOptions:
for dir in parentDirs(pd, fromRoot=true, inclusive=false): for dir in parentDirs(pd, fromRoot=true, inclusive=false):
readConfigFile(dir / cfg) readConfigFile(dir / cfg)
if optSkipProjConfigFile notin gGlobalOptions: if optSkipProjConfigFile notin gGlobalOptions:
readConfigFile(pd / cfg) readConfigFile(pd / cfg)
if gProjectName.len != 0: if gProjectName.len != 0:
# new project wide config file: # new project wide config file:
var projectConfig = changeFileExt(gProjectFull, "nimcfg") var projectConfig = changeFileExt(gProjectFull, "nimcfg")

View file

@ -191,6 +191,17 @@ proc getPrefixDir*(): string =
else: else:
result = splitPath(getAppDir()).head result = splitPath(getAppDir()).head
proc setDefaultLibpath*() =
# set default value (can be overwritten):
if libpath == "":
# choose default libpath:
var prefix = getPrefixDir()
when defined(posix):
if prefix == "/usr": libpath = "/usr/lib/nim"
elif prefix == "/usr/local": libpath = "/usr/local/lib/nim"
else: libpath = joinPath(prefix, "lib")
else: libpath = joinPath(prefix, "lib")
proc canonicalizePath*(path: string): string = proc canonicalizePath*(path: string): string =
when not FileSystemCaseSensitive: result = path.expandFilename.toLower when not FileSystemCaseSensitive: result = path.expandFilename.toLower
else: result = path.expandFilename else: result = path.expandFilename

View file

@ -157,8 +157,8 @@ var
binDir*, backend*: string binDir*, backend*: string
skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*, skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*,
installExt*, bin*: seq[string] installExt*, bin*: seq[string] = @[]
requiresData*: seq[string] requiresData*: seq[string] = @[]
proc requires*(deps: varargs[string]) = proc requires*(deps: varargs[string]) =
for d in deps: requiresData.add(d) for d in deps: requiresData.add(d)