improvements for NimScript support
This commit is contained in:
parent
e90c155260
commit
a373bdd0c9
3 changed files with 62 additions and 59 deletions
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue