pas2nim compiles; testing will be done later

This commit is contained in:
rumpf_a@web.de 2010-01-24 10:53:51 +01:00
commit 6bbed25d14
5 changed files with 311 additions and 395 deletions

View file

@ -1,7 +1,7 @@
# #
# #
# The Nimrod Compiler # The Nimrod Compiler
# (c) Copyright 2009 Andreas Rumpf # (c) Copyright 2010 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -17,7 +17,7 @@ var
cmdLineInfo: TLineInfo cmdLineInfo: TLineInfo
proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) = proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
var p = parseopt.init() var p = parseopt.initOptParser()
while true: while true:
parseopt.next(p) parseopt.next(p)
case p.kind case p.kind
@ -40,7 +40,7 @@ proc ProcessCmdLine(pass: TCmdLinePass, command, filename: var string) =
filename = unixToNativePath(p.key) # BUGFIX for portable build scripts filename = unixToNativePath(p.key) # BUGFIX for portable build scripts
break break
if pass == passCmd2: if pass == passCmd2:
arguments = getRestOfCommandLine(p) arguments = cmdLineRest(p)
if not (optRun in gGlobalOptions) and (arguments != ""): if not (optRun in gGlobalOptions) and (arguments != ""):
rawMessage(errArgsNeedRunOption) rawMessage(errArgsNeedRunOption)

View file

@ -1,115 +0,0 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2008 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# A command line parser; the Nimrod version of this file
# will become part of the standard library.
import
os, strutils
type
TCmdLineKind* = enum
cmdEnd, # end of command line reached
cmdArgument, # argument detected
cmdLongoption, # a long option ``--option`` detected
cmdShortOption # a short option ``-c`` detected
TOptParser* = object of TObject
cmd*: string
pos*: int
inShortState*: bool
kind*: TCmdLineKind
key*, val*: string
proc init*(cmdline: string = ""): TOptParser
proc next*(p: var TOptParser)
proc getRestOfCommandLine*(p: TOptParser): string
# implementation
proc init(cmdline: string = ""): TOptParser =
result.pos = 0
result.inShortState = false
if cmdline != "":
result.cmd = cmdline
else:
result.cmd = ""
for i in countup(1, ParamCount()):
result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i)) & ' '
result.kind = cmdEnd
result.key = ""
result.val = ""
proc parseWord(s: string, i: int, w: var string,
delim: TCharSet = {'\x09', ' ', '\0'}): int =
result = i
if s[result] == '\"':
inc(result)
while not (s[result] in {'\0', '\"'}):
add(w, s[result])
inc(result)
if s[result] == '\"': inc(result)
else:
while not (s[result] in delim):
add(w, s[result])
inc(result)
proc handleShortOption(p: var TOptParser) =
var i: int
i = p.pos
p.kind = cmdShortOption
add(p.key, p.cmd[i])
inc(i)
p.inShortState = true
while p.cmd[i] in {'\x09', ' '}:
inc(i)
p.inShortState = false
if p.cmd[i] in {':', '='}:
inc(i)
p.inShortState = false
while p.cmd[i] in {'\x09', ' '}: inc(i)
i = parseWord(p.cmd, i, p.val)
if p.cmd[i] == '\0': p.inShortState = false
p.pos = i
proc next(p: var TOptParser) =
var i: int
i = p.pos
while p.cmd[i] in {'\x09', ' '}: inc(i)
p.pos = i
setlen(p.key, 0)
setlen(p.val, 0)
if p.inShortState:
handleShortOption(p)
return
case p.cmd[i]
of '\0':
p.kind = cmdEnd
of '-':
inc(i)
if p.cmd[i] == '-':
p.kind = cmdLongOption
inc(i)
i = parseWord(p.cmd, i, p.key, {'\0', ' ', '\x09', ':', '='})
while p.cmd[i] in {'\x09', ' '}: inc(i)
if p.cmd[i] in {':', '='}:
inc(i)
while p.cmd[i] in {'\x09', ' '}: inc(i)
p.pos = parseWord(p.cmd, i, p.val)
else:
p.pos = i
else:
p.pos = i
handleShortOption(p)
else:
p.kind = cmdArgument
p.pos = parseWord(p.cmd, i, p.key)
proc getRestOfCommandLine(p: TOptParser): string =
result = strip(copy(p.cmd, p.pos + 0, len(p.cmd) - 1)) # always -1, because Pascal version uses a trailing zero here

View file

@ -7,61 +7,58 @@
# distribution, for details about the copyright. # distribution, for details about the copyright.
# #
#
import import
llstream, strutils, os, ast, rnimsyn, options, msgs, strutils, os, parseopt, llstream, ast, rnimsyn, options, msgs,
paslex, pasparse paslex, pasparse
proc exSymbols(n: PNode) = const
case n.kind Version = "0.8"
of nkEmpty..nkNilLit: nil Usage = """
of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos]) pas2nim - Pascal to Nimrod source converter
of nkWhenStmt, nkStmtList: (c) 2010 Andreas Rumpf
for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i]) Usage: pas2nim [options] inputfile [options]
of nkVarSection, nkConstSection: Options:
for i in countup(0, sonsLen(n) - 1): exSymbol(n.sons[i].sons[0]) -o, --out:FILE set output filename
of nkTypeSection: --ref convert ^typ to ref typ (default: ptr typ)
for i in countup(0, sonsLen(n) - 1): --boot use special translation rules for the Nimrod compiler
exSymbol(n.sons[i].sons[0]) -v, --version write pas2nim's version
if (n.sons[i].sons[2] != nil) and -h, --help show this help
(n.sons[i].sons[2].kind == nkObjectTy): """
fixRecordDef(n.sons[i].sons[2])
else: nil
proc CommandExportSymbols(filename: string) = proc main(infile, outfile: string, flags: set[TParserFlag]) =
# now unused! var stream = LLStreamOpen(infile, fmRead)
var module = parseFile(addFileExt(filename, NimExt)) if stream == nil: rawMessage(errCannotOpenFile, infile)
if module != nil: var p: TParser
exSymbols(module) OpenParser(p, infile, stream, flags)
renderModule(module, getOutFile(filename, "pretty." & NimExt))
proc CommandLexPas(filename: string) =
var f = addFileExt(filename, "pas")
var stream = LLStreamOpen(f, fmRead)
if stream != nil:
var
L: TPasLex
tok: TPasTok
OpenLexer(L, f, stream)
getPasTok(L, tok)
while tok.xkind != pxEof:
printPasTok(tok)
getPasTok(L, tok)
closeLexer(L)
else: rawMessage(errCannotOpenFile, f)
proc CommandPas(filename: string) =
var f = addFileExt(filename, "pas")
var stream = LLStreamOpen(f, fmRead)
if stream != nil:
var p: TPasParser
OpenPasParser(p, f, stream)
var module = parseUnit(p) var module = parseUnit(p)
closePasParser(p) closeParser(p)
renderModule(module, getOutFile(filename, NimExt)) renderModule(module, outfile)
else:
rawMessage(errCannotOpenFile, f)
var
infile = ""
outfile = ""
flags: set[TParserFlag] = {}
for kind, key, val in getopt():
case kind
of cmdArgument: infile = key
of cmdLongOption, cmdShortOption:
case key
of "help", "h":
stdout.write(Usage)
quit(0)
of "version", "v":
stdout.write(Version & "\n")
quit(0)
of "o", "out": outfile = key
of "ref": incl(flags, pfRefs)
of "boot": flags = flags + {pfRefs, pfMoreReplacements, pfImportBlackList}
else: stdout.write("[Error] unknown option: " & key)
of cmdEnd: assert(false)
if infile.len == 0:
# no filename has been given, so we show the help:
stdout.write(Usage)
else:
if outfile.len == 0:
outfile = changeFileExt(infile, "nim")
infile = addFileExt(infile, "pas")
main(infile, outfile, flags)

View file

@ -11,7 +11,7 @@
# the scanner module. # the scanner module.
import import
nhashes, options, msgs, strutils, platform, idents, lexbase nhashes, options, msgs, strutils, platform, idents, lexbase, llstream
const const
MaxLineLength* = 80 # lines longer than this lead to a warning MaxLineLength* = 80 # lines longer than this lead to a warning
@ -24,7 +24,7 @@ const
# keywords are sorted! # keywords are sorted!
type type
TPasTokKind* = enum TTokKind* = enum
pxInvalid, pxEof, pxInvalid, pxEof,
pxAnd, pxArray, pxAs, pxAsm, pxBegin, pxCase, pxClass, pxConst, pxAnd, pxArray, pxAs, pxAsm, pxBegin, pxCase, pxClass, pxConst,
pxConstructor, pxDestructor, pxDiv, pxDo, pxDownto, pxElse, pxEnd, pxExcept, pxConstructor, pxDestructor, pxDiv, pxDo, pxDownto, pxElse, pxEnd, pxExcept,
@ -46,7 +46,7 @@ type
pxAsgn, pxEquals, pxDot, pxDotDot, pxHat, pxPlus, pxMinus, pxStar, pxSlash, pxAsgn, pxEquals, pxDot, pxDotDot, pxHat, pxPlus, pxMinus, pxStar, pxSlash,
pxLe, pxLt, pxGe, pxGt, pxNeq, pxAt, pxStarDirLe, pxStarDirRi, pxCurlyDirLe, pxLe, pxLt, pxGe, pxGt, pxNeq, pxAt, pxStarDirLe, pxStarDirRi, pxCurlyDirLe,
pxCurlyDirRi pxCurlyDirRi
TPasTokKinds* = set[TPasTokKind] TTokKinds* = set[TTokKind]
const const
Keywords = ["and", "array", "as", "asm", "begin", "case", "class", "const", Keywords = ["and", "array", "as", "asm", "begin", "case", "class", "const",
@ -63,8 +63,9 @@ const
lastKeyword = pxXor lastKeyword = pxXor
type type
TPasTok* = object TNumericalBase* = enum base10, base2, base8, base16
xkind*: TPasTokKind # the type of the token TToken* = object
xkind*: TTokKind # the type of the token
ident*: PIdent # the parsed identifier ident*: PIdent # the parsed identifier
iNumber*: BiggestInt # the parsed integer literal iNumber*: BiggestInt # the parsed integer literal
fNumber*: BiggestFloat # the parsed floating point literal fNumber*: BiggestFloat # the parsed floating point literal
@ -72,79 +73,104 @@ type
# or float literals # or float literals
literal*: string # the parsed (string) literal literal*: string # the parsed (string) literal
TPasLex* = object TLexer* = object of TBaseLexer
filename*: string filename*: string
proc getPasTok*(L: var TPasLex, tok: var TPasTok) proc getTok*(L: var TLexer, tok: var TToken)
proc PrintPasTok*(tok: TPasTok) proc PrintTok*(tok: TToken)
proc pasTokToStr*(tok: TPasTok): string proc `$`*(tok: TToken): string
# implementation # implementation
var dummyIdent: PIdent var
dummyIdent: PIdent
gLinesCompiled: int
proc fillToken(L: var TToken) = proc fillToken(L: var TToken) =
L.TokType = tkInvalid L.xkind = pxInvalid
L.iNumber = 0 L.iNumber = 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 # this prevents many bugs!
proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) = proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) =
openBaseLexer(lex, inputstream) openBaseLexer(lex, inputstream)
lex.indentStack = @[0]
lex.filename = filename lex.filename = filename
lex.indentAhead = - 1
proc closeLexer(lex: var TLexer) = proc closeLexer*(lex: var TLexer) =
inc(gLinesCompiled, lex.LineNumber) inc(gLinesCompiled, lex.LineNumber)
closeBaseLexer(lex) closeBaseLexer(lex)
proc getColumn(L: TLexer): int = proc getColumn(L: TLexer): int =
result = getColNumber(L, L.bufPos) result = getColNumber(L, L.bufPos)
proc getLineInfo(L: TLexer): TLineInfo = proc getLineInfo*(L: TLexer): TLineInfo =
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos)) result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
msgs.liMessage(getLineInfo(L), msg, arg) msgs.liMessage(getLineInfo(L), msg, arg)
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
msgs.liMessage(info, msg, arg) msgs.liMessage(info, msg, arg)
proc binaryStrSearch(x: openarray[string], y: string): int = proc TokKindToStr*(k: TTokKind): string =
var a = 0 case k
var b = len(x) of pxEof: result = "[EOF]"
while a < b: of firstKeyword..lastKeyword:
var mid = (a + b) div 2 result = keywords[ord(k)-ord(firstKeyword)]
if x[mid] < y: a = mid + 1 of pxInvalid, pxComment, pxStrLit: result = "string literal"
else: b = mid of pxCommand: result = "{@"
if a < len(x) and x[a] == y: result = a of pxAmp: result = "{&"
else: result = -1 of pxPer: result = "{%"
of pxSymbol: result = "identifier"
of pxIntLit, pxInt64Lit: result = "integer literal"
of pxFloatLit: result = "floating point literal"
of pxParLe: result = "("
of pxParRi: result = ")"
of pxBracketLe: result = "["
of pxBracketRi: result = "]"
of pxComma: result = ","
of pxSemiColon: result = ";"
of pxColon: result = ":"
of pxAsgn: result = ":="
of pxEquals: result = "="
of pxDot: result = "."
of pxDotDot: result = ".."
of pxHat: result = "^"
of pxPlus: result = "+"
of pxMinus: result = "-"
of pxStar: result = "*"
of pxSlash: result = "/"
of pxLe: result = "<="
of pxLt: result = "<"
of pxGe: result = ">="
of pxGt: result = ">"
of pxNeq: result = "<>"
of pxAt: result = "@"
of pxStarDirLe: result = "(*$"
of pxStarDirRi: result = "*)"
of pxCurlyDirLe: result = "{$"
of pxCurlyDirRi: result = "}"
proc pastokToStr(tok: TPasTok): string = proc `$`(tok: TToken): string =
case tok.xkind case tok.xkind
of pxIntLit, pxInt64Lit: result = $(tok.iNumber) of pxInvalid, pxComment, pxStrLit: result = tok.literal
of pxFloatLit: result = $(tok.fNumber) of pxSymbol: result = tok.ident.s
of pxInvalid, pxComment..pxStrLit: result = tok.literal of pxIntLit, pxInt64Lit: result = $tok.iNumber
else: of pxFloatLit: result = $tok.fNumber
if (tok.ident.s != ""): result = tok.ident.s else: result = TokKindToStr(tok.xkind)
else: result = pasTokKindToStr[tok.xkind]
proc PrintPasTok(tok: TPasTok) = proc PrintTok(tok: TToken) =
write(stdout, pasTokKindToStr[tok.xkind]) writeln(stdout, $tok)
write(stdout, ' ')
writeln(stdout, pastokToStr(tok))
proc setKeyword(L: var TPasLex, tok: var TPasTok) = proc setKeyword(L: var TLexer, tok: var TToken) =
var x = binaryStrSearch(keywords, toLower(tok.ident.s)) var x = binaryStrSearch(keywords, toLower(tok.ident.s))
if x < 0: tok.xkind = pxSymbol if x < 0: tok.xkind = pxSymbol
else: tok.xKind = TPasTokKind(x + ord(firstKeyword)) else: tok.xKind = TTokKind(x + ord(firstKeyword))
proc matchUnderscoreChars(L: var TPasLex, tok: var TPasTok, chars: TCharSet) = proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
# matches ([chars]_)* # matches ([chars]_)*
var pos = L.bufpos # use registers for pos, buf var pos = L.bufpos # use registers for pos, buf
var buf = L.buf var buf = L.buf
@ -164,7 +190,7 @@ proc isFloatLiteral(s: string): bool =
if s[i] in {'.', 'e', 'E'}: if s[i] in {'.', 'e', 'E'}:
return true return true
proc getNumber2(L: var TPasLex, tok: var TPasTok) = proc getNumber2(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 1 # skip % var pos = L.bufpos + 1 # skip %
if not (L.buf[pos] in {'0'..'1'}): if not (L.buf[pos] in {'0'..'1'}):
# BUGFIX for %date% # BUGFIX for %date%
@ -192,7 +218,7 @@ proc getNumber2(L: var TPasLex, tok: var TPasTok) =
else: tok.xkind = pxIntLit else: tok.xkind = pxIntLit
L.bufpos = pos L.bufpos = pos
proc getNumber16(L: var TPasLex, tok: var TPasTok) = proc getNumber16(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 1 # skip $ var pos = L.bufpos + 1 # skip $
tok.base = base16 tok.base = base16
var xi: biggestInt = 0 var xi: biggestInt = 0
@ -223,7 +249,7 @@ proc getNumber16(L: var TPasLex, tok: var TPasTok) =
tok.xkind = pxIntLit tok.xkind = pxIntLit
L.bufpos = pos L.bufpos = pos
proc getNumber10(L: var TPasLex, tok: var TPasTok) = proc getNumber10(L: var TLexer, tok: var TToken) =
tok.base = base10 tok.base = base10
matchUnderscoreChars(L, tok, {'0'..'9'}) matchUnderscoreChars(L, tok, {'0'..'9'})
if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}): if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}):
@ -251,7 +277,7 @@ proc HandleCRLF(L: var TLexer, pos: int): int =
of LF: result = lexbase.HandleLF(L, pos) of LF: result = lexbase.HandleLF(L, pos)
else: result = pos else: result = pos
proc getString(L: var TPasLex, tok: var TPasTok) = proc getString(L: var TLexer, tok: var TToken) =
var xi: int var xi: int
var pos = L.bufPos var pos = L.bufPos
var buf = L.buf var buf = L.buf
@ -300,7 +326,7 @@ proc getString(L: var TPasLex, tok: var TPasTok) =
tok.xkind = pxStrLit tok.xkind = pxStrLit
L.bufpos = pos L.bufpos = pos
proc getSymbol(L: var TPasLex, tok: var TPasTok) = proc getSymbol(L: var TLexer, tok: var TToken) =
var h: THash = 0 var h: THash = 0
var pos = L.bufpos var pos = L.bufpos
var buf = L.buf var buf = L.buf
@ -326,7 +352,7 @@ proc getSymbol(L: var TPasLex, tok: var TPasTok) =
L.bufpos = pos L.bufpos = pos
setKeyword(L, tok) setKeyword(L, tok)
proc scanLineComment(L: var TPasLex, tok: var TPasTok) = proc scanLineComment(L: var TLexer, tok: var TToken) =
var pos = L.bufpos var pos = L.bufpos
var buf = L.buf var buf = L.buf
# a comment ends if the next line does not start with the // on the same # a comment ends if the next line does not start with the // on the same
@ -351,7 +377,7 @@ proc scanLineComment(L: var TPasLex, tok: var TPasTok) =
break break
L.bufpos = pos L.bufpos = pos
proc scanCurlyComment(L: var TPasLex, tok: var TPasTok) = proc scanCurlyComment(L: var TLexer, tok: var TToken) =
var pos = L.bufpos var pos = L.bufpos
var buf = L.buf var buf = L.buf
tok.literal = "#" tok.literal = "#"
@ -371,7 +397,7 @@ proc scanCurlyComment(L: var TPasLex, tok: var TPasTok) =
inc(pos) inc(pos)
L.bufpos = pos L.bufpos = pos
proc scanStarComment(L: var TPasLex, tok: var TPasTok) = proc scanStarComment(L: var TLexer, tok: var TToken) =
var pos = L.bufpos var pos = L.bufpos
var buf = L.buf var buf = L.buf
tok.literal = "#" tok.literal = "#"
@ -396,7 +422,7 @@ proc scanStarComment(L: var TPasLex, tok: var TPasTok) =
inc(pos) inc(pos)
L.bufpos = pos L.bufpos = pos
proc skip(L: var TPasLex, tok: var TPasTok) = proc skip(L: var TLexer, tok: var TToken) =
var pos = L.bufpos var pos = L.bufpos
var buf = L.buf var buf = L.buf
while true: while true:
@ -410,7 +436,7 @@ proc skip(L: var TPasLex, tok: var TPasTok) =
break # EndOfFile also leaves the loop break # EndOfFile also leaves the loop
L.bufpos = pos L.bufpos = pos
proc getPasTok(L: var TPasLex, tok: var TPasTok) = proc getTok(L: var TLexer, tok: var TToken) =
tok.xkind = pxInvalid tok.xkind = pxInvalid
fillToken(tok) fillToken(tok)
skip(L, tok) skip(L, tok)

View file

@ -15,18 +15,23 @@ import
os, llstream, paslex, idents, strutils, ast, astalgo, msgs, options os, llstream, paslex, idents, strutils, ast, astalgo, msgs, options
type type
TPasSection* = enum TSection = enum
seImplementation, seInterface seImplementation, seInterface
TPasContext* = enum TContext = enum
conExpr, conStmt, conTypeDesc conExpr, conStmt, conTypeDesc
TPasParser*{.final.} = object TParserFlag* = enum
section*: TPasSection pfRefs, ## use "ref" instead of "ptr" for Pascal's ^typ
inParamList*: bool pfMoreReplacements, ## use more than the default replacements
context*: TPasContext # needed for the @emit command pfImportBlackList ## use import blacklist
lastVarSection*: PNode TParser*{.final.} = object
lex*: TPasLex section: TSection
tok*: TPasTok inParamList: bool
repl*: TIdTable # replacements context: TContext # needed for the @emit command
lastVarSection: PNode
lex: TLexer
tok: TToken
repl: TIdTable # replacements
flags: set[TParserFlag]
TReplaceTuple* = array[0..1, string] TReplaceTuple* = array[0..1, string]
@ -49,49 +54,42 @@ const
["ltu", "`<%`"], ["leu", "`<=%`"], ["shlu", "`shl`"], ["shru", "`shr`"], ["ltu", "`<%`"], ["leu", "`<=%`"], ["shlu", "`shl`"], ["shru", "`shr`"],
["assigned", "not isNil"], ["eintoverflow", "EOverflow"], ["format", "`%`"], ["assigned", "not isNil"], ["eintoverflow", "EOverflow"], ["format", "`%`"],
["snil", "nil"], ["tostringf", "$"], ["ttextfile", "tfile"], ["snil", "nil"], ["tostringf", "$"], ["ttextfile", "tfile"],
["tbinaryfile", "tfile"], ["strstart", "0"], ["nl", "\"\\n\""], ["tostring", ["tbinaryfile", "tfile"], ["strstart", "0"], ["nl", "\"\\n\""],
"$"]] #, ["tostring", "$"]]
# ('NL', '"\n"'),
# ('tabulator', '''\t'''),
# ('esc', '''\e'''),
# ('cr', '''\r'''),
# ('lf', '''\l'''),
# ('ff', '''\f'''),
# ('bel', '''\a'''),
# ('backspace', '''\b'''),
# ('vt', '''\v''')
proc ParseUnit*(p: var TPasParser): PNode proc ParseUnit*(p: var TParser): PNode
proc openPasParser*(p: var TPasParser, filename: string, inputStream: PLLStream) proc openParser*(p: var TParser, filename: string, inputStream: PLLStream,
proc closePasParser*(p: var TPasParser) flags: set[TParserFlag] = {})
proc closeParser*(p: var TParser)
proc exSymbol*(n: var PNode) proc exSymbol*(n: var PNode)
proc fixRecordDef*(n: var PNode) proc fixRecordDef*(n: var PNode)
# XXX: move these two to an auxiliary module # XXX: move these two to an auxiliary module
# implementation # implementation
proc OpenPasParser(p: var TPasParser, filename: string, proc OpenParser(p: var TParser, filename: string,
inputStream: PLLStream) = inputStream: PLLStream, flags: set[TParserFlag] = {}) =
OpenLexer(p.lex, filename, inputStream) OpenLexer(p.lex, filename, inputStream)
initIdTable(p.repl) initIdTable(p.repl)
for i in countup(low(stdReplacements), high(stdReplacements)): for i in countup(low(stdReplacements), high(stdReplacements)):
IdTablePut(p.repl, getIdent(stdReplacements[i][0]), IdTablePut(p.repl, getIdent(stdReplacements[i][0]),
getIdent(stdReplacements[i][1])) getIdent(stdReplacements[i][1]))
if gCmd == cmdBoot: if pfMoreReplacements in flags:
for i in countup(low(nimReplacements), high(nimReplacements)): for i in countup(low(nimReplacements), high(nimReplacements)):
IdTablePut(p.repl, getIdent(nimReplacements[i][0]), IdTablePut(p.repl, getIdent(nimReplacements[i][0]),
getIdent(nimReplacements[i][1])) getIdent(nimReplacements[i][1]))
p.flags = flags
proc ClosePasParser(p: var TPasParser) = CloseLexer(p.lex) proc CloseParser(p: var TParser) = CloseLexer(p.lex)
proc getTok(p: var TPasParser) = getPasTok(p.lex, p.tok) proc getTok(p: var TParser) = getTok(p.lex, p.tok)
proc parMessage(p: TPasParser, msg: TMsgKind, arg = "") = proc parMessage(p: TParser, msg: TMsgKind, arg = "") =
lexMessage(p.lex, msg, arg) lexMessage(p.lex, msg, arg)
proc parLineInfo(p: TPasParser): TLineInfo = proc parLineInfo(p: TParser): TLineInfo =
result = getLineInfo(p.lex) result = getLineInfo(p.lex)
proc skipCom(p: var TPasParser, n: PNode) = proc skipCom(p: var TParser, n: PNode) =
while p.tok.xkind == pxComment: while p.tok.xkind == pxComment:
if (n != nil): if (n != nil):
if n.comment == nil: n.comment = p.tok.literal if n.comment == nil: n.comment = p.tok.literal
@ -100,48 +98,48 @@ proc skipCom(p: var TPasParser, n: PNode) =
parMessage(p, warnCommentXIgnored, p.tok.literal) parMessage(p, warnCommentXIgnored, p.tok.literal)
getTok(p) getTok(p)
proc ExpectIdent(p: TPasParser) = proc ExpectIdent(p: TParser) =
if p.tok.xkind != pxSymbol: if p.tok.xkind != pxSymbol:
lexMessage(p.lex, errIdentifierExpected, pasTokToStr(p.tok)) lexMessage(p.lex, errIdentifierExpected, $(p.tok))
proc Eat(p: var TPasParser, xkind: TPasTokKind) = proc Eat(p: var TParser, xkind: TTokKind) =
if p.tok.xkind == xkind: getTok(p) if p.tok.xkind == xkind: getTok(p)
else: lexMessage(p.lex, errTokenExpected, PasTokKindToStr[xkind]) else: lexMessage(p.lex, errTokenExpected, TokKindToStr(xkind))
proc Opt(p: var TPasParser, xkind: TPasTokKind) = proc Opt(p: var TParser, xkind: TTokKind) =
if p.tok.xkind == xkind: getTok(p) if p.tok.xkind == xkind: getTok(p)
proc newNodeP(kind: TNodeKind, p: TPasParser): 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: TPasParser): PNode = proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TParser): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
result.intVal = intVal result.intVal = intVal
proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat,
p: TPasParser): PNode = p: TParser): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
result.floatVal = floatVal result.floatVal = floatVal
proc newStrNodeP(kind: TNodeKind, strVal: string, p: TPasParser): PNode = proc newStrNodeP(kind: TNodeKind, strVal: string, p: TParser): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
result.strVal = strVal result.strVal = strVal
proc newIdentNodeP(ident: PIdent, p: TPasParser): PNode = proc newIdentNodeP(ident: PIdent, p: TParser): PNode =
result = newNodeP(nkIdent, p) result = newNodeP(nkIdent, p)
result.ident = ident result.ident = ident
proc createIdentNodeP(ident: PIdent, p: TPasParser): PNode = proc createIdentNodeP(ident: PIdent, p: TParser): PNode =
result = newNodeP(nkIdent, p) result = newNodeP(nkIdent, p)
var x = PIdent(IdTableGet(p.repl, ident)) var x = PIdent(IdTableGet(p.repl, ident))
if x != nil: result.ident = x if x != nil: result.ident = x
else: result.ident = ident else: result.ident = ident
proc parseExpr(p: var TPasParser): PNode proc parseExpr(p: var TParser): PNode
proc parseStmt(p: var TPasParser): PNode proc parseStmt(p: var TParser): PNode
proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode
proc parseEmit(p: var TPasParser, definition: PNode): PNode = proc parseEmit(p: var TParser, definition: PNode): PNode =
getTok(p) # skip 'emit' getTok(p) # skip 'emit'
result = nil result = nil
if p.tok.xkind != pxCurlyDirRi: if p.tok.xkind != pxCurlyDirRi:
@ -160,7 +158,7 @@ proc parseEmit(p: var TPasParser, definition: PNode): PNode =
result = parseTypeDesc(p, definition) result = parseTypeDesc(p, definition)
eat(p, pxCurlyDirRi) eat(p, pxCurlyDirRi)
proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode = proc parseCommand(p: var TParser, definition: PNode = nil): PNode =
result = nil result = nil
getTok(p) getTok(p)
if p.tok.ident.id == getIdent("discard").id: if p.tok.ident.id == getIdent("discard").id:
@ -183,7 +181,7 @@ proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode =
addSon(result, a.sons[0]) addSon(result, a.sons[0])
addSon(result, a.sons[1]) addSon(result, a.sons[1])
else: else:
parMessage(p, errInvalidDirectiveX, pasTokToStr(p.tok)) parMessage(p, errInvalidDirectiveX, $(p.tok))
result = a result = a
elif p.tok.ident.id == getIdent("emit").id: elif p.tok.ident.id == getIdent("emit").id:
result = parseEmit(p, definition) result = parseEmit(p, definition)
@ -218,24 +216,21 @@ proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode =
getTok(p) getTok(p)
eat(p, pxCurlyDirRi) eat(p, pxCurlyDirRi)
else: else:
parMessage(p, errInvalidDirectiveX, pasTokToStr(p.tok)) parMessage(p, errInvalidDirectiveX, $(p.tok))
while true: while true:
getTok(p) getTok(p)
if (p.tok.xkind == pxCurlyDirRi) or (p.tok.xkind == pxEof): break if (p.tok.xkind == pxCurlyDirRi) or (p.tok.xkind == pxEof): break
eat(p, pxCurlyDirRi) eat(p, pxCurlyDirRi)
result = nil result = nil
proc getPrecedence(kind: TPasTokKind): int = proc getPrecedence(kind: TTokKind): int =
case kind case kind
of pxDiv, pxMod, pxStar, pxSlash, pxShl, pxShr, pxAnd: of pxDiv, pxMod, pxStar, pxSlash, pxShl, pxShr, pxAnd: result = 5
result = 5 of pxPlus, pxMinus, pxOr, pxXor: result = 4
of pxPlus, pxMinus, pxOr, pxXor: of pxIn, pxEquals, pxLe, pxLt, pxGe, pxGt, pxNeq, pxIs: result = 3
result = 4
of pxIn, pxEquals, pxLe, pxLt, pxGe, pxGt, pxNeq, pxIs:
result = 3
else: result = -1 else: result = -1
proc rangeExpr(p: var TPasParser): PNode = proc rangeExpr(p: var TParser): PNode =
var a = parseExpr(p) var a = parseExpr(p)
if p.tok.xkind == pxDotDot: if p.tok.xkind == pxDotDot:
result = newNodeP(nkRange, p) result = newNodeP(nkRange, p)
@ -246,7 +241,7 @@ proc rangeExpr(p: var TPasParser): PNode =
else: else:
result = a result = a
proc bracketExprList(p: var TPasParser, first: PNode): PNode = proc bracketExprList(p: var TParser, first: PNode): PNode =
result = newNodeP(nkBracketExpr, p) result = newNodeP(nkBracketExpr, p)
addSon(result, first) addSon(result, first)
getTok(p) getTok(p)
@ -256,7 +251,7 @@ proc bracketExprList(p: var TPasParser, first: PNode): PNode =
getTok(p) getTok(p)
break break
if p.tok.xkind == pxEof: if p.tok.xkind == pxEof:
parMessage(p, errTokenExpected, PasTokKindToStr[pxBracketRi]) parMessage(p, errTokenExpected, TokKindToStr(pxBracketRi))
break break
var a = rangeExpr(p) var a = rangeExpr(p)
skipCom(p, a) skipCom(p, a)
@ -265,8 +260,8 @@ proc bracketExprList(p: var TPasParser, first: PNode): PNode =
skipCom(p, a) skipCom(p, a)
addSon(result, a) addSon(result, a)
proc exprColonEqExpr(p: var TPasParser, kind: TNodeKind, proc exprColonEqExpr(p: var TParser, kind: TNodeKind,
tok: TPasTokKind): PNode = tok: TTokKind): PNode =
var a = parseExpr(p) var a = parseExpr(p)
if p.tok.xkind == tok: if p.tok.xkind == tok:
result = newNodeP(kind, p) result = newNodeP(kind, p)
@ -277,8 +272,8 @@ proc exprColonEqExpr(p: var TPasParser, kind: TNodeKind,
else: else:
result = a result = a
proc exprListAux(p: var TPasParser, elemKind: TNodeKind, proc exprListAux(p: var TParser, elemKind: TNodeKind,
endTok, sepTok: TPasTokKind, result: PNode) = endTok, sepTok: TTokKind, result: PNode) =
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
while true: while true:
@ -286,7 +281,7 @@ proc exprListAux(p: var TPasParser, elemKind: TNodeKind,
getTok(p) getTok(p)
break break
if p.tok.xkind == pxEof: if p.tok.xkind == pxEof:
parMessage(p, errTokenExpected, PasTokKindToStr[endtok]) parMessage(p, errTokenExpected, TokKindToStr(endtok))
break break
var a = exprColonEqExpr(p, elemKind, sepTok) var a = exprColonEqExpr(p, elemKind, sepTok)
skipCom(p, a) skipCom(p, a)
@ -295,11 +290,11 @@ proc exprListAux(p: var TPasParser, elemKind: TNodeKind,
skipCom(p, a) skipCom(p, a)
addSon(result, a) addSon(result, a)
proc qualifiedIdent(p: var TPasParser): PNode = proc qualifiedIdent(p: var TParser): PNode =
if p.tok.xkind == pxSymbol: if p.tok.xkind == pxSymbol:
result = createIdentNodeP(p.tok.ident, p) result = createIdentNodeP(p.tok.ident, p)
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $p.tok)
return nil return nil
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -313,9 +308,9 @@ proc qualifiedIdent(p: var TPasParser): PNode =
addSon(result, createIdentNodeP(p.tok.ident, p)) addSon(result, createIdentNodeP(p.tok.ident, p))
getTok(p) getTok(p)
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $p.tok)
proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind, proc qualifiedIdentListAux(p: var TParser, endTok: TTokKind,
result: PNode) = result: PNode) =
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -324,7 +319,7 @@ proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind,
getTok(p) getTok(p)
break break
if p.tok.xkind == pxEof: if p.tok.xkind == pxEof:
parMessage(p, errTokenExpected, PasTokKindToStr[endtok]) parMessage(p, errTokenExpected, TokKindToStr(endtok))
break break
var a = qualifiedIdent(p) var a = qualifiedIdent(p)
skipCom(p, a) skipCom(p, a)
@ -333,8 +328,8 @@ proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind,
skipCom(p, a) skipCom(p, a)
addSon(result, a) addSon(result, a)
proc exprColonEqExprList(p: var TPasParser, kind, elemKind: TNodeKind, proc exprColonEqExprList(p: var TParser, kind, elemKind: TNodeKind,
endTok, sepTok: TPasTokKind): PNode = endTok, sepTok: TTokKind): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
exprListAux(p, elemKind, endTok, sepTok, result) exprListAux(p, elemKind, endTok, sepTok, result)
@ -345,7 +340,7 @@ proc setBaseFlags(n: PNode, base: TNumericalBase) =
of base8: incl(n.flags, nfBase8) of base8: incl(n.flags, nfBase8)
of base16: incl(n.flags, nfBase16) of base16: incl(n.flags, nfBase16)
proc identOrLiteral(p: var TPasParser): PNode = proc identOrLiteral(p: var TParser): PNode =
case p.tok.xkind case p.tok.xkind
of pxSymbol: of pxSymbol:
result = createIdentNodeP(p.tok.ident, p) result = createIdentNodeP(p.tok.ident, p)
@ -393,17 +388,17 @@ proc identOrLiteral(p: var TPasParser): PNode =
of pxCommand: of pxCommand:
result = parseCommand(p) result = parseCommand(p)
else: else:
parMessage(p, errExprExpected, pasTokToStr(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 = nil result = nil
if result != nil: skipCom(p, result) if result != nil: skipCom(p, result)
proc primary(p: var TPasParser): PNode = proc primary(p: var TParser): PNode =
# prefix operator? # prefix operator?
if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or
(p.tok.xkind == pxPlus): (p.tok.xkind == pxPlus):
result = newNodeP(nkPrefix, p) result = newNodeP(nkPrefix, p)
var a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) var a = newIdentNodeP(getIdent($(p.tok)), p)
addSon(result, a) addSon(result, a)
getTok(p) getTok(p)
skipCom(p, a) skipCom(p, a)
@ -411,7 +406,7 @@ proc primary(p: var TPasParser): PNode =
return return
elif p.tok.xkind == pxAt: elif p.tok.xkind == pxAt:
result = newNodeP(nkAddr, p) result = newNodeP(nkAddr, p)
var a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) var a = newIdentNodeP(getIdent($(p.tok)), p)
getTok(p) getTok(p)
if p.tok.xkind == pxBracketLe: if p.tok.xkind == pxBracketLe:
result = newNodeP(nkPrefix, p) result = newNodeP(nkPrefix, p)
@ -438,7 +433,7 @@ proc primary(p: var TPasParser): PNode =
addSon(result, createIdentNodeP(p.tok.ident, p)) addSon(result, createIdentNodeP(p.tok.ident, p))
getTok(p) getTok(p)
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $(p.tok))
of pxHat: of pxHat:
var a = result var a = result
result = newNodeP(nkDerefExpr, p) result = newNodeP(nkDerefExpr, p)
@ -448,16 +443,16 @@ proc primary(p: var TPasParser): PNode =
result = bracketExprList(p, result) result = bracketExprList(p, result)
else: break else: break
proc lowestExprAux(p: var TPasParser, v: var PNode, limit: int): TPasTokKind = proc lowestExprAux(p: var TParser, v: var PNode, limit: int): TTokKind =
var var
nextop: TPasTokKind nextop: TTokKind
v2, node, opNode: PNode v2, node, opNode: PNode
v = primary(p) # expand while operators have priorities higher than 'limit' v = primary(p) # expand while operators have priorities higher than 'limit'
var op = p.tok.xkind var op = p.tok.xkind
var opPred = getPrecedence(op) var opPred = getPrecedence(op)
while (opPred > limit): while (opPred > limit):
node = newNodeP(nkInfix, p) node = newNodeP(nkInfix, p)
opNode = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) # skip operator: opNode = newIdentNodeP(getIdent($(p.tok)), p) # skip operator:
getTok(p) getTok(p)
case op case op
of pxPlus: of pxPlus:
@ -498,10 +493,8 @@ proc fixExpr(n: PNode): PNode =
if n == nil: return if n == nil: return
case n.kind case n.kind
of nkInfix: of nkInfix:
if n.sons[1].kind == nkBracket: if n.sons[1].kind == nkBracket: n.sons[1].kind = nkCurly
n.sons[1].kind = nkCurly if n.sons[2].kind == nkBracket: n.sons[2].kind = nkCurly
if n.sons[2].kind == nkBracket:
n.sons[2].kind = nkCurly
if (n.sons[0].kind == nkIdent): if (n.sons[0].kind == nkIdent):
if (n.sons[0].ident.id == getIdent("+").id): if (n.sons[0].ident.id == getIdent("+").id):
if (n.sons[1].kind == nkCharLit) and (n.sons[2].kind == nkStrLit) and if (n.sons[1].kind == nkCharLit) and (n.sons[2].kind == nkStrLit) and
@ -517,7 +510,7 @@ proc fixExpr(n: PNode): PNode =
if not (n.kind in {nkEmpty..nkNilLit}): if not (n.kind in {nkEmpty..nkNilLit}):
for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i]) for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i])
proc parseExpr(p: var TPasParser): PNode = proc parseExpr(p: var TParser): PNode =
var oldcontext = p.context var oldcontext = p.context
p.context = conExpr p.context = conExpr
if p.tok.xkind == pxCommand: if p.tok.xkind == pxCommand:
@ -527,7 +520,7 @@ proc parseExpr(p: var TPasParser): PNode =
result = fixExpr(result) result = fixExpr(result)
p.context = oldcontext p.context = oldcontext
proc parseExprStmt(p: var TPasParser): PNode = proc parseExprStmt(p: var TParser): PNode =
var info = parLineInfo(p) var info = parLineInfo(p)
var a = parseExpr(p) var a = parseExpr(p)
if p.tok.xkind == pxAsgn: if p.tok.xkind == pxAsgn:
@ -545,7 +538,7 @@ proc inImportBlackList(ident: PIdent): bool =
if ident.id == getIdent(ImportBlackList[i]).id: if ident.id == getIdent(ImportBlackList[i]).id:
return true return true
proc parseUsesStmt(p: var TPasParser): PNode = proc parseUsesStmt(p: var TParser): PNode =
var a: PNode var a: PNode
result = newNodeP(nkImportStmt, p) result = newNodeP(nkImportStmt, p)
getTok(p) # skip `import` getTok(p) # skip `import`
@ -555,11 +548,11 @@ proc parseUsesStmt(p: var TPasParser): PNode =
of pxEof: break of pxEof: break
of pxSymbol: a = newIdentNodeP(p.tok.ident, p) of pxSymbol: a = newIdentNodeP(p.tok.ident, p)
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $(p.tok))
break break
getTok(p) # skip identifier, string getTok(p) # skip identifier, string
skipCom(p, a) skipCom(p, a)
if (gCmd != cmdBoot) or not inImportBlackList(a.ident): if pfImportBlackList notin p.flags or not inImportBlackList(a.ident):
addSon(result, createIdentNodeP(a.ident, p)) addSon(result, createIdentNodeP(a.ident, p))
if p.tok.xkind == pxComma: if p.tok.xkind == pxComma:
getTok(p) getTok(p)
@ -568,14 +561,14 @@ proc parseUsesStmt(p: var TPasParser): PNode =
break break
if sonsLen(result) == 0: result = nil if sonsLen(result) == 0: result = nil
proc parseIncludeDir(p: var TPasParser): PNode = proc parseIncludeDir(p: var TParser): PNode =
result = newNodeP(nkIncludeStmt, p) result = newNodeP(nkIncludeStmt, p)
getTok(p) # skip `include` getTok(p) # skip `include`
var filename = "" var filename = ""
while true: while true:
case p.tok.xkind case p.tok.xkind
of pxSymbol, pxDot, pxDotDot, pxSlash: of pxSymbol, pxDot, pxDotDot, pxSlash:
filename = filename & pasTokToStr(p.tok) filename = filename & $(p.tok)
getTok(p) getTok(p)
of pxStrLit: of pxStrLit:
filename = p.tok.literal filename = p.tok.literal
@ -584,26 +577,26 @@ proc parseIncludeDir(p: var TPasParser): PNode =
of pxCurlyDirRi: of pxCurlyDirRi:
break break
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $(p.tok))
break break
addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, "nim"), p)) addSon(result, newStrNodeP(nkStrLit, changeFileExt(filename, "nim"), p))
if filename == "config.inc": result = nil if filename == "config.inc": result = nil
proc definedExprAux(p: var TPasParser): PNode = proc definedExprAux(p: var TParser): PNode =
result = newNodeP(nkCall, p) result = newNodeP(nkCall, p)
addSon(result, newIdentNodeP(getIdent("defined"), p)) addSon(result, newIdentNodeP(getIdent("defined"), p))
ExpectIdent(p) ExpectIdent(p)
addSon(result, createIdentNodeP(p.tok.ident, p)) addSon(result, createIdentNodeP(p.tok.ident, p))
getTok(p) getTok(p)
proc isHandledDirective(p: TPasParser): bool = proc isHandledDirective(p: TParser): bool =
result = false result = false
if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}:
case whichKeyword(p.tok.ident) case toLower(p.tok.ident.s)
of wElse, wEndif: result = false of "else", "endif": result = false
else: result = true else: result = true
proc parseStmtList(p: var TPasParser): PNode = proc parseStmtList(p: var TParser): PNode =
result = newNodeP(nkStmtList, p) result = newNodeP(nkStmtList, p)
while true: while true:
case p.tok.xkind case p.tok.xkind
@ -616,27 +609,27 @@ proc parseStmtList(p: var TPasParser): PNode =
addSon(result, parseStmt(p)) addSon(result, parseStmt(p))
if sonsLen(result) == 1: result = result.sons[0] if sonsLen(result) == 1: result = result.sons[0]
proc parseIfDirAux(p: var TPasParser, result: PNode) = proc parseIfDirAux(p: var TParser, result: PNode) =
addSon(result.sons[0], parseStmtList(p)) addSon(result.sons[0], parseStmtList(p))
if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}:
var endMarker = succ(p.tok.xkind) var endMarker = succ(p.tok.xkind)
if whichKeyword(p.tok.ident) == wElse: if toLower(p.tok.ident.s) == "else":
var s = newNodeP(nkElse, p) var s = newNodeP(nkElse, p)
while (p.tok.xkind != pxEof) and (p.tok.xkind != endMarker): getTok(p) while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p)
eat(p, endMarker) eat(p, endMarker)
addSon(s, parseStmtList(p)) addSon(s, parseStmtList(p))
addSon(result, s) addSon(result, s)
if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}: if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}:
endMarker = succ(p.tok.xkind) endMarker = succ(p.tok.xkind)
if whichKeyword(p.tok.ident) == wEndif: if toLower(p.tok.ident.s) == "endif":
while (p.tok.xkind != pxEof) and (p.tok.xkind != endMarker): getTok(p) while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p)
eat(p, endMarker) eat(p, endMarker)
else: else:
parMessage(p, errXExpected, "{$endif}") parMessage(p, errXExpected, "{$endif}")
else: else:
parMessage(p, errXExpected, "{$endif}") parMessage(p, errXExpected, "{$endif}")
proc parseIfdefDir(p: var TPasParser, endMarker: TPasTokKind): PNode = proc parseIfdefDir(p: var TParser, endMarker: TTokKind): PNode =
result = newNodeP(nkWhenStmt, p) result = newNodeP(nkWhenStmt, p)
addSon(result, newNodeP(nkElifBranch, p)) addSon(result, newNodeP(nkElifBranch, p))
getTok(p) getTok(p)
@ -644,7 +637,7 @@ proc parseIfdefDir(p: var TPasParser, endMarker: TPasTokKind): PNode =
eat(p, endMarker) eat(p, endMarker)
parseIfDirAux(p, result) parseIfDirAux(p, result)
proc parseIfndefDir(p: var TPasParser, endMarker: TPasTokKind): PNode = proc parseIfndefDir(p: var TParser, endMarker: TTokKind): PNode =
result = newNodeP(nkWhenStmt, p) result = newNodeP(nkWhenStmt, p)
addSon(result, newNodeP(nkElifBranch, p)) addSon(result, newNodeP(nkElifBranch, p))
getTok(p) getTok(p)
@ -655,7 +648,7 @@ proc parseIfndefDir(p: var TPasParser, endMarker: TPasTokKind): PNode =
addSon(result.sons[0], e) addSon(result.sons[0], e)
parseIfDirAux(p, result) parseIfDirAux(p, result)
proc parseIfDir(p: var TPasParser, endMarker: TPasTokKind): PNode = proc parseIfDir(p: var TParser, endMarker: TTokKind): PNode =
result = newNodeP(nkWhenStmt, p) result = newNodeP(nkWhenStmt, p)
addSon(result, newNodeP(nkElifBranch, p)) addSon(result, newNodeP(nkElifBranch, p))
getTok(p) getTok(p)
@ -663,33 +656,33 @@ proc parseIfDir(p: var TPasParser, endMarker: TPasTokKind): PNode =
eat(p, endMarker) eat(p, endMarker)
parseIfDirAux(p, result) parseIfDirAux(p, result)
proc parseDirective(p: var TPasParser): PNode = proc parseDirective(p: var TParser): PNode =
result = nil result = nil
if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return
var endMarker = succ(p.tok.xkind) var endMarker = succ(p.tok.xkind)
if p.tok.ident != nil: if p.tok.ident != nil:
case whichKeyword(p.tok.ident) case toLower(p.tok.ident.s)
of wInclude: of "include":
result = parseIncludeDir(p) result = parseIncludeDir(p)
eat(p, endMarker) eat(p, endMarker)
of wIf: result = parseIfDir(p, endMarker) of "if": result = parseIfDir(p, endMarker)
of wIfdef: result = parseIfdefDir(p, endMarker) of "ifdef": result = parseIfdefDir(p, endMarker)
of wIfndef: result = parseIfndefDir(p, endMarker) of "ifndef": result = parseIfndefDir(p, endMarker)
else: else:
# skip unknown compiler directive # skip unknown compiler directive
while (p.tok.xkind != pxEof) and (p.tok.xkind != endMarker): getTok(p) while p.tok.xkind != pxEof and p.tok.xkind != endMarker: getTok(p)
eat(p, endMarker) eat(p, endMarker)
else: else:
eat(p, endMarker) eat(p, endMarker)
proc parseRaise(p: var TPasParser): PNode = proc parseRaise(p: var TParser): PNode =
result = newNodeP(nkRaiseStmt, p) result = newNodeP(nkRaiseStmt, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
if p.tok.xkind != pxSemicolon: addSon(result, parseExpr(p)) if p.tok.xkind != pxSemicolon: addSon(result, parseExpr(p))
else: addSon(result, nil) else: addSon(result, nil)
proc parseIf(p: var TPasParser): PNode = proc parseIf(p: var TParser): PNode =
result = newNodeP(nkIfStmt, p) result = newNodeP(nkIfStmt, p)
while true: while true:
getTok(p) # skip ``if`` getTok(p) # skip ``if``
@ -713,7 +706,7 @@ proc parseIf(p: var TPasParser): PNode =
else: else:
break break
proc parseWhile(p: var TPasParser): PNode = proc parseWhile(p: var TParser): PNode =
result = newNodeP(nkWhileStmt, p) result = newNodeP(nkWhileStmt, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -722,7 +715,7 @@ proc parseWhile(p: var TPasParser): PNode =
skipCom(p, result) skipCom(p, result)
addSon(result, parseStmt(p)) addSon(result, parseStmt(p))
proc parseRepeat(p: var TPasParser): PNode = proc parseRepeat(p: var TParser): PNode =
result = newNodeP(nkWhileStmt, p) result = newNodeP(nkWhileStmt, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -746,7 +739,7 @@ proc parseRepeat(p: var TPasParser): PNode =
addSon(s, a) addSon(s, a)
addSon(result, s) addSon(result, s)
proc parseCase(p: var TPasParser): PNode = proc parseCase(p: var TParser): PNode =
var b: PNode var b: PNode
result = newNodeP(nkCaseStmt, p) result = newNodeP(nkCaseStmt, p)
getTok(p) getTok(p)
@ -770,7 +763,7 @@ proc parseCase(p: var TPasParser): PNode =
if b.kind == nkElse: break if b.kind == nkElse: break
eat(p, pxEnd) eat(p, pxEnd)
proc parseTry(p: var TPasParser): PNode = proc parseTry(p: var TParser): PNode =
result = newNodeP(nkTryStmt, p) result = newNodeP(nkTryStmt, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -807,8 +800,7 @@ proc parseTry(p: var TPasParser): PNode =
addSon(result, e) addSon(result, e)
eat(p, pxEnd) eat(p, pxEnd)
proc parseFor(p: var TPasParser): PNode = proc parseFor(p: var TParser): PNode =
var a, b, c: PNode
result = newNodeP(nkForStmt, p) result = newNodeP(nkForStmt, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -816,9 +808,9 @@ proc parseFor(p: var TPasParser): PNode =
addSon(result, createIdentNodeP(p.tok.ident, p)) addSon(result, createIdentNodeP(p.tok.ident, p))
getTok(p) getTok(p)
eat(p, pxAsgn) eat(p, pxAsgn)
a = parseExpr(p) var a = parseExpr(p)
b = nil var b: PNode = nil
c = newNodeP(nkCall, p) var c = newNodeP(nkCall, p)
if p.tok.xkind == pxTo: if p.tok.xkind == pxTo:
addSon(c, newIdentNodeP(getIdent("countup"), p)) addSon(c, newIdentNodeP(getIdent("countup"), p))
getTok(p) getTok(p)
@ -828,7 +820,7 @@ proc parseFor(p: var TPasParser): PNode =
getTok(p) getTok(p)
b = parseExpr(p) b = parseExpr(p)
else: else:
parMessage(p, errTokenExpected, PasTokKindToStr[pxTo]) parMessage(p, errTokenExpected, TokKindToStr(pxTo))
addSon(c, a) addSon(c, a)
addSon(c, b) addSon(c, b)
eat(p, pxDo) eat(p, pxDo)
@ -836,7 +828,7 @@ proc parseFor(p: var TPasParser): PNode =
addSon(result, c) addSon(result, c)
addSon(result, parseStmt(p)) addSon(result, parseStmt(p))
proc parseParam(p: var TPasParser): PNode = proc parseParam(p: var TParser): PNode =
var a, v: PNode var a, v: PNode
result = newNodeP(nkIdentDefs, p) result = newNodeP(nkIdentDefs, p)
v = nil v = nil
@ -856,7 +848,7 @@ proc parseParam(p: var TPasParser): PNode =
of pxSymbol: a = createIdentNodeP(p.tok.ident, p) of pxSymbol: a = createIdentNodeP(p.tok.ident, p)
of pxColon, pxEof, pxParRi, pxEquals: break of pxColon, pxEof, pxParRi, pxEquals: break
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $(p.tok))
return return
getTok(p) # skip identifier getTok(p) # skip identifier
skipCom(p, a) skipCom(p, a)
@ -873,7 +865,7 @@ proc parseParam(p: var TPasParser): PNode =
else: else:
addSon(result, nil) addSon(result, nil)
if p.tok.xkind != pxEquals: if p.tok.xkind != pxEquals:
parMessage(p, errColonOrEqualsExpected, pasTokToStr(p.tok)) parMessage(p, errColonOrEqualsExpected, $(p.tok))
if p.tok.xkind == pxEquals: if p.tok.xkind == pxEquals:
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -881,7 +873,7 @@ proc parseParam(p: var TPasParser): PNode =
else: else:
addSon(result, nil) addSon(result, nil)
proc parseParamList(p: var TPasParser): PNode = proc parseParamList(p: var TParser): PNode =
var a: PNode var a: PNode
result = newNodeP(nkFormalParams, p) result = newNodeP(nkFormalParams, p)
addSon(result, nil) # return type addSon(result, nil) # return type
@ -910,16 +902,16 @@ proc parseParamList(p: var TPasParser): PNode =
skipCom(p, result) skipCom(p, result)
result.sons[0] = parseTypeDesc(p) result.sons[0] = parseTypeDesc(p)
proc parseCallingConvention(p: var TPasParser): PNode = proc parseCallingConvention(p: var TParser): PNode =
result = nil result = nil
if p.tok.xkind == pxSymbol: if p.tok.xkind == pxSymbol:
case whichKeyword(p.tok.ident) case toLower(p.tok.ident.s)
of wStdcall, wCDecl, wSafeCall, wSysCall, wInline, wFastCall: of "stdcall", "cdecl", "safecall", "syscall", "inline", "fastcall":
result = newNodeP(nkPragma, p) result = newNodeP(nkPragma, p)
addSon(result, newIdentNodeP(p.tok.ident, p)) addSon(result, newIdentNodeP(p.tok.ident, p))
getTok(p) getTok(p)
opt(p, pxSemicolon) opt(p, pxSemicolon)
of wRegister: of "register":
result = newNodeP(nkPragma, p) result = newNodeP(nkPragma, p)
addSon(result, newIdentNodeP(getIdent("fastcall"), p)) addSon(result, newIdentNodeP(getIdent("fastcall"), p))
getTok(p) getTok(p)
@ -927,20 +919,20 @@ proc parseCallingConvention(p: var TPasParser): PNode =
else: else:
nil nil
proc parseRoutineSpecifiers(p: var TPasParser, noBody: var bool): PNode = proc parseRoutineSpecifiers(p: var TParser, noBody: var bool): PNode =
var e: PNode var e: PNode
result = parseCallingConvention(p) result = parseCallingConvention(p)
noBody = false noBody = false
while p.tok.xkind == pxSymbol: while p.tok.xkind == pxSymbol:
case whichKeyword(p.tok.ident) case toLower(p.tok.ident.s)
of wAssembler, wOverload, wFar: of "assembler", "overload", "far":
getTok(p) getTok(p)
opt(p, pxSemicolon) opt(p, pxSemicolon)
of wForward: of "forward":
noBody = true noBody = true
getTok(p) getTok(p)
opt(p, pxSemicolon) opt(p, pxSemicolon)
of wImportc: of "importc":
# This is a fake for platform module. There is no ``importc`` # This is a fake for platform module. There is no ``importc``
# directive in Pascal. # directive in Pascal.
if result == nil: result = newNodeP(nkPragma, p) if result == nil: result = newNodeP(nkPragma, p)
@ -948,7 +940,7 @@ proc parseRoutineSpecifiers(p: var TPasParser, noBody: var bool): PNode =
noBody = true noBody = true
getTok(p) getTok(p)
opt(p, pxSemicolon) opt(p, pxSemicolon)
of wNoConv: of "noconv":
# This is a fake for platform module. There is no ``noconv`` # This is a fake for platform module. There is no ``noconv``
# directive in Pascal. # directive in Pascal.
if result == nil: result = newNodeP(nkPragma, p) if result == nil: result = newNodeP(nkPragma, p)
@ -956,19 +948,19 @@ proc parseRoutineSpecifiers(p: var TPasParser, noBody: var bool): PNode =
noBody = true noBody = true
getTok(p) getTok(p)
opt(p, pxSemicolon) opt(p, pxSemicolon)
of wProcVar: of "procvar":
# This is a fake for the Nimrod compiler. There is no ``procvar`` # This is a fake for the Nimrod compiler. There is no ``procvar``
# directive in Pascal. # directive in Pascal.
if result == nil: result = newNodeP(nkPragma, p) if result == nil: result = newNodeP(nkPragma, p)
addSon(result, newIdentNodeP(getIdent("procvar"), p)) addSon(result, newIdentNodeP(getIdent("procvar"), p))
getTok(p) getTok(p)
opt(p, pxSemicolon) opt(p, pxSemicolon)
of wVarargs: of "varargs":
if result == nil: result = newNodeP(nkPragma, p) if result == nil: result = newNodeP(nkPragma, p)
addSon(result, newIdentNodeP(getIdent("varargs"), p)) addSon(result, newIdentNodeP(getIdent("varargs"), p))
getTok(p) getTok(p)
opt(p, pxSemicolon) opt(p, pxSemicolon)
of wExternal: of "external":
if result == nil: result = newNodeP(nkPragma, p) if result == nil: result = newNodeP(nkPragma, p)
getTok(p) getTok(p)
noBody = true noBody = true
@ -993,7 +985,7 @@ proc parseRoutineSpecifiers(p: var TPasParser, noBody: var bool): PNode =
if result == nil: result = newNodeP(nkPragma, p) if result == nil: result = newNodeP(nkPragma, p)
addSon(result, e.sons[0]) addSon(result, e.sons[0])
proc parseRoutineType(p: var TPasParser): PNode = proc parseRoutineType(p: var TParser): PNode =
result = newNodeP(nkProcTy, p) result = newNodeP(nkProcTy, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -1002,8 +994,8 @@ proc parseRoutineType(p: var TPasParser): PNode =
addSon(result, parseCallingConvention(p)) addSon(result, parseCallingConvention(p))
skipCom(p, result) skipCom(p, result)
proc parseEnum(p: var TPasParser): PNode = proc parseEnum(p: var TParser): PNode =
var a, b: PNode var a: PNode
result = newNodeP(nkEnumTy, p) result = newNodeP(nkEnumTy, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -1013,14 +1005,14 @@ proc parseEnum(p: var TPasParser): PNode =
of pxEof, pxParRi: break of pxEof, pxParRi: break
of pxSymbol: a = newIdentNodeP(p.tok.ident, p) of pxSymbol: a = newIdentNodeP(p.tok.ident, p)
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $(p.tok))
break break
getTok(p) # skip identifier getTok(p) # skip identifier
skipCom(p, a) skipCom(p, a)
if (p.tok.xkind == pxEquals) or (p.tok.xkind == pxAsgn): if (p.tok.xkind == pxEquals) or (p.tok.xkind == pxAsgn):
getTok(p) getTok(p)
skipCom(p, a) skipCom(p, a)
b = a var b = a
a = newNodeP(nkEnumFieldDef, p) a = newNodeP(nkEnumFieldDef, p)
addSon(a, b) addSon(a, b)
addSon(a, parseExpr(p)) addSon(a, parseExpr(p))
@ -1030,7 +1022,7 @@ proc parseEnum(p: var TPasParser): PNode =
addSon(result, a) addSon(result, a)
eat(p, pxParRi) eat(p, pxParRi)
proc identVis(p: var TPasParser): PNode = proc identVis(p: var TParser): PNode =
# identifier with visability # identifier with visability
var a = createIdentNodeP(p.tok.ident, p) var a = createIdentNodeP(p.tok.ident, p)
if p.section == seInterface: if p.section == seInterface:
@ -1042,13 +1034,13 @@ proc identVis(p: var TPasParser): PNode =
getTok(p) getTok(p)
type type
TSymbolParser = proc (p: var TPasParser): PNode TSymbolParser = proc (p: var TParser): PNode
proc rawIdent(p: var TPasParser): PNode = proc rawIdent(p: var TParser): PNode =
result = createIdentNodeP(p.tok.ident, p) result = createIdentNodeP(p.tok.ident, p)
getTok(p) getTok(p)
proc parseIdentColonEquals(p: var TPasParser, proc parseIdentColonEquals(p: var TParser,
identParser: TSymbolParser): PNode = identParser: TSymbolParser): PNode =
var a: PNode var a: PNode
result = newNodeP(nkIdentDefs, p) result = newNodeP(nkIdentDefs, p)
@ -1057,7 +1049,7 @@ proc parseIdentColonEquals(p: var TPasParser,
of pxSymbol: a = identParser(p) of pxSymbol: a = identParser(p)
of pxColon, pxEof, pxParRi, pxEquals: break of pxColon, pxEof, pxParRi, pxEquals: break
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $(p.tok))
return return
skipCom(p, a) skipCom(p, a)
if p.tok.xkind == pxComma: if p.tok.xkind == pxComma:
@ -1071,7 +1063,7 @@ proc parseIdentColonEquals(p: var TPasParser,
else: else:
addSon(result, nil) addSon(result, nil)
if p.tok.xkind != pxEquals: if p.tok.xkind != pxEquals:
parMessage(p, errColonOrEqualsExpected, pasTokToStr(p.tok)) parMessage(p, errColonOrEqualsExpected, $(p.tok))
if p.tok.xkind == pxEquals: if p.tok.xkind == pxEquals:
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -1082,7 +1074,7 @@ proc parseIdentColonEquals(p: var TPasParser,
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
proc parseRecordCase(p: var TPasParser): PNode = proc parseRecordCase(p: var TParser): PNode =
var a, b, c: PNode var a, b, c: PNode
result = newNodeP(nkRecCase, p) result = newNodeP(nkRecCase, p)
getTok(p) getTok(p)
@ -1123,7 +1115,7 @@ proc parseRecordCase(p: var TPasParser): PNode =
addSon(result, b) addSon(result, b)
if b.kind == nkElse: break if b.kind == nkElse: break
proc parseRecordPart(p: var TPasParser): PNode = proc parseRecordPart(p: var TParser): PNode =
result = nil result = nil
while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd): while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd):
if result == nil: result = newNodeP(nkRecList, p) if result == nil: result = newNodeP(nkRecList, p)
@ -1137,7 +1129,7 @@ proc parseRecordPart(p: var TPasParser): PNode =
of pxComment: of pxComment:
skipCom(p, lastSon(result)) skipCom(p, lastSon(result))
else: else:
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok)) parMessage(p, errIdentifierExpected, $(p.tok))
break break
proc exSymbol(n: var PNode) = proc exSymbol(n: var PNode) =
@ -1182,7 +1174,7 @@ proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
InternalError(ident.info, "addPragmaToIdent") InternalError(ident.info, "addPragmaToIdent")
addSon(pragmasNode, pragma) addSon(pragmasNode, pragma)
proc parseRecordBody(p: var TPasParser, result, definition: PNode) = proc parseRecordBody(p: var TParser, result, definition: PNode) =
skipCom(p, result) skipCom(p, result)
var a = parseRecordPart(p) var a = parseRecordPart(p)
if result.kind != nkTupleTy: fixRecordDef(a) if result.kind != nkTupleTy: fixRecordDef(a)
@ -1206,7 +1198,7 @@ proc parseRecordBody(p: var TPasParser, result, definition: PNode) =
opt(p, pxSemicolon) opt(p, pxSemicolon)
skipCom(p, result) skipCom(p, result)
proc parseRecordOrObject(p: var TPasParser, kind: TNodeKind, proc parseRecordOrObject(p: var TParser, kind: TNodeKind,
definition: PNode): PNode = definition: PNode): PNode =
result = newNodeP(kind, p) result = newNodeP(kind, p)
getTok(p) getTok(p)
@ -1221,7 +1213,7 @@ proc parseRecordOrObject(p: var TPasParser, kind: TNodeKind,
addSon(result, nil) addSon(result, nil)
parseRecordBody(p, result, definition) parseRecordBody(p, result, definition)
proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode = proc parseTypeDesc(p: var TParser, definition: PNode = nil): PNode =
var oldcontext = p.context var oldcontext = p.context
p.context = conTypeDesc p.context = conTypeDesc
if p.tok.xkind == pxPacked: getTok(p) if p.tok.xkind == pxPacked: getTok(p)
@ -1273,7 +1265,7 @@ proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode =
of pxHat: of pxHat:
getTok(p) getTok(p)
if p.tok.xkind == pxCommand: result = parseCommand(p) if p.tok.xkind == pxCommand: result = parseCommand(p)
elif gCmd == cmdBoot: result = newNodeP(nkRefTy, p) elif pfRefs in p.flags: result = newNodeP(nkRefTy, p)
else: result = newNodeP(nkPtrTy, p) else: result = newNodeP(nkPtrTy, p)
addSon(result, parseTypeDesc(p)) addSon(result, parseTypeDesc(p))
of pxType: of pxType:
@ -1293,7 +1285,7 @@ proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode =
result = a result = a
p.context = oldcontext p.context = oldcontext
proc parseTypeDef(p: var TPasParser): PNode = proc parseTypeDef(p: var TParser): PNode =
result = newNodeP(nkTypeDef, p) result = newNodeP(nkTypeDef, p)
addSon(result, identVis(p)) addSon(result, identVis(p))
addSon(result, nil) # generic params addSon(result, nil) # generic params
@ -1307,14 +1299,14 @@ proc parseTypeDef(p: var TPasParser): PNode =
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
proc parseTypeSection(p: var TPasParser): PNode = proc parseTypeSection(p: var TParser): PNode =
result = newNodeP(nkTypeSection, p) result = newNodeP(nkTypeSection, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
while p.tok.xkind == pxSymbol: while p.tok.xkind == pxSymbol:
addSon(result, parseTypeDef(p)) addSon(result, parseTypeDef(p))
proc parseConstant(p: var TPasParser): PNode = proc parseConstant(p: var TParser): PNode =
result = newNodeP(nkConstDef, p) result = newNodeP(nkConstDef, p)
addSon(result, identVis(p)) addSon(result, identVis(p))
if p.tok.xkind == pxColon: if p.tok.xkind == pxColon:
@ -1324,7 +1316,7 @@ proc parseConstant(p: var TPasParser): PNode =
else: else:
addSon(result, nil) addSon(result, nil)
if p.tok.xkind != pxEquals: if p.tok.xkind != pxEquals:
parMessage(p, errColonOrEqualsExpected, pasTokToStr(p.tok)) parMessage(p, errColonOrEqualsExpected, $(p.tok))
if p.tok.xkind == pxEquals: if p.tok.xkind == pxEquals:
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -1335,14 +1327,14 @@ proc parseConstant(p: var TPasParser): PNode =
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
proc parseConstSection(p: var TPasParser): PNode = proc parseConstSection(p: var TParser): PNode =
result = newNodeP(nkConstSection, p) result = newNodeP(nkConstSection, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
while p.tok.xkind == pxSymbol: while p.tok.xkind == pxSymbol:
addSon(result, parseConstant(p)) addSon(result, parseConstant(p))
proc parseVar(p: var TPasParser): PNode = proc parseVar(p: var TParser): PNode =
result = newNodeP(nkVarSection, p) result = newNodeP(nkVarSection, p)
getTok(p) getTok(p)
skipCom(p, result) skipCom(p, result)
@ -1350,7 +1342,7 @@ proc parseVar(p: var TPasParser): PNode =
addSon(result, parseIdentColonEquals(p, identVis)) addSon(result, parseIdentColonEquals(p, identVis))
p.lastVarSection = result p.lastVarSection = result
proc parseRoutine(p: var TPasParser): PNode = proc parseRoutine(p: var TParser): PNode =
var var
stmts: PNode stmts: PNode
noBody: bool noBody: bool
@ -1381,7 +1373,7 @@ proc parseRoutine(p: var TPasParser): PNode =
for i in countup(0, sonsLen(a) - 1): addSon(stmts, a.sons[i]) for i in countup(0, sonsLen(a) - 1): addSon(stmts, a.sons[i])
addSon(result, stmts) addSon(result, stmts)
proc fixExit(p: var TPasParser, n: PNode): bool = proc fixExit(p: var TParser, n: PNode): bool =
result = false result = false
if (p.tok.ident.id == getIdent("exit").id): if (p.tok.ident.id == getIdent("exit").id):
var length = sonsLen(n) var length = sonsLen(n)
@ -1396,7 +1388,7 @@ proc fixExit(p: var TPasParser, n: PNode): bool =
opt(p, pxSemicolon) opt(p, pxSemicolon)
skipCom(p, a) skipCom(p, a)
proc fixVarSection(p: var TPasParser, counter: PNode) = proc fixVarSection(p: var TParser, counter: PNode) =
if p.lastVarSection == nil: return if p.lastVarSection == nil: return
assert(counter.kind == nkIdent) assert(counter.kind == nkIdent)
for i in countup(0, sonsLen(p.lastVarSection) - 1): for i in countup(0, sonsLen(p.lastVarSection) - 1):
@ -1408,7 +1400,23 @@ proc fixVarSection(p: var TPasParser, counter: PNode) =
delSon(p.lastVarSection, i) delSon(p.lastVarSection, i)
return return
proc parseBegin(p: var TPasParser, result: PNode) = proc exSymbols(n: PNode) =
case n.kind
of nkEmpty..nkNilLit: nil
of nkProcDef..nkIteratorDef: exSymbol(n.sons[namePos])
of nkWhenStmt, nkStmtList:
for i in countup(0, sonsLen(n) - 1): exSymbols(n.sons[i])
of nkVarSection, nkConstSection:
for i in countup(0, sonsLen(n) - 1): exSymbol(n.sons[i].sons[0])
of nkTypeSection:
for i in countup(0, sonsLen(n) - 1):
exSymbol(n.sons[i].sons[0])
if (n.sons[i].sons[2] != nil) and
(n.sons[i].sons[2].kind == nkObjectTy):
fixRecordDef(n.sons[i].sons[2])
else: nil
proc parseBegin(p: var TParser, result: PNode) =
getTok(p) getTok(p)
while true: while true:
case p.tok.xkind case p.tok.xkind
@ -1423,7 +1431,7 @@ proc parseBegin(p: var TPasParser, result: PNode) =
else: addSonIfNotNil(result, parseStmt(p)) else: addSonIfNotNil(result, parseStmt(p))
if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p)) if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p))
proc parseStmt(p: var TPasParser): PNode = proc parseStmt(p: var TParser): PNode =
var oldcontext = p.context var oldcontext = p.context
p.context = conStmt p.context = conStmt
result = nil result = nil
@ -1489,7 +1497,7 @@ proc parseStmt(p: var TPasParser): PNode =
if result != nil: skipCom(p, result) if result != nil: skipCom(p, result)
p.context = oldcontext p.context = oldcontext
proc parseUnit(p: var TPasParser): PNode = proc parseUnit(p: var TParser): PNode =
result = newNodeP(nkStmtList, p) result = newNodeP(nkStmtList, p)
getTok(p) # read first token getTok(p) # read first token
while true: while true: