improvements for NimScript support

This commit is contained in:
Araq
2015-09-03 14:11:33 +02:00
parent e90c155260
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.
import
llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
import
llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
options, idents, wordrecg, strtabs
# ---------------- configuration file parser -----------------------------
# 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
rawGetTok(L, tok)
while tok.tokType in {tkComment}: rawGetTok(L, tok)
proc parseExpr(L: var TLexer, tok: var TToken): bool
proc parseAtom(L: var TLexer, tok: var TToken): bool =
if tok.tokType == tkParLe:
proc parseAtom(L: var TLexer, tok: var TToken): bool =
if tok.tokType == tkParLe:
ppGetTok(L, tok)
result = parseExpr(L, tok)
if tok.tokType == tkParRi: ppGetTok(L, tok)
else: lexMessage(L, errTokenExpected, "\')\'")
elif tok.ident.id == ord(wNot):
elif tok.ident.id == ord(wNot):
ppGetTok(L, tok)
result = not parseAtom(L, tok)
else:
result = isDefined(tok.ident)
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)
while tok.ident.id == ord(wAnd):
while tok.ident.id == ord(wAnd):
ppGetTok(L, tok) # skip "and"
var b = parseAtom(L, tok)
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)
while tok.ident.id == ord(wOr):
while tok.ident.id == ord(wOr):
ppGetTok(L, tok) # skip "or"
var b = parseAndExpr(L, tok)
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'
result = parseExpr(L, tok)
if tok.tokType == tkColon: ppGetTok(L, tok)
else: lexMessage(L, errTokenExpected, "\':\'")
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")
ppGetTok(L, tok) # skip 'end'
setLen(condStack, high(condStack))
type
TJumpDest = enum
type
TJumpDest = enum
jdEndif, jdElseEndif
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")
ppGetTok(L, tok)
if tok.tokType == tkColon: ppGetTok(L, tok)
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")
var res = evalppIf(L, tok)
if condStack[high(condStack)] or not res: jumpToDirective(L, tok, jdElseEndif)
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
while true:
while true:
if tok.ident != nil and tok.ident.s == "@":
ppGetTok(L, tok)
case whichKeyword(tok.ident)
of wIf:
of wIf:
inc(nestedIfs)
of wElse:
of wElse:
if dest == jdElseEndif and nestedIfs == 0:
doElse(L, tok)
break
of wElif:
break
of wElif:
if dest == jdElseEndif and nestedIfs == 0:
doElif(L, tok)
break
of wEnd:
if nestedIfs == 0:
break
of wEnd:
if nestedIfs == 0:
doEnd(L, tok)
break
break
if nestedIfs > 0: dec(nestedIfs)
else:
else:
discard
ppGetTok(L, tok)
elif tok.tokType == tkEof:
lexMessage(L, errTokenExpected, "@end")
else:
ppGetTok(L, tok)
proc parseDirective(L: var TLexer, tok: var TToken) =
proc parseDirective(L: var TLexer, tok: var TToken) =
ppGetTok(L, tok) # skip @
case whichKeyword(tok.ident)
of wIf:
@@ -126,13 +126,13 @@ proc parseDirective(L: var TLexer, tok: var TToken) =
ppGetTok(L, tok)
else:
case tok.ident.s.normalize
of "putenv":
of "putenv":
ppGetTok(L, tok)
var key = tokToStr(tok)
ppGetTok(L, tok)
os.putEnv(key, tokToStr(tok))
ppGetTok(L, tok)
of "prependenv":
of "prependenv":
ppGetTok(L, tok)
var key = tokToStr(tok)
ppGetTok(L, tok)
@@ -145,17 +145,17 @@ proc parseDirective(L: var TLexer, tok: var TToken) =
os.putEnv(key, os.getEnv(key) & tokToStr(tok))
ppGetTok(L, 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)
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
proc checkSymbol(L: TLexer, tok: TToken) =
if tok.tokType notin {tkSymbol..pred(tkIntLit), tkStrLit..tkTripleStrLit}:
proc checkSymbol(L: TLexer, tok: TToken) =
if tok.tokType notin {tkSymbol..pred(tkIntLit), tkStrLit..tkTripleStrLit}:
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:
confTok(L, tok) # skip unnecessary prefix
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)
confTok(L, tok) # skip symbol
var val = ""
while tok.tokType == tkDot:
while tok.tokType == tkDot:
add(s, '.')
confTok(L, tok)
checkSymbol(L, tok)
add(s, tokToStr(tok))
confTok(L, tok)
if tok.tokType == tkBracketLe:
if tok.tokType == tkBracketLe:
# BUGFIX: val, not s!
# BUGFIX: do not copy '['!
confTok(L, tok)
@@ -180,7 +180,7 @@ proc parseAssignment(L: var TLexer, tok: var TToken) =
else: lexMessage(L, errTokenExpected, "']'")
add(val, ']')
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, ':')
confTok(L, tok) # skip ':' or '=' or '%'
checkSymbol(L, tok)
@@ -226,15 +226,7 @@ proc getSystemConfigPath(filename: string): string =
if not existsFile(result): result = "/etc/" & filename
proc loadConfigs*(cfg: string) =
# 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")
setDefaultLibpath()
if optSkipConfigFile notin gGlobalOptions:
readConfigFile(getSystemConfigPath(cfg))
@@ -246,10 +238,10 @@ proc loadConfigs*(cfg: string) =
if optSkipParentConfigFiles notin gGlobalOptions:
for dir in parentDirs(pd, fromRoot=true, inclusive=false):
readConfigFile(dir / cfg)
if optSkipProjConfigFile notin gGlobalOptions:
readConfigFile(pd / cfg)
if gProjectName.len != 0:
# new project wide config file:
var projectConfig = changeFileExt(gProjectFull, "nimcfg")

View File

@@ -191,6 +191,17 @@ proc getPrefixDir*(): string =
else:
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 =
when not FileSystemCaseSensitive: result = path.expandFilename.toLower
else: result = path.expandFilename

View File

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