lexer, parser cleanup; boehm gc for mac os x
This commit is contained in:
parent
aeb0506132
commit
9207492bb9
6 changed files with 104 additions and 100 deletions
|
|
@ -83,7 +83,6 @@ type
|
||||||
base10, # base10 is listed as the first element,
|
base10, # base10 is listed as the first element,
|
||||||
# so that it is the correct default value
|
# so that it is the correct default value
|
||||||
base2, base8, base16
|
base2, base8, base16
|
||||||
PToken* = ref TToken
|
|
||||||
TToken* = object # a Nimrod token
|
TToken* = object # a Nimrod token
|
||||||
tokType*: TTokType # the type of the token
|
tokType*: TTokType # the type of the token
|
||||||
indent*: int # the indentation; only valid if tokType = tkIndent
|
indent*: int # the indentation; only valid if tokType = tkIndent
|
||||||
|
|
@ -94,9 +93,7 @@ type
|
||||||
# or float literals
|
# or float literals
|
||||||
literal*: string # the parsed (string) literal; and
|
literal*: string # the parsed (string) literal; and
|
||||||
# documentation comments are here too
|
# documentation comments are here too
|
||||||
next*: PToken # next token; can be used for arbitrary look-ahead
|
|
||||||
|
|
||||||
PLexer* = ref TLexer
|
|
||||||
TLexer* = object of TBaseLexer
|
TLexer* = object of TBaseLexer
|
||||||
filename*: string
|
filename*: string
|
||||||
indentStack*: seq[int] # the indentation stack
|
indentStack*: seq[int] # the indentation stack
|
||||||
|
|
@ -118,13 +115,10 @@ proc rawGetTok*(L: var TLexer, tok: var TToken)
|
||||||
proc getColumn*(L: TLexer): int
|
proc getColumn*(L: TLexer): int
|
||||||
proc getLineInfo*(L: TLexer): TLineInfo
|
proc getLineInfo*(L: TLexer): TLineInfo
|
||||||
proc closeLexer*(lex: var TLexer)
|
proc closeLexer*(lex: var TLexer)
|
||||||
proc PrintTok*(tok: PToken)
|
proc PrintTok*(tok: TToken)
|
||||||
proc tokToStr*(tok: PToken): string
|
proc tokToStr*(tok: TToken): string
|
||||||
|
|
||||||
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "")
|
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "")
|
||||||
# the Pascal scanner uses this too:
|
|
||||||
proc fillToken*(L: var TToken)
|
|
||||||
# implementation
|
|
||||||
|
|
||||||
proc isKeyword(kind: TTokType): bool =
|
proc isKeyword(kind: TTokType): bool =
|
||||||
result = (kind >= tokKeywordLow) and (kind <= tokKeywordHigh)
|
result = (kind >= tokKeywordLow) and (kind <= tokKeywordHigh)
|
||||||
|
|
@ -157,7 +151,7 @@ proc findIdent(L: TLexer, indent: int): bool =
|
||||||
if L.indentStack[i] == indent:
|
if L.indentStack[i] == indent:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
proc tokToStr(tok: PToken): string =
|
proc tokToStr*(tok: TToken): string =
|
||||||
case tok.tokType
|
case tok.tokType
|
||||||
of tkIntLit..tkInt64Lit: result = $tok.iNumber
|
of tkIntLit..tkInt64Lit: result = $tok.iNumber
|
||||||
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
|
of tkFloatLit..tkFloat64Lit: result = $tok.fNumber
|
||||||
|
|
@ -171,21 +165,30 @@ proc tokToStr(tok: PToken): string =
|
||||||
InternalError("tokToStr")
|
InternalError("tokToStr")
|
||||||
result = ""
|
result = ""
|
||||||
|
|
||||||
proc PrintTok(tok: PToken) =
|
proc PrintTok*(tok: TToken) =
|
||||||
write(stdout, TokTypeToStr[tok.tokType])
|
write(stdout, TokTypeToStr[tok.tokType])
|
||||||
write(stdout, " ")
|
write(stdout, " ")
|
||||||
writeln(stdout, tokToStr(tok))
|
writeln(stdout, tokToStr(tok))
|
||||||
|
|
||||||
var dummyIdent: PIdent
|
var dummyIdent: PIdent
|
||||||
|
|
||||||
proc fillToken(L: var TToken) =
|
proc initToken*(L: var TToken) =
|
||||||
L.TokType = tkInvalid
|
L.TokType = tkInvalid
|
||||||
L.iNumber = 0
|
L.iNumber = 0
|
||||||
L.Indent = 0
|
L.Indent = 0
|
||||||
L.literal = ""
|
L.literal = ""
|
||||||
L.fNumber = 0.0
|
L.fNumber = 0.0
|
||||||
L.base = base10
|
L.base = base10
|
||||||
L.ident = dummyIdent # this prevents many bugs!
|
L.ident = dummyIdent
|
||||||
|
|
||||||
|
proc fillToken(L: var TToken) =
|
||||||
|
L.TokType = tkInvalid
|
||||||
|
L.iNumber = 0
|
||||||
|
L.Indent = 0
|
||||||
|
setLen(L.literal, 0)
|
||||||
|
L.fNumber = 0.0
|
||||||
|
L.base = base10
|
||||||
|
L.ident = dummyIdent
|
||||||
|
|
||||||
proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) =
|
proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) =
|
||||||
openBaseLexer(lex, inputstream)
|
openBaseLexer(lex, inputstream)
|
||||||
|
|
|
||||||
|
|
@ -165,11 +165,11 @@ proc CommandScan(filename: string) =
|
||||||
if stream != nil:
|
if stream != nil:
|
||||||
var
|
var
|
||||||
L: TLexer
|
L: TLexer
|
||||||
tok: PToken
|
tok: TToken
|
||||||
new(tok)
|
initToken(tok)
|
||||||
openLexer(L, f, stream)
|
openLexer(L, f, stream)
|
||||||
while true:
|
while true:
|
||||||
rawGetTok(L, tok[])
|
rawGetTok(L, tok)
|
||||||
PrintTok(tok)
|
PrintTok(tok)
|
||||||
if tok.tokType == tkEof: break
|
if tok.tokType == tkEof: break
|
||||||
CloseLexer(L)
|
CloseLexer(L)
|
||||||
|
|
|
||||||
|
|
@ -16,13 +16,13 @@ import
|
||||||
# ---------------- configuration file parser -----------------------------
|
# ---------------- configuration file parser -----------------------------
|
||||||
# we use Nimrod's scanner here to safe space and work
|
# we use Nimrod's scanner here to safe space and work
|
||||||
|
|
||||||
proc ppGetTok(L: var TLexer, tok: PToken) =
|
proc ppGetTok(L: var TLexer, tok: var TToken) =
|
||||||
# simple filter
|
# simple filter
|
||||||
rawGetTok(L, tok[])
|
rawGetTok(L, tok)
|
||||||
while tok.tokType in {tkInd, tkSad, tkDed, tkComment}: rawGetTok(L, tok[])
|
while tok.tokType in {tkInd, tkSad, tkDed, tkComment}: rawGetTok(L, tok)
|
||||||
|
|
||||||
proc parseExpr(L: var TLexer, tok: PToken): bool
|
proc parseExpr(L: var TLexer, tok: var TToken): bool
|
||||||
proc parseAtom(L: var TLexer, tok: PToken): 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)
|
||||||
|
|
@ -35,21 +35,21 @@ proc parseAtom(L: var TLexer, tok: PToken): bool =
|
||||||
result = isDefined(tok.ident)
|
result = isDefined(tok.ident)
|
||||||
ppGetTok(L, tok)
|
ppGetTok(L, tok)
|
||||||
|
|
||||||
proc parseAndExpr(L: var TLexer, tok: PToken): 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: PToken): 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: PToken): 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)
|
||||||
|
|
@ -57,7 +57,7 @@ proc EvalppIf(L: var TLexer, tok: PToken): bool =
|
||||||
|
|
||||||
var condStack: seq[bool] = @[]
|
var condStack: seq[bool] = @[]
|
||||||
|
|
||||||
proc doEnd(L: var TLexer, tok: PToken) =
|
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))
|
||||||
|
|
@ -66,20 +66,20 @@ type
|
||||||
TJumpDest = enum
|
TJumpDest = enum
|
||||||
jdEndif, jdElseEndif
|
jdEndif, jdElseEndif
|
||||||
|
|
||||||
proc jumpToDirective(L: var TLexer, tok: PToken, dest: TJumpDest)
|
proc jumpToDirective(L: var TLexer, tok: var TToken, dest: TJumpDest)
|
||||||
proc doElse(L: var TLexer, tok: PToken) =
|
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: PToken) =
|
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: PToken, 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 == "@"):
|
||||||
|
|
@ -108,7 +108,7 @@ proc jumpToDirective(L: var TLexer, tok: PToken, dest: TJumpDest) =
|
||||||
else:
|
else:
|
||||||
ppGetTok(L, tok)
|
ppGetTok(L, tok)
|
||||||
|
|
||||||
proc parseDirective(L: var TLexer, tok: PToken) =
|
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:
|
||||||
|
|
@ -143,16 +143,16 @@ proc parseDirective(L: var TLexer, tok: PToken) =
|
||||||
ppGetTok(L, tok)
|
ppGetTok(L, tok)
|
||||||
else: lexMessage(L, errInvalidDirectiveX, tokToStr(tok))
|
else: lexMessage(L, errInvalidDirectiveX, tokToStr(tok))
|
||||||
|
|
||||||
proc confTok(L: var TLexer, tok: PToken) =
|
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: PToken) =
|
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: PToken) =
|
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) # safe for later in case of an error
|
var info = getLineInfo(L) # safe for later in case of an error
|
||||||
|
|
@ -192,9 +192,9 @@ proc parseAssignment(L: var TLexer, tok: PToken) =
|
||||||
proc readConfigFile(filename: string) =
|
proc readConfigFile(filename: string) =
|
||||||
var
|
var
|
||||||
L: TLexer
|
L: TLexer
|
||||||
tok: PToken
|
tok: TToken
|
||||||
stream: PLLStream
|
stream: PLLStream
|
||||||
new(tok)
|
initToken(tok)
|
||||||
stream = LLStreamOpen(filename, fmRead)
|
stream = LLStreamOpen(filename, fmRead)
|
||||||
if stream != nil:
|
if stream != nil:
|
||||||
openLexer(L, filename, stream)
|
openLexer(L, filename, stream)
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ import
|
||||||
type
|
type
|
||||||
TParser*{.final.} = object # a TParser object represents a module that
|
TParser*{.final.} = object # a TParser object represents a module that
|
||||||
# is being parsed
|
# is being parsed
|
||||||
lex*: PLexer # the lexer that is used for parsing
|
lex*: TLexer # the lexer that is used for parsing
|
||||||
tok*: PToken # the current token
|
tok*: TToken # the current token
|
||||||
|
|
||||||
|
|
||||||
proc ParseAll*(p: var TParser): PNode
|
proc ParseAll*(p: var TParser): PNode
|
||||||
|
|
@ -32,8 +32,8 @@ proc parseTopLevelStmt*(p: var TParser): PNode
|
||||||
# emtyNode if end of stream.
|
# emtyNode if end of stream.
|
||||||
|
|
||||||
# helpers for the other parsers
|
# helpers for the other parsers
|
||||||
proc getPrecedence*(tok: PToken): int
|
proc getPrecedence*(tok: TToken): int
|
||||||
proc isOperator*(tok: PToken): bool
|
proc isOperator*(tok: TToken): bool
|
||||||
proc getTok*(p: var TParser)
|
proc getTok*(p: var TParser)
|
||||||
proc parMessage*(p: TParser, msg: TMsgKind, arg: string = "")
|
proc parMessage*(p: TParser, msg: TMsgKind, arg: string = "")
|
||||||
proc skipComment*(p: var TParser, node: PNode)
|
proc skipComment*(p: var TParser, node: PNode)
|
||||||
|
|
@ -54,23 +54,22 @@ proc setBaseFlags*(n: PNode, base: TNumericalBase)
|
||||||
proc parseSymbol*(p: var TParser): PNode
|
proc parseSymbol*(p: var TParser): PNode
|
||||||
# implementation
|
# implementation
|
||||||
|
|
||||||
proc initParser(p: var TParser) =
|
|
||||||
new(p.lex)
|
|
||||||
new(p.tok)
|
|
||||||
|
|
||||||
proc getTok(p: var TParser) =
|
proc getTok(p: var TParser) =
|
||||||
rawGetTok(p.lex[], p.tok[])
|
rawGetTok(p.lex, p.tok)
|
||||||
|
|
||||||
proc OpenParser(p: var TParser, filename: string, inputStream: PLLStream) =
|
proc OpenParser(p: var TParser, filename: string, inputStream: PLLStream) =
|
||||||
initParser(p)
|
initToken(p.tok)
|
||||||
OpenLexer(p.lex[], filename, inputstream)
|
OpenLexer(p.lex, filename, inputstream)
|
||||||
getTok(p) # read the first token
|
getTok(p) # read the first token
|
||||||
|
|
||||||
proc CloseParser(p: var TParser) =
|
proc CloseParser(p: var TParser) =
|
||||||
CloseLexer(p.lex[])
|
CloseLexer(p.lex)
|
||||||
|
|
||||||
proc parMessage(p: TParser, msg: TMsgKind, arg: string = "") =
|
proc parMessage(p: TParser, msg: TMsgKind, arg: string = "") =
|
||||||
lexMessage(p.lex[], msg, arg)
|
lexMessage(p.lex, msg, arg)
|
||||||
|
|
||||||
|
proc parMessage(p: TParser, msg: TMsgKind, tok: TToken) =
|
||||||
|
lexMessage(p.lex, msg, tokToStr(tok))
|
||||||
|
|
||||||
proc skipComment(p: var TParser, node: PNode) =
|
proc skipComment(p: var TParser, node: PNode) =
|
||||||
if p.tok.tokType == tkComment:
|
if p.tok.tokType == tkComment:
|
||||||
|
|
@ -93,18 +92,18 @@ proc optInd(p: var TParser, n: PNode) =
|
||||||
|
|
||||||
proc expectIdentOrKeyw(p: TParser) =
|
proc expectIdentOrKeyw(p: TParser) =
|
||||||
if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType):
|
if p.tok.tokType != tkSymbol and not isKeyword(p.tok.tokType):
|
||||||
lexMessage(p.lex[], errIdentifierExpected, tokToStr(p.tok))
|
lexMessage(p.lex, errIdentifierExpected, tokToStr(p.tok))
|
||||||
|
|
||||||
proc ExpectIdent(p: TParser) =
|
proc ExpectIdent(p: TParser) =
|
||||||
if p.tok.tokType != tkSymbol:
|
if p.tok.tokType != tkSymbol:
|
||||||
lexMessage(p.lex[], errIdentifierExpected, tokToStr(p.tok))
|
lexMessage(p.lex, errIdentifierExpected, tokToStr(p.tok))
|
||||||
|
|
||||||
proc Eat(p: var TParser, TokType: TTokType) =
|
proc Eat(p: var TParser, TokType: TTokType) =
|
||||||
if p.tok.TokType == TokType: getTok(p)
|
if p.tok.TokType == TokType: getTok(p)
|
||||||
else: lexMessage(p.lex[], errTokenExpected, TokTypeToStr[tokType])
|
else: lexMessage(p.lex, errTokenExpected, TokTypeToStr[tokType])
|
||||||
|
|
||||||
proc parLineInfo(p: TParser): TLineInfo =
|
proc parLineInfo(p: TParser): TLineInfo =
|
||||||
result = getLineInfo(p.lex[])
|
result = getLineInfo(p.lex)
|
||||||
|
|
||||||
proc indAndComment(p: var TParser, n: PNode) =
|
proc indAndComment(p: var TParser, n: PNode) =
|
||||||
if p.tok.tokType == tkInd:
|
if p.tok.tokType == tkInd:
|
||||||
|
|
@ -116,7 +115,7 @@ proc indAndComment(p: var TParser, n: PNode) =
|
||||||
skipComment(p, n)
|
skipComment(p, n)
|
||||||
|
|
||||||
proc newNodeP(kind: TNodeKind, p: TParser): PNode =
|
proc newNodeP(kind: TNodeKind, p: TParser): PNode =
|
||||||
result = newNodeI(kind, getLineInfo(p.lex[]))
|
result = newNodeI(kind, getLineInfo(p.lex))
|
||||||
|
|
||||||
proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode =
|
proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode =
|
||||||
result = newNodeP(kind, p)
|
result = newNodeP(kind, p)
|
||||||
|
|
@ -140,10 +139,10 @@ proc parseStmt(p: var TParser): PNode
|
||||||
proc parseTypeDesc(p: var TParser): PNode
|
proc parseTypeDesc(p: var TParser): PNode
|
||||||
proc parseParamList(p: var TParser): PNode
|
proc parseParamList(p: var TParser): PNode
|
||||||
|
|
||||||
proc IsLeftAssociative(tok: PToken): bool {.inline.} =
|
proc IsLeftAssociative(tok: TToken): bool {.inline.} =
|
||||||
result = tok.tokType != tkOpr or tok.ident.s[0] != '^'
|
result = tok.tokType != tkOpr or tok.ident.s[0] != '^'
|
||||||
|
|
||||||
proc getPrecedence(tok: PToken): int =
|
proc getPrecedence(tok: TToken): int =
|
||||||
case tok.tokType
|
case tok.tokType
|
||||||
of tkOpr:
|
of tkOpr:
|
||||||
case tok.ident.s[0]
|
case tok.ident.s[0]
|
||||||
|
|
@ -161,7 +160,7 @@ proc getPrecedence(tok: PToken): int =
|
||||||
of tkOr, tkXor: result = 2
|
of tkOr, tkXor: result = 2
|
||||||
else: result = - 10
|
else: result = - 10
|
||||||
|
|
||||||
proc isOperator(tok: PToken): bool =
|
proc isOperator(tok: TToken): bool =
|
||||||
result = getPrecedence(tok) >= 0
|
result = getPrecedence(tok) >= 0
|
||||||
|
|
||||||
proc parseSymbol(p: var TParser): PNode =
|
proc parseSymbol(p: var TParser): PNode =
|
||||||
|
|
@ -192,11 +191,12 @@ proc parseSymbol(p: var TParser): PNode =
|
||||||
add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p))
|
add(result, newIdentNodeP(getIdent(tokToStr(p.tok)), p))
|
||||||
getTok(p)
|
getTok(p)
|
||||||
else:
|
else:
|
||||||
if result.len == 0: parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
if result.len == 0:
|
||||||
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
eat(p, tkAccent)
|
eat(p, tkAccent)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
|
|
||||||
proc indexExpr(p: var TParser): PNode =
|
proc indexExpr(p: var TParser): PNode =
|
||||||
|
|
@ -228,8 +228,7 @@ proc exprColonEqExpr(p: var TParser, kind: TNodeKind, tok: TTokType): PNode =
|
||||||
else:
|
else:
|
||||||
result = a
|
result = a
|
||||||
|
|
||||||
proc exprList(p: var TParser, endTok: TTokType,
|
proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
|
||||||
result: PNode) =
|
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
while (p.tok.tokType != endTok) and (p.tok.tokType != tkEof):
|
||||||
|
|
@ -414,7 +413,7 @@ proc identOrLiteral(p: var TParser): PNode =
|
||||||
of tkAddr:
|
of tkAddr:
|
||||||
result = parseAddr(p)
|
result = parseAddr(p)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errExprExpected, tokToStr(p.tok))
|
parMessage(p, errExprExpected, p.tok)
|
||||||
getTok(p) # we must consume a token here to prevend endless loops!
|
getTok(p) # we must consume a token here to prevend endless loops!
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
|
|
||||||
|
|
@ -459,28 +458,25 @@ proc primary(p: var TParser): PNode =
|
||||||
result = indexExprList(p, result)
|
result = indexExprList(p, result)
|
||||||
else: break
|
else: break
|
||||||
|
|
||||||
proc lowestExprAux(p: var TParser, v: var PNode, limit: int): PToken =
|
proc lowestExprAux(p: var TParser, limit: int): PNode =
|
||||||
v = primary(p) # expand while operators have priorities higher than 'limit'
|
result = primary(p)
|
||||||
var op = p.tok
|
# expand while operators have priorities higher than 'limit'
|
||||||
var opPrec = getPrecedence(op)
|
var opPrec = getPrecedence(p.tok)
|
||||||
while opPrec >= limit:
|
while opPrec >= limit:
|
||||||
var leftAssoc = ord(IsLeftAssociative(op))
|
var leftAssoc = ord(IsLeftAssociative(p.tok))
|
||||||
var node = newNodeP(nkInfix, p)
|
var a = newNodeP(nkInfix, p)
|
||||||
var opNode = newIdentNodeP(op.ident, p) # skip operator:
|
var opNode = newIdentNodeP(p.tok.ident, p) # skip operator:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, opNode) # read sub-expression with higher priority
|
optInd(p, opNode) # read sub-expression with higher priority
|
||||||
var v2: PNode
|
var b = lowestExprAux(p, opPrec + leftAssoc)
|
||||||
var nextop = lowestExprAux(p, v2, opPrec + leftAssoc)
|
addSon(a, opNode)
|
||||||
addSon(node, opNode)
|
addSon(a, result)
|
||||||
addSon(node, v)
|
addSon(a, b)
|
||||||
addSon(node, v2)
|
result = a
|
||||||
v = node
|
opPrec = getPrecedence(p.tok)
|
||||||
op = nextop
|
|
||||||
opPrec = getPrecedence(nextop)
|
|
||||||
result = op # return first untreated operator
|
|
||||||
|
|
||||||
proc lowestExpr(p: var TParser): PNode =
|
proc lowestExpr(p: var TParser): PNode =
|
||||||
discard lowestExprAux(p, result, - 1)
|
result = lowestExprAux(p, -1)
|
||||||
|
|
||||||
proc parseIfExpr(p: var TParser): PNode =
|
proc parseIfExpr(p: var TParser): PNode =
|
||||||
result = newNodeP(nkIfExpr, p)
|
result = newNodeP(nkIfExpr, p)
|
||||||
|
|
@ -510,7 +506,7 @@ proc parsePragma(p: var TParser): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, a)
|
optInd(p, a)
|
||||||
optPar(p)
|
optPar(p)
|
||||||
if (p.tok.tokType == tkCurlyDotRi) or (p.tok.tokType == tkCurlyRi): getTok(p)
|
if p.tok.tokType in {tkCurlyDotRi, tkCurlyRi}: getTok(p)
|
||||||
else: parMessage(p, errTokenExpected, ".}")
|
else: parMessage(p, errTokenExpected, ".}")
|
||||||
|
|
||||||
proc identVis(p: var TParser): PNode =
|
proc identVis(p: var TParser): PNode =
|
||||||
|
|
@ -560,7 +556,7 @@ proc parseIdentColonEquals(p: var TParser, flags: TDeclaredIdentFlags): PNode =
|
||||||
else:
|
else:
|
||||||
addSon(result, ast.emptyNode)
|
addSon(result, ast.emptyNode)
|
||||||
if (p.tok.tokType != tkEquals) and not (withBothOptional in flags):
|
if (p.tok.tokType != tkEquals) and not (withBothOptional in flags):
|
||||||
parMessage(p, errColonOrEqualsExpected, tokToStr(p.tok))
|
parMessage(p, errColonOrEqualsExpected, p.tok)
|
||||||
if p.tok.tokType == tkEquals:
|
if p.tok.tokType == tkEquals:
|
||||||
getTok(p)
|
getTok(p)
|
||||||
optInd(p, result)
|
optInd(p, result)
|
||||||
|
|
@ -751,7 +747,7 @@ proc parseImportOrIncludeStmt(p: var TParser, kind: TNodeKind): PNode =
|
||||||
a = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
|
a = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
|
|
@ -776,7 +772,7 @@ proc parseFromStmt(p: var TParser): PNode =
|
||||||
a = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
|
a = newStrNodeP(nkTripleStrLit, p.tok.literal, p)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
return
|
return
|
||||||
addSon(result, a) #optInd(p, a);
|
addSon(result, a) #optInd(p, a);
|
||||||
eat(p, tkImport)
|
eat(p, tkImport)
|
||||||
|
|
@ -788,7 +784,7 @@ proc parseFromStmt(p: var TParser): PNode =
|
||||||
of tkSymbol, tkAccent:
|
of tkSymbol, tkAccent:
|
||||||
a = parseSymbol(p)
|
a = parseSymbol(p)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
if p.tok.tokType != tkComma: break
|
if p.tok.tokType != tkComma: break
|
||||||
|
|
@ -1060,7 +1056,7 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkInd:
|
of tkInd:
|
||||||
pushInd(p.lex[], p.tok.indent)
|
pushInd(p.lex, p.tok.indent)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -1081,13 +1077,13 @@ proc parseSection(p: var TParser, kind: TNodeKind,
|
||||||
skipComment(p, a)
|
skipComment(p, a)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
popInd(p.lex[])
|
popInd(p.lex)
|
||||||
of tkSymbol, tkAccent, tkParLe:
|
of tkSymbol, tkAccent, tkParLe:
|
||||||
# tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
|
# tkParLe is allowed for ``var (x, y) = ...`` tuple parsing
|
||||||
addSon(result, defparser(p))
|
addSon(result, defparser(p))
|
||||||
else: parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
else: parMessage(p, errIdentifierExpected, p.tok)
|
||||||
|
|
||||||
proc parseConstant(p: var TParser): PNode =
|
proc parseConstant(p: var TParser): PNode =
|
||||||
result = newNodeP(nkConstDef, p)
|
result = newNodeP(nkConstDef, p)
|
||||||
|
|
@ -1188,7 +1184,7 @@ proc parseObjectPart(p: var TParser): PNode =
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkInd:
|
of tkInd:
|
||||||
result = newNodeP(nkRecList, p)
|
result = newNodeP(nkRecList, p)
|
||||||
pushInd(p.lex[], p.tok.indent)
|
pushInd(p.lex, p.tok.indent)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
skipComment(p, result)
|
skipComment(p, result)
|
||||||
while true:
|
while true:
|
||||||
|
|
@ -1203,9 +1199,9 @@ proc parseObjectPart(p: var TParser): PNode =
|
||||||
of tkEof:
|
of tkEof:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, tokToStr(p.tok))
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
popInd(p.lex[])
|
popInd(p.lex)
|
||||||
of tkWhen:
|
of tkWhen:
|
||||||
result = parseObjectWhen(p)
|
result = parseObjectWhen(p)
|
||||||
of tkCase:
|
of tkCase:
|
||||||
|
|
@ -1322,7 +1318,7 @@ proc complexOrSimpleStmt(p: var TParser): PNode =
|
||||||
proc parseStmt(p: var TParser): PNode =
|
proc parseStmt(p: var TParser): PNode =
|
||||||
if p.tok.tokType == tkInd:
|
if p.tok.tokType == tkInd:
|
||||||
result = newNodeP(nkStmtList, p)
|
result = newNodeP(nkStmtList, p)
|
||||||
pushInd(p.lex[], p.tok.indent)
|
pushInd(p.lex, p.tok.indent)
|
||||||
getTok(p)
|
getTok(p)
|
||||||
while true:
|
while true:
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
|
|
@ -1335,7 +1331,7 @@ proc parseStmt(p: var TParser): PNode =
|
||||||
var a = complexOrSimpleStmt(p)
|
var a = complexOrSimpleStmt(p)
|
||||||
if a.kind == nkEmpty: break
|
if a.kind == nkEmpty: break
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
popInd(p.lex[] )
|
popInd(p.lex)
|
||||||
else:
|
else:
|
||||||
# the case statement is only needed for better error messages:
|
# the case statement is only needed for better error messages:
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
|
|
@ -1345,7 +1341,7 @@ proc parseStmt(p: var TParser): PNode =
|
||||||
result = ast.emptyNode
|
result = ast.emptyNode
|
||||||
else:
|
else:
|
||||||
result = simpleStmt(p)
|
result = simpleStmt(p)
|
||||||
if result.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
|
if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
|
||||||
if p.tok.tokType == tkSad: getTok(p)
|
if p.tok.tokType == tkSad: getTok(p)
|
||||||
|
|
||||||
proc parseAll(p: var TParser): PNode =
|
proc parseAll(p: var TParser): PNode =
|
||||||
|
|
@ -1357,7 +1353,7 @@ proc parseAll(p: var TParser): PNode =
|
||||||
of tkEof: break
|
of tkEof: break
|
||||||
else:
|
else:
|
||||||
var a = complexOrSimpleStmt(p)
|
var a = complexOrSimpleStmt(p)
|
||||||
if a.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
|
if a.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
|
||||||
addSon(result, a)
|
addSon(result, a)
|
||||||
|
|
||||||
proc parseTopLevelStmt(p: var TParser): PNode =
|
proc parseTopLevelStmt(p: var TParser): PNode =
|
||||||
|
|
@ -1371,5 +1367,5 @@ proc parseTopLevelStmt(p: var TParser): PNode =
|
||||||
of tkEof: break
|
of tkEof: break
|
||||||
else:
|
else:
|
||||||
result = complexOrSimpleStmt(p)
|
result = complexOrSimpleStmt(p)
|
||||||
if result.kind == nkEmpty: parMessage(p, errExprExpected, tokToStr(p.tok))
|
if result.kind == nkEmpty: parMessage(p, errExprExpected, p.tok)
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ gcc.options.debug = "-g"
|
||||||
@end
|
@end
|
||||||
@else:
|
@else:
|
||||||
@if not release:
|
@if not release:
|
||||||
gcc.options.always = "-w"
|
gcc.options.always = "-w -O1"
|
||||||
@else:
|
@else:
|
||||||
gcc.options.always = "-w"
|
gcc.options.always = "-w"
|
||||||
@end
|
@end
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,10 @@ proc raiseOutOfMem() {.noreturn.} =
|
||||||
when defined(boehmgc):
|
when defined(boehmgc):
|
||||||
when defined(windows):
|
when defined(windows):
|
||||||
const boehmLib = "boehmgc.dll"
|
const boehmLib = "boehmgc.dll"
|
||||||
|
elif defined(macosx):
|
||||||
|
const boehmLib = "libgc.dylib"
|
||||||
|
|
||||||
|
proc boehmGCinit {.importc: "GC_init", dynlib: boehmLib.}
|
||||||
else:
|
else:
|
||||||
const boehmLib = "/usr/lib/libgc.so.1"
|
const boehmLib = "/usr/lib/libgc.so.1"
|
||||||
|
|
||||||
|
|
@ -93,7 +97,8 @@ when defined(boehmgc):
|
||||||
proc dealloc(p: Pointer) =
|
proc dealloc(p: Pointer) =
|
||||||
boehmDealloc(p)
|
boehmDealloc(p)
|
||||||
|
|
||||||
proc initGC() = nil
|
proc initGC() =
|
||||||
|
when defined(macosx): boehmGCinit()
|
||||||
|
|
||||||
#boehmGCincremental()
|
#boehmGCincremental()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue