mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-07 12:24:19 +00:00
strutils.parseHexInt added
This commit is contained in:
@@ -15,7 +15,6 @@ cc = gcc
|
||||
@end
|
||||
|
||||
path="$lib/pure"
|
||||
path="$lib/devel"
|
||||
path="$lib/impure"
|
||||
path="$lib/wrappers"
|
||||
path="$lib/wrappers/cairo"
|
||||
|
||||
@@ -326,6 +326,10 @@ proc ParseFloat*(s: string): float {.noSideEffect, procvar.}
|
||||
## a valid floating point number, `EInvalidValue` is raised. ``NAN``,
|
||||
## ``INF``, ``-INF`` are also supported (case insensitive comparison).
|
||||
|
||||
proc ParseHexInt*(s: string): int {.noSideEffect, procvar.}
|
||||
## Parses a hexadecimal integer value contained in `s`. If `s` is not
|
||||
## a valid integer, `EInvalidValue` is raised.
|
||||
|
||||
# the stringify and format operators:
|
||||
proc toString*[Ty](x: Ty): string {.deprecated.}
|
||||
## This generic proc is the same as the stringify operator `$`.
|
||||
@@ -731,6 +735,25 @@ proc ParseBiggestInt(s: string): biggestInt =
|
||||
if index == -1:
|
||||
raise newException(EInvalidValue, "invalid integer: " & s)
|
||||
|
||||
|
||||
proc ParseHexInt(s: string): int =
|
||||
var i = 0
|
||||
if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2)
|
||||
while true:
|
||||
case s[i]
|
||||
of '_': inc(i)
|
||||
of '0'..'9':
|
||||
result = result shl 4 or (ord(s[i]) - ord('0'))
|
||||
inc(i)
|
||||
of 'a'..'f':
|
||||
result = result shl 4 or (ord(s[i]) - ord('a') + 10)
|
||||
inc(i)
|
||||
of 'A'..'F':
|
||||
result = result shl 4 or (ord(s[i]) - ord('A') + 10)
|
||||
inc(i)
|
||||
of '\0': break
|
||||
else: raise newException(EInvalidValue, "invalid integer: " & s)
|
||||
|
||||
proc ParseFloat(s: string): float =
|
||||
var
|
||||
esign = 1.0
|
||||
|
||||
@@ -232,7 +232,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) =
|
||||
of wPath, wP:
|
||||
expectArg(switch, arg, pass, info)
|
||||
path = processPath(arg)
|
||||
discard lists.IncludeStr(options.searchPaths, path)
|
||||
if not contains(options.searchPaths, path):
|
||||
lists.PrependStr(options.searchPaths, path)
|
||||
#discard lists.IncludeStr(options.searchPaths, path)
|
||||
of wOut, wO:
|
||||
expectArg(switch, arg, pass, info)
|
||||
options.outFile = arg
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2008 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -60,15 +60,16 @@ proc AppendStr(list: var TLinkedList, data: string) =
|
||||
proc PrependStr(list: var TLinkedList, data: string) =
|
||||
prepend(list, newStrEntry(data))
|
||||
|
||||
proc IncludeStr(list: var TLinkedList, data: string): bool =
|
||||
var it: PListEntry
|
||||
it = list.head
|
||||
proc Contains*(list: TLinkedList, data: string): bool =
|
||||
var it = list.head
|
||||
while it != nil:
|
||||
if PStrEntry(it).data == data:
|
||||
return true # already in list
|
||||
return true
|
||||
it = it.next
|
||||
|
||||
proc IncludeStr(list: var TLinkedList, data: string): bool =
|
||||
if Contains(list, data): return true
|
||||
AppendStr(list, data) # else: add to list
|
||||
result = false
|
||||
|
||||
proc InsertBefore(list: var TLinkedList, pos, entry: PListEntry) =
|
||||
assert(pos != nil)
|
||||
|
||||
65
rod/main.nim
65
rod/main.nim
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
import
|
||||
llstream, strutils, ast, astalgo, scanner, syntaxes, rnimsyn, options, msgs,
|
||||
os, lists, condsyms, paslex, pasparse, rodread, rodwrite, ropes, trees,
|
||||
os, lists, condsyms, rodread, rodwrite, ropes, trees,
|
||||
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
||||
cgen, ecmasgen,
|
||||
platform, interact, nimconf, importer, passaux, depends, transf, evals, types
|
||||
@@ -47,7 +47,6 @@ proc getModule(filename: string): PSym =
|
||||
for i in countup(0, high(compMods)):
|
||||
if sameFile(compMods[i].filename, filename):
|
||||
return compMods[i].module
|
||||
result = nil
|
||||
|
||||
proc newModule(filename: string): PSym =
|
||||
# We cannot call ``newSym`` here, because we have to circumvent the ID
|
||||
@@ -152,61 +151,11 @@ proc CommandInteractive() =
|
||||
incl(m.flags, sfMainModule)
|
||||
processModule(m, "stdin", LLStreamOpenStdIn(), nil)
|
||||
|
||||
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 CommandExportSymbols(filename: string) =
|
||||
# now unused!
|
||||
var module = parseFile(addFileExt(filename, NimExt))
|
||||
if module != nil:
|
||||
exSymbols(module)
|
||||
renderModule(module, getOutFile(filename, "pretty." & NimExt))
|
||||
|
||||
proc CommandPretty(filename: string) =
|
||||
var module = parseFile(addFileExt(filename, NimExt))
|
||||
if module != nil:
|
||||
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)
|
||||
closePasParser(p)
|
||||
renderModule(module, getOutFile(filename, NimExt))
|
||||
else:
|
||||
rawMessage(errCannotOpenFile, f)
|
||||
|
||||
proc CommandScan(filename: string) =
|
||||
var f = addFileExt(filename, nimExt)
|
||||
var stream = LLStreamOpen(f, fmRead)
|
||||
@@ -274,14 +223,6 @@ proc MainCommand(cmd, filename: string) =
|
||||
LoadSpecialConfig(DocTexConfig)
|
||||
wantFile(filename)
|
||||
CommandRst2TeX(filename)
|
||||
of wPas:
|
||||
gCmd = cmdPas
|
||||
wantFile(filename)
|
||||
CommandPas(filename)
|
||||
of wBoot:
|
||||
gCmd = cmdBoot
|
||||
wantFile(filename)
|
||||
CommandPas(filename)
|
||||
of wGenDepend:
|
||||
gCmd = cmdGenDepend
|
||||
wantFile(filename)
|
||||
@@ -306,4 +247,4 @@ proc MainCommand(cmd, filename: string) =
|
||||
gCmd = cmdInteractive
|
||||
CommandInteractive()
|
||||
else: rawMessage(errInvalidCommandX, cmd)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -41,7 +41,7 @@ type # please make sure we have under 32 options
|
||||
TGlobalOptions* = set[TGlobalOption]
|
||||
TCommands* = enum # Nimrod's commands
|
||||
cmdNone, cmdCompileToC, cmdCompileToCpp, cmdCompileToEcmaScript,
|
||||
cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc, cmdPas, cmdBoot,
|
||||
cmdCompileToLLVM, cmdInterpret, cmdPretty, cmdDoc,
|
||||
cmdGenDepend, cmdListDef, cmdCheck, # semantic checking for whole project
|
||||
cmdParse, # parse a single file (for debugging)
|
||||
cmdScan, # scan a single file (for debugging)
|
||||
|
||||
67
rod/pas2nim/pas2nim.nim
Executable file
67
rod/pas2nim/pas2nim.nim
Executable file
@@ -0,0 +1,67 @@
|
||||
#
|
||||
#
|
||||
# Pas2nim - Pascal to Nimrod source converter
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
#
|
||||
|
||||
import
|
||||
llstream, strutils, os, ast, rnimsyn, options, msgs,
|
||||
paslex, pasparse
|
||||
|
||||
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 CommandExportSymbols(filename: string) =
|
||||
# now unused!
|
||||
var module = parseFile(addFileExt(filename, NimExt))
|
||||
if module != nil:
|
||||
exSymbols(module)
|
||||
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)
|
||||
closePasParser(p)
|
||||
renderModule(module, getOutFile(filename, NimExt))
|
||||
else:
|
||||
rawMessage(errCannotOpenFile, f)
|
||||
|
||||
|
||||
|
||||
@@ -1,44 +1,31 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# Pas2nim - Pascal to Nimrod source converter
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
# This module implements a FreePascal scanner. This is a adaption from
|
||||
# This module implements a FreePascal scanner. This is an adaption from
|
||||
# the scanner module.
|
||||
|
||||
import
|
||||
nhashes, options, msgs, strutils, platform, idents, lexbase, wordrecg, scanner
|
||||
nhashes, options, msgs, strutils, platform, idents, lexbase
|
||||
|
||||
const
|
||||
MaxLineLength* = 80 # lines longer than this lead to a warning
|
||||
numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'} # we support up to base 36
|
||||
numChars*: TCharSet = {'0'..'9', 'a'..'z', 'A'..'Z'}
|
||||
SymChars*: TCharSet = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'}
|
||||
SymStartChars*: TCharSet = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
|
||||
OpChars*: TCharSet = {'+', '-', '*', '/', '<', '>', '!', '?', '^', '.', '|',
|
||||
'=', ':', '%', '&', '$', '@', '~', '\x80'..'\xFF'}
|
||||
|
||||
type # order is important for TPasTokKind
|
||||
# keywords are sorted!
|
||||
|
||||
type
|
||||
TPasTokKind* = enum
|
||||
pxInvalid, pxEof, # keywords:
|
||||
#[[[cog
|
||||
#from string import capitalize
|
||||
#keywords = eval(open("data/pas_keyw.yml").read())
|
||||
#idents = ""
|
||||
#strings = ""
|
||||
#i = 1
|
||||
#for k in keywords:
|
||||
# idents = idents + "px" + capitalize(k) + ", "
|
||||
# strings = strings + "'" + k + "', "
|
||||
# if i % 4 == 0:
|
||||
# idents = idents + "\n"
|
||||
# strings = strings + "\n"
|
||||
# i = i + 1
|
||||
#cog.out(idents)
|
||||
#]]]
|
||||
pxInvalid, pxEof,
|
||||
pxAnd, pxArray, pxAs, pxAsm, pxBegin, pxCase, pxClass, pxConst,
|
||||
pxConstructor, pxDestructor, pxDiv, pxDo, pxDownto, pxElse, pxEnd, pxExcept,
|
||||
pxExports, pxFinalization, pxFinally, pxFor, pxFunction, pxGoto, pxIf,
|
||||
@@ -47,13 +34,13 @@ type # order is important for TPasTokKind
|
||||
pxOr, pxOut, pxPacked, pxProcedure, pxProgram, pxProperty, pxRaise,
|
||||
pxRecord, pxRepeat, pxResourcestring, pxSet, pxShl, pxShr, pxThen,
|
||||
pxThreadvar, pxTo, pxTry, pxType, pxUnit, pxUntil, pxUses, pxVar, pxWhile,
|
||||
pxWith, pxXor, #[[[end]]]
|
||||
pxWith, pxXor,
|
||||
pxComment, # ordinary comment
|
||||
pxCommand, # {@}
|
||||
pxAmp, # {&}
|
||||
pxPer, # {%}
|
||||
pxStrLit, pxSymbol, # a symbol
|
||||
pxIntLit, pxInt64Lit, # long constant like 0x00000070fffffff or out of int range
|
||||
pxIntLit, pxInt64Lit, # long constant like 0x70fffffff or out of int range
|
||||
pxFloatLit, pxParLe, pxParRi, pxBracketLe, pxBracketRi, pxComma,
|
||||
pxSemiColon, pxColon, # operators
|
||||
pxAsgn, pxEquals, pxDot, pxDotDot, pxHat, pxPlus, pxMinus, pxStar, pxSlash,
|
||||
@@ -62,10 +49,7 @@ type # order is important for TPasTokKind
|
||||
TPasTokKinds* = set[TPasTokKind]
|
||||
|
||||
const
|
||||
PasTokKindToStr*: array[TPasTokKind, string] = ["pxInvalid", "[EOF]", #[[[cog
|
||||
#cog.out(strings)
|
||||
#]]]
|
||||
"and", "array", "as", "asm", "begin", "case", "class", "const",
|
||||
Keywords = ["and", "array", "as", "asm", "begin", "case", "class", "const",
|
||||
"constructor", "destructor", "div", "do", "downto", "else", "end", "except",
|
||||
"exports", "finalization", "finally", "for", "function", "goto", "if",
|
||||
"implementation", "in", "inherited", "initialization", "inline",
|
||||
@@ -73,23 +57,74 @@ const
|
||||
"or", "out", "packed", "procedure", "program", "property", "raise",
|
||||
"record", "repeat", "resourcestring", "set", "shl", "shr", "then",
|
||||
"threadvar", "to", "try", "type", "unit", "until", "uses", "var", "while",
|
||||
"with", "xor", #[[[end]]]
|
||||
"pxComment", "pxCommand", "{&}", "{%}", "pxStrLit", "[IDENTIFIER]",
|
||||
"pxIntLit", "pxInt64Lit", "pxFloatLit", "(", ")", "[", "]", ",", ";", ":",
|
||||
":=", "=", ".", "..", "^", "+", "-", "*", "/", "<=", "<", ">=", ">", "<>",
|
||||
"@", "(*$", "*)", "{$", "}"]
|
||||
"with", "xor"]
|
||||
|
||||
firstKeyword = pxAnd
|
||||
lastKeyword = pxXor
|
||||
|
||||
type
|
||||
TPasTok* = object of TToken # a Pascal token
|
||||
TPasTok* = object
|
||||
xkind*: TPasTokKind # the type of the token
|
||||
ident*: PIdent # the parsed identifier
|
||||
iNumber*: BiggestInt # the parsed integer literal
|
||||
fNumber*: BiggestFloat # the parsed floating point literal
|
||||
base*: TNumericalBase # the numerical base; only valid for int
|
||||
# or float literals
|
||||
literal*: string # the parsed (string) literal
|
||||
|
||||
TPasLex* = object
|
||||
filename*: string
|
||||
|
||||
TPasLex* = object of TLexer
|
||||
|
||||
proc getPasTok*(L: var TPasLex, tok: var TPasTok)
|
||||
proc PrintPasTok*(tok: TPasTok)
|
||||
proc pasTokToStr*(tok: TPasTok): string
|
||||
# implementation
|
||||
|
||||
var dummyIdent: PIdent
|
||||
|
||||
proc fillToken(L: var TToken) =
|
||||
L.TokType = tkInvalid
|
||||
L.iNumber = 0
|
||||
L.Indent = 0
|
||||
L.literal = ""
|
||||
L.fNumber = 0.0
|
||||
L.base = base10
|
||||
L.ident = dummyIdent # this prevents many bugs!
|
||||
|
||||
proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) =
|
||||
openBaseLexer(lex, inputstream)
|
||||
lex.indentStack = @[0]
|
||||
lex.filename = filename
|
||||
lex.indentAhead = - 1
|
||||
|
||||
proc closeLexer(lex: var TLexer) =
|
||||
inc(gLinesCompiled, lex.LineNumber)
|
||||
closeBaseLexer(lex)
|
||||
|
||||
proc getColumn(L: TLexer): int =
|
||||
result = getColNumber(L, L.bufPos)
|
||||
|
||||
proc getLineInfo(L: TLexer): TLineInfo =
|
||||
result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos))
|
||||
|
||||
proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") =
|
||||
msgs.liMessage(getLineInfo(L), msg, arg)
|
||||
|
||||
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
|
||||
var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart)
|
||||
msgs.liMessage(info, msg, arg)
|
||||
|
||||
proc binaryStrSearch(x: openarray[string], y: string): int =
|
||||
var a = 0
|
||||
var b = len(x)
|
||||
while a < b:
|
||||
var mid = (a + b) div 2
|
||||
if x[mid] < y: a = mid + 1
|
||||
else: b = mid
|
||||
if a < len(x) and x[a] == y: result = a
|
||||
else: result = -1
|
||||
|
||||
proc pastokToStr(tok: TPasTok): string =
|
||||
case tok.xkind
|
||||
of pxIntLit, pxInt64Lit: result = $(tok.iNumber)
|
||||
@@ -105,144 +140,14 @@ proc PrintPasTok(tok: TPasTok) =
|
||||
writeln(stdout, pastokToStr(tok))
|
||||
|
||||
proc setKeyword(L: var TPasLex, tok: var TPasTok) =
|
||||
case tok.ident.id #[[[cog
|
||||
#for k in keywords:
|
||||
# m = capitalize(k)
|
||||
# cog.outl("ord(w%s):%s tok.xkind := px%s;" % (m, ' '*(18-len(m)), m))
|
||||
#]]]
|
||||
of ord(wAnd):
|
||||
tok.xkind = pxAnd
|
||||
of ord(wArray):
|
||||
tok.xkind = pxArray
|
||||
of ord(wAs):
|
||||
tok.xkind = pxAs
|
||||
of ord(wAsm):
|
||||
tok.xkind = pxAsm
|
||||
of ord(wBegin):
|
||||
tok.xkind = pxBegin
|
||||
of ord(wCase):
|
||||
tok.xkind = pxCase
|
||||
of ord(wClass):
|
||||
tok.xkind = pxClass
|
||||
of ord(wConst):
|
||||
tok.xkind = pxConst
|
||||
of ord(wConstructor):
|
||||
tok.xkind = pxConstructor
|
||||
of ord(wDestructor):
|
||||
tok.xkind = pxDestructor
|
||||
of ord(wDiv):
|
||||
tok.xkind = pxDiv
|
||||
of ord(wDo):
|
||||
tok.xkind = pxDo
|
||||
of ord(wDownto):
|
||||
tok.xkind = pxDownto
|
||||
of ord(wElse):
|
||||
tok.xkind = pxElse
|
||||
of ord(wEnd):
|
||||
tok.xkind = pxEnd
|
||||
of ord(wExcept):
|
||||
tok.xkind = pxExcept
|
||||
of ord(wExports):
|
||||
tok.xkind = pxExports
|
||||
of ord(wFinalization):
|
||||
tok.xkind = pxFinalization
|
||||
of ord(wFinally):
|
||||
tok.xkind = pxFinally
|
||||
of ord(wFor):
|
||||
tok.xkind = pxFor
|
||||
of ord(wFunction):
|
||||
tok.xkind = pxFunction
|
||||
of ord(wGoto):
|
||||
tok.xkind = pxGoto
|
||||
of ord(wIf):
|
||||
tok.xkind = pxIf
|
||||
of ord(wImplementation):
|
||||
tok.xkind = pxImplementation
|
||||
of ord(wIn):
|
||||
tok.xkind = pxIn
|
||||
of ord(wInherited):
|
||||
tok.xkind = pxInherited
|
||||
of ord(wInitialization):
|
||||
tok.xkind = pxInitialization
|
||||
of ord(wInline):
|
||||
tok.xkind = pxInline
|
||||
of ord(wInterface):
|
||||
tok.xkind = pxInterface
|
||||
of ord(wIs):
|
||||
tok.xkind = pxIs
|
||||
of ord(wLabel):
|
||||
tok.xkind = pxLabel
|
||||
of ord(wLibrary):
|
||||
tok.xkind = pxLibrary
|
||||
of ord(wMod):
|
||||
tok.xkind = pxMod
|
||||
of ord(wNil):
|
||||
tok.xkind = pxNil
|
||||
of ord(wNot):
|
||||
tok.xkind = pxNot
|
||||
of ord(wObject):
|
||||
tok.xkind = pxObject
|
||||
of ord(wOf):
|
||||
tok.xkind = pxOf
|
||||
of ord(wOr):
|
||||
tok.xkind = pxOr
|
||||
of ord(wOut):
|
||||
tok.xkind = pxOut
|
||||
of ord(wPacked):
|
||||
tok.xkind = pxPacked
|
||||
of ord(wProcedure):
|
||||
tok.xkind = pxProcedure
|
||||
of ord(wProgram):
|
||||
tok.xkind = pxProgram
|
||||
of ord(wProperty):
|
||||
tok.xkind = pxProperty
|
||||
of ord(wRaise):
|
||||
tok.xkind = pxRaise
|
||||
of ord(wRecord):
|
||||
tok.xkind = pxRecord
|
||||
of ord(wRepeat):
|
||||
tok.xkind = pxRepeat
|
||||
of ord(wResourcestring):
|
||||
tok.xkind = pxResourcestring
|
||||
of ord(wSet):
|
||||
tok.xkind = pxSet
|
||||
of ord(wShl):
|
||||
tok.xkind = pxShl
|
||||
of ord(wShr):
|
||||
tok.xkind = pxShr
|
||||
of ord(wThen):
|
||||
tok.xkind = pxThen
|
||||
of ord(wThreadvar):
|
||||
tok.xkind = pxThreadvar
|
||||
of ord(wTo):
|
||||
tok.xkind = pxTo
|
||||
of ord(wTry):
|
||||
tok.xkind = pxTry
|
||||
of ord(wType):
|
||||
tok.xkind = pxType
|
||||
of ord(wUnit):
|
||||
tok.xkind = pxUnit
|
||||
of ord(wUntil):
|
||||
tok.xkind = pxUntil
|
||||
of ord(wUses):
|
||||
tok.xkind = pxUses
|
||||
of ord(wVar):
|
||||
tok.xkind = pxVar
|
||||
of ord(wWhile):
|
||||
tok.xkind = pxWhile
|
||||
of ord(wWith):
|
||||
tok.xkind = pxWith
|
||||
of ord(wXor):
|
||||
tok.xkind = pxXor #[[[end]]]
|
||||
else: tok.xkind = pxSymbol
|
||||
var x = binaryStrSearch(keywords, toLower(tok.ident.s))
|
||||
if x < 0: tok.xkind = pxSymbol
|
||||
else: tok.xKind = TPasTokKind(x + ord(firstKeyword))
|
||||
|
||||
proc matchUnderscoreChars(L: var TPasLex, tok: var TPasTok, chars: TCharSet) =
|
||||
# matches ([chars]_)*
|
||||
var
|
||||
pos: int
|
||||
buf: cstring
|
||||
pos = L.bufpos # use registers for pos, buf
|
||||
buf = L.buf
|
||||
var pos = L.bufpos # use registers for pos, buf
|
||||
var buf = L.buf
|
||||
while true:
|
||||
if buf[pos] in chars:
|
||||
add(tok.literal, buf[pos])
|
||||
@@ -255,16 +160,12 @@ proc matchUnderscoreChars(L: var TPasLex, tok: var TPasTok, chars: TCharSet) =
|
||||
L.bufPos = pos
|
||||
|
||||
proc isFloatLiteral(s: string): bool =
|
||||
for i in countup(0, len(s) + 0 - 1):
|
||||
for i in countup(0, len(s)-1):
|
||||
if s[i] in {'.', 'e', 'E'}:
|
||||
return true
|
||||
result = false
|
||||
|
||||
proc getNumber2(L: var TPasLex, tok: var TPasTok) =
|
||||
var
|
||||
pos, bits: int
|
||||
xi: biggestInt
|
||||
pos = L.bufpos + 1 # skip %
|
||||
var pos = L.bufpos + 1 # skip %
|
||||
if not (L.buf[pos] in {'0'..'1'}):
|
||||
# BUGFIX for %date%
|
||||
tok.xkind = pxInvalid
|
||||
@@ -272,8 +173,8 @@ proc getNumber2(L: var TPasLex, tok: var TPasTok) =
|
||||
inc(L.bufpos)
|
||||
return
|
||||
tok.base = base2
|
||||
xi = 0
|
||||
bits = 0
|
||||
var xi: biggestInt = 0
|
||||
var bits = 0
|
||||
while true:
|
||||
case L.buf[pos]
|
||||
of 'A'..'Z', 'a'..'z', '2'..'9', '.':
|
||||
@@ -287,27 +188,21 @@ proc getNumber2(L: var TPasLex, tok: var TPasTok) =
|
||||
inc(bits)
|
||||
else: break
|
||||
tok.iNumber = xi
|
||||
if (bits > 32):
|
||||
tok.xkind = pxInt64Lit
|
||||
else:
|
||||
tok.xkind = pxIntLit
|
||||
if (bits > 32): tok.xkind = pxInt64Lit
|
||||
else: tok.xkind = pxIntLit
|
||||
L.bufpos = pos
|
||||
|
||||
proc getNumber16(L: var TPasLex, tok: var TPasTok) =
|
||||
var
|
||||
pos, bits: int
|
||||
xi: biggestInt
|
||||
pos = L.bufpos + 1 # skip $
|
||||
var pos = L.bufpos + 1 # skip $
|
||||
tok.base = base16
|
||||
xi = 0
|
||||
bits = 0
|
||||
var xi: biggestInt = 0
|
||||
var bits = 0
|
||||
while true:
|
||||
case L.buf[pos]
|
||||
of 'G'..'Z', 'g'..'z', '.':
|
||||
lexMessage(L, errInvalidNumber)
|
||||
inc(pos)
|
||||
of '_':
|
||||
inc(pos)
|
||||
of '_': inc(pos)
|
||||
of '0'..'9':
|
||||
xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0'))
|
||||
inc(pos)
|
||||
@@ -357,11 +252,9 @@ proc HandleCRLF(L: var TLexer, pos: int): int =
|
||||
else: result = pos
|
||||
|
||||
proc getString(L: var TPasLex, tok: var TPasTok) =
|
||||
var
|
||||
pos, xi: int
|
||||
buf: cstring
|
||||
pos = L.bufPos
|
||||
buf = L.buf
|
||||
var xi: int
|
||||
var pos = L.bufPos
|
||||
var buf = L.buf
|
||||
while true:
|
||||
if buf[pos] == '\'':
|
||||
inc(pos)
|
||||
@@ -408,16 +301,11 @@ proc getString(L: var TPasLex, tok: var TPasTok) =
|
||||
L.bufpos = pos
|
||||
|
||||
proc getSymbol(L: var TPasLex, tok: var TPasTok) =
|
||||
var
|
||||
pos: int
|
||||
c: Char
|
||||
buf: cstring
|
||||
h: THash # hashing algorithm inlined
|
||||
h = 0
|
||||
pos = L.bufpos
|
||||
buf = L.buf
|
||||
var h: THash = 0
|
||||
var pos = L.bufpos
|
||||
var buf = L.buf
|
||||
while true:
|
||||
c = buf[pos]
|
||||
var c = buf[pos]
|
||||
case c
|
||||
of 'a'..'z', '0'..'9', '\x80'..'\xFF':
|
||||
h = h +% Ord(c)
|
||||
@@ -428,8 +316,7 @@ proc getSymbol(L: var TPasLex, tok: var TPasTok) =
|
||||
h = h +% Ord(c)
|
||||
h = h +% h shl 10
|
||||
h = h xor (h shr 6)
|
||||
of '_':
|
||||
nil
|
||||
of '_': nil
|
||||
else: break
|
||||
Inc(pos)
|
||||
h = h +% h shl 3
|
||||
@@ -440,15 +327,12 @@ proc getSymbol(L: var TPasLex, tok: var TPasTok) =
|
||||
setKeyword(L, tok)
|
||||
|
||||
proc scanLineComment(L: var TPasLex, tok: var TPasTok) =
|
||||
var
|
||||
buf: cstring
|
||||
pos, col: int
|
||||
indent: int
|
||||
pos = L.bufpos
|
||||
buf = L.buf # a comment ends if the next line does not start with the // on the same
|
||||
# column after only whitespace
|
||||
var pos = L.bufpos
|
||||
var buf = L.buf
|
||||
# a comment ends if the next line does not start with the // on the same
|
||||
# column after only whitespace
|
||||
tok.xkind = pxComment
|
||||
col = getColNumber(L, pos)
|
||||
var col = getColNumber(L, pos)
|
||||
while true:
|
||||
inc(pos, 2) # skip //
|
||||
add(tok.literal, '#')
|
||||
@@ -457,7 +341,7 @@ proc scanLineComment(L: var TPasLex, tok: var TPasTok) =
|
||||
inc(pos)
|
||||
pos = handleCRLF(L, pos)
|
||||
buf = L.buf
|
||||
indent = 0
|
||||
var indent = 0
|
||||
while buf[pos] == ' ':
|
||||
inc(pos)
|
||||
inc(indent)
|
||||
@@ -468,11 +352,8 @@ proc scanLineComment(L: var TPasLex, tok: var TPasTok) =
|
||||
L.bufpos = pos
|
||||
|
||||
proc scanCurlyComment(L: var TPasLex, tok: var TPasTok) =
|
||||
var
|
||||
buf: cstring
|
||||
pos: int
|
||||
pos = L.bufpos
|
||||
buf = L.buf
|
||||
var pos = L.bufpos
|
||||
var buf = L.buf
|
||||
tok.literal = "#"
|
||||
tok.xkind = pxComment
|
||||
while true:
|
||||
@@ -480,23 +361,19 @@ proc scanCurlyComment(L: var TPasLex, tok: var TPasTok) =
|
||||
of CR, LF:
|
||||
pos = HandleCRLF(L, pos)
|
||||
buf = L.buf
|
||||
tok.literal = tok.literal & "\n" & '#'
|
||||
add(tok.literal, "\n#")
|
||||
of '}':
|
||||
inc(pos)
|
||||
break
|
||||
of lexbase.EndOfFile:
|
||||
lexMessage(L, errTokenExpected, "}")
|
||||
of lexbase.EndOfFile: lexMessage(L, errTokenExpected, "}")
|
||||
else:
|
||||
add(tok.literal, buf[pos])
|
||||
inc(pos)
|
||||
L.bufpos = pos
|
||||
|
||||
proc scanStarComment(L: var TPasLex, tok: var TPasTok) =
|
||||
var
|
||||
buf: cstring
|
||||
pos: int
|
||||
pos = L.bufpos
|
||||
buf = L.buf
|
||||
var pos = L.bufpos
|
||||
var buf = L.buf
|
||||
tok.literal = "#"
|
||||
tok.xkind = pxComment
|
||||
while true:
|
||||
@@ -504,7 +381,7 @@ proc scanStarComment(L: var TPasLex, tok: var TPasTok) =
|
||||
of CR, LF:
|
||||
pos = HandleCRLF(L, pos)
|
||||
buf = L.buf
|
||||
tok.literal = tok.literal & "\n" & '#'
|
||||
add(tok.literal, "\n#")
|
||||
of '*':
|
||||
inc(pos)
|
||||
if buf[pos] == ')':
|
||||
@@ -520,11 +397,8 @@ proc scanStarComment(L: var TPasLex, tok: var TPasTok) =
|
||||
L.bufpos = pos
|
||||
|
||||
proc skip(L: var TPasLex, tok: var TPasTok) =
|
||||
var
|
||||
buf: cstring
|
||||
pos: int
|
||||
pos = L.bufpos
|
||||
buf = L.buf
|
||||
var pos = L.bufpos
|
||||
var buf = L.buf
|
||||
while true:
|
||||
case buf[pos]
|
||||
of ' ', Tabulator:
|
||||
@@ -537,11 +411,10 @@ proc skip(L: var TPasLex, tok: var TPasTok) =
|
||||
L.bufpos = pos
|
||||
|
||||
proc getPasTok(L: var TPasLex, tok: var TPasTok) =
|
||||
var c: Char
|
||||
tok.xkind = pxInvalid
|
||||
fillToken(tok)
|
||||
skip(L, tok)
|
||||
c = L.buf[L.bufpos]
|
||||
var c = L.buf[L.bufpos]
|
||||
if c in SymStartChars:
|
||||
getSymbol(L, tok)
|
||||
elif c in {'0'..'9'}:
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# Pas2nim - Pascal to Nimrod source converter
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -9,11 +9,10 @@
|
||||
|
||||
# This module implements the parser of the Pascal variant Nimrod is written in.
|
||||
# It transfers a Pascal module into a Nimrod AST. Then the renderer can be
|
||||
# used to generate the Nimrod version of the compiler.
|
||||
# used to convert the AST to its text representation.
|
||||
|
||||
import
|
||||
os, llstream, scanner, paslex, idents, wordrecg, strutils, ast, astalgo, msgs,
|
||||
options
|
||||
os, llstream, paslex, idents, strutils, ast, astalgo, msgs, options
|
||||
|
||||
type
|
||||
TPasSection* = enum
|
||||
@@ -96,7 +95,7 @@ proc skipCom(p: var TPasParser, n: PNode) =
|
||||
while p.tok.xkind == pxComment:
|
||||
if (n != nil):
|
||||
if n.comment == nil: n.comment = p.tok.literal
|
||||
else: n.comment = n.comment & "\n" & p.tok.literal
|
||||
else: add(n.comment, "\n" & p.tok.literal)
|
||||
else:
|
||||
parMessage(p, warnCommentXIgnored, p.tok.literal)
|
||||
getTok(p)
|
||||
@@ -119,7 +118,8 @@ proc newIntNodeP(kind: TNodeKind, intVal: BiggestInt, p: TPasParser): PNode =
|
||||
result = newNodeP(kind, p)
|
||||
result.intVal = intVal
|
||||
|
||||
proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat, p: TPasParser): PNode =
|
||||
proc newFloatNodeP(kind: TNodeKind, floatVal: BiggestFloat,
|
||||
p: TPasParser): PNode =
|
||||
result = newNodeP(kind, p)
|
||||
result.floatVal = floatVal
|
||||
|
||||
@@ -132,17 +132,16 @@ proc newIdentNodeP(ident: PIdent, p: TPasParser): PNode =
|
||||
result.ident = ident
|
||||
|
||||
proc createIdentNodeP(ident: PIdent, p: TPasParser): PNode =
|
||||
var x: PIdent
|
||||
result = newNodeP(nkIdent, p)
|
||||
x = PIdent(IdTableGet(p.repl, ident))
|
||||
var x = PIdent(IdTableGet(p.repl, ident))
|
||||
if x != nil: result.ident = x
|
||||
else: result.ident = ident
|
||||
|
||||
proc parseExpr(p: var TPasParser): PNode
|
||||
proc parseStmt(p: var TPasParser): PNode
|
||||
proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode
|
||||
|
||||
proc parseEmit(p: var TPasParser, definition: PNode): PNode =
|
||||
var a: PNode
|
||||
getTok(p) # skip 'emit'
|
||||
result = nil
|
||||
if p.tok.xkind != pxCurlyDirRi:
|
||||
@@ -152,7 +151,7 @@ proc parseEmit(p: var TPasParser, definition: PNode): PNode =
|
||||
of conStmt:
|
||||
result = parseStmt(p)
|
||||
if p.tok.xkind != pxCurlyDirRi:
|
||||
a = result
|
||||
var a = result
|
||||
result = newNodeP(nkStmtList, p)
|
||||
addSon(result, a)
|
||||
while p.tok.xkind != pxCurlyDirRi:
|
||||
@@ -162,7 +161,6 @@ proc parseEmit(p: var TPasParser, definition: PNode): PNode =
|
||||
eat(p, pxCurlyDirRi)
|
||||
|
||||
proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode =
|
||||
var a: PNode
|
||||
result = nil
|
||||
getTok(p)
|
||||
if p.tok.ident.id == getIdent("discard").id:
|
||||
@@ -179,7 +177,7 @@ proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode =
|
||||
elif p.tok.ident.id == getIdent("cast").id:
|
||||
getTok(p)
|
||||
eat(p, pxCurlyDirRi)
|
||||
a = parseExpr(p)
|
||||
var a = parseExpr(p)
|
||||
if (a.kind == nkCall) and (sonsLen(a) == 2):
|
||||
result = newNodeP(nkCast, p)
|
||||
addSon(result, a.sons[0])
|
||||
@@ -230,16 +228,15 @@ proc parseCommand(p: var TPasParser, definition: PNode = nil): PNode =
|
||||
proc getPrecedence(kind: TPasTokKind): int =
|
||||
case kind
|
||||
of pxDiv, pxMod, pxStar, pxSlash, pxShl, pxShr, pxAnd:
|
||||
result = 5 # highest
|
||||
result = 5
|
||||
of pxPlus, pxMinus, pxOr, pxXor:
|
||||
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 =
|
||||
var a: PNode
|
||||
a = parseExpr(p)
|
||||
var a = parseExpr(p)
|
||||
if p.tok.xkind == pxDotDot:
|
||||
result = newNodeP(nkRange, p)
|
||||
addSon(result, a)
|
||||
@@ -250,7 +247,6 @@ proc rangeExpr(p: var TPasParser): PNode =
|
||||
result = a
|
||||
|
||||
proc bracketExprList(p: var TPasParser, first: PNode): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkBracketExpr, p)
|
||||
addSon(result, first)
|
||||
getTok(p)
|
||||
@@ -262,16 +258,16 @@ proc bracketExprList(p: var TPasParser, first: PNode): PNode =
|
||||
if p.tok.xkind == pxEof:
|
||||
parMessage(p, errTokenExpected, PasTokKindToStr[pxBracketRi])
|
||||
break
|
||||
a = rangeExpr(p)
|
||||
var a = rangeExpr(p)
|
||||
skipCom(p, a)
|
||||
if p.tok.xkind == pxComma:
|
||||
getTok(p)
|
||||
skipCom(p, a)
|
||||
addSon(result, a)
|
||||
|
||||
proc exprColonEqExpr(p: var TPasParser, kind: TNodeKind, tok: TPasTokKind): PNode =
|
||||
var a: PNode
|
||||
a = parseExpr(p)
|
||||
proc exprColonEqExpr(p: var TPasParser, kind: TNodeKind,
|
||||
tok: TPasTokKind): PNode =
|
||||
var a = parseExpr(p)
|
||||
if p.tok.xkind == tok:
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p)
|
||||
@@ -283,7 +279,6 @@ proc exprColonEqExpr(p: var TPasParser, kind: TNodeKind, tok: TPasTokKind): PNod
|
||||
|
||||
proc exprListAux(p: var TPasParser, elemKind: TNodeKind,
|
||||
endTok, sepTok: TPasTokKind, result: PNode) =
|
||||
var a: PNode
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
while true:
|
||||
@@ -293,7 +288,7 @@ proc exprListAux(p: var TPasParser, elemKind: TNodeKind,
|
||||
if p.tok.xkind == pxEof:
|
||||
parMessage(p, errTokenExpected, PasTokKindToStr[endtok])
|
||||
break
|
||||
a = exprColonEqExpr(p, elemKind, sepTok)
|
||||
var a = exprColonEqExpr(p, elemKind, sepTok)
|
||||
skipCom(p, a)
|
||||
if (p.tok.xkind == pxComma) or (p.tok.xkind == pxSemicolon):
|
||||
getTok(p)
|
||||
@@ -301,7 +296,6 @@ proc exprListAux(p: var TPasParser, elemKind: TNodeKind,
|
||||
addSon(result, a)
|
||||
|
||||
proc qualifiedIdent(p: var TPasParser): PNode =
|
||||
var a: PNode
|
||||
if p.tok.xkind == pxSymbol:
|
||||
result = createIdentNodeP(p.tok.ident, p)
|
||||
else:
|
||||
@@ -313,7 +307,7 @@ proc qualifiedIdent(p: var TPasParser): PNode =
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
if p.tok.xkind == pxSymbol:
|
||||
a = result
|
||||
var a = result
|
||||
result = newNodeI(nkDotExpr, a.info)
|
||||
addSon(result, a)
|
||||
addSon(result, createIdentNodeP(p.tok.ident, p))
|
||||
@@ -321,8 +315,8 @@ proc qualifiedIdent(p: var TPasParser): PNode =
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok))
|
||||
|
||||
proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind, result: PNode) =
|
||||
var a: PNode
|
||||
proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind,
|
||||
result: PNode) =
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
while true:
|
||||
@@ -332,7 +326,7 @@ proc qualifiedIdentListAux(p: var TPasParser, endTok: TPasTokKind, result: PNode
|
||||
if p.tok.xkind == pxEof:
|
||||
parMessage(p, errTokenExpected, PasTokKindToStr[endtok])
|
||||
break
|
||||
a = qualifiedIdent(p)
|
||||
var a = qualifiedIdent(p)
|
||||
skipCom(p, a)
|
||||
if p.tok.xkind == pxComma:
|
||||
getTok(p)
|
||||
@@ -346,17 +340,12 @@ proc exprColonEqExprList(p: var TPasParser, kind, elemKind: TNodeKind,
|
||||
|
||||
proc setBaseFlags(n: PNode, base: TNumericalBase) =
|
||||
case base
|
||||
of base10:
|
||||
nil
|
||||
of base2:
|
||||
incl(n.flags, nfBase2)
|
||||
of base8:
|
||||
incl(n.flags, nfBase8)
|
||||
of base16:
|
||||
incl(n.flags, nfBase16)
|
||||
of base10: nil
|
||||
of base2: incl(n.flags, nfBase2)
|
||||
of base8: incl(n.flags, nfBase8)
|
||||
of base16: incl(n.flags, nfBase16)
|
||||
|
||||
proc identOrLiteral(p: var TPasParser): PNode =
|
||||
var a: PNode
|
||||
case p.tok.xkind
|
||||
of pxSymbol:
|
||||
result = createIdentNodeP(p.tok.ident, p)
|
||||
@@ -382,8 +371,9 @@ proc identOrLiteral(p: var TPasParser): PNode =
|
||||
getTok(p)
|
||||
of pxParLe:
|
||||
# () constructor
|
||||
result = exprColonEqExprList(p, nkPar, nkExprColonExpr, pxParRi, pxColon) #if hasSonWith(result, nkExprColonExpr) then
|
||||
# replaceSons(result, nkExprColonExpr, nkExprEqExpr)
|
||||
result = exprColonEqExprList(p, nkPar, nkExprColonExpr, pxParRi, pxColon)
|
||||
#if hasSonWith(result, nkExprColonExpr) then
|
||||
# replaceSons(result, nkExprColonExpr, nkExprEqExpr)
|
||||
if (sonsLen(result) > 1) and not hasSonWith(result, nkExprColonExpr):
|
||||
result.kind = nkBracket # is an array constructor
|
||||
of pxBracketLe:
|
||||
@@ -392,7 +382,7 @@ proc identOrLiteral(p: var TPasParser): PNode =
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
while (p.tok.xkind != pxBracketRi) and (p.tok.xkind != pxEof):
|
||||
a = rangeExpr(p)
|
||||
var a = rangeExpr(p)
|
||||
if a.kind == nkRange:
|
||||
result.kind = nkCurly # it is definitely a set literal
|
||||
opt(p, pxComma)
|
||||
@@ -404,17 +394,16 @@ proc identOrLiteral(p: var TPasParser): PNode =
|
||||
result = parseCommand(p)
|
||||
else:
|
||||
parMessage(p, errExprExpected, pasTokToStr(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
|
||||
if result != nil: skipCom(p, result)
|
||||
|
||||
proc primary(p: var TPasParser): PNode =
|
||||
var a: PNode
|
||||
# prefix operator?
|
||||
if (p.tok.xkind == pxNot) or (p.tok.xkind == pxMinus) or
|
||||
(p.tok.xkind == pxPlus):
|
||||
result = newNodeP(nkPrefix, p)
|
||||
a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p)
|
||||
var a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p)
|
||||
addSon(result, a)
|
||||
getTok(p)
|
||||
skipCom(p, a)
|
||||
@@ -422,7 +411,7 @@ proc primary(p: var TPasParser): PNode =
|
||||
return
|
||||
elif p.tok.xkind == pxAt:
|
||||
result = newNodeP(nkAddr, p)
|
||||
a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p)
|
||||
var a = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p)
|
||||
getTok(p)
|
||||
if p.tok.xkind == pxBracketLe:
|
||||
result = newNodeP(nkPrefix, p)
|
||||
@@ -435,12 +424,12 @@ proc primary(p: var TPasParser): PNode =
|
||||
while true:
|
||||
case p.tok.xkind
|
||||
of pxParLe:
|
||||
a = result
|
||||
var a = result
|
||||
result = newNodeP(nkCall, p)
|
||||
addSon(result, a)
|
||||
exprListAux(p, nkExprEqExpr, pxParRi, pxEquals, result)
|
||||
of pxDot:
|
||||
a = result
|
||||
var a = result
|
||||
result = newNodeP(nkDotExpr, p)
|
||||
addSon(result, a)
|
||||
getTok(p) # skip '.'
|
||||
@@ -451,7 +440,7 @@ proc primary(p: var TPasParser): PNode =
|
||||
else:
|
||||
parMessage(p, errIdentifierExpected, pasTokToStr(p.tok))
|
||||
of pxHat:
|
||||
a = result
|
||||
var a = result
|
||||
result = newNodeP(nkDerefExpr, p)
|
||||
addSon(result, a)
|
||||
getTok(p)
|
||||
@@ -461,12 +450,11 @@ proc primary(p: var TPasParser): PNode =
|
||||
|
||||
proc lowestExprAux(p: var TPasParser, v: var PNode, limit: int): TPasTokKind =
|
||||
var
|
||||
op, nextop: TPasTokKind
|
||||
opPred: int
|
||||
nextop: TPasTokKind
|
||||
v2, node, opNode: PNode
|
||||
v = primary(p) # expand while operators have priorities higher than 'limit'
|
||||
op = p.tok.xkind
|
||||
opPred = getPrecedence(op)
|
||||
v = primary(p) # expand while operators have priorities higher than 'limit'
|
||||
var op = p.tok.xkind
|
||||
var opPred = getPrecedence(op)
|
||||
while (opPred > limit):
|
||||
node = newNodeP(nkInfix, p)
|
||||
opNode = newIdentNodeP(getIdent(pasTokToStr(p.tok)), p) # skip operator:
|
||||
@@ -530,8 +518,7 @@ proc fixExpr(n: PNode): PNode =
|
||||
for i in countup(0, sonsLen(n) - 1): result.sons[i] = fixExpr(n.sons[i])
|
||||
|
||||
proc parseExpr(p: var TPasParser): PNode =
|
||||
var oldcontext: TPasContext
|
||||
oldcontext = p.context
|
||||
var oldcontext = p.context
|
||||
p.context = conExpr
|
||||
if p.tok.xkind == pxCommand:
|
||||
result = parseCommand(p)
|
||||
@@ -541,15 +528,12 @@ proc parseExpr(p: var TPasParser): PNode =
|
||||
p.context = oldcontext
|
||||
|
||||
proc parseExprStmt(p: var TPasParser): PNode =
|
||||
var
|
||||
a, b: PNode
|
||||
info: TLineInfo
|
||||
info = parLineInfo(p)
|
||||
a = parseExpr(p)
|
||||
var info = parLineInfo(p)
|
||||
var a = parseExpr(p)
|
||||
if p.tok.xkind == pxAsgn:
|
||||
getTok(p)
|
||||
skipCom(p, a)
|
||||
b = parseExpr(p)
|
||||
var b = parseExpr(p)
|
||||
result = newNodeI(nkAsgn, info)
|
||||
addSon(result, a)
|
||||
addSon(result, b)
|
||||
@@ -560,7 +544,6 @@ proc inImportBlackList(ident: PIdent): bool =
|
||||
for i in countup(low(ImportBlackList), high(ImportBlackList)):
|
||||
if ident.id == getIdent(ImportBlackList[i]).id:
|
||||
return true
|
||||
result = false
|
||||
|
||||
proc parseUsesStmt(p: var TPasParser): PNode =
|
||||
var a: PNode
|
||||
@@ -586,10 +569,9 @@ proc parseUsesStmt(p: var TPasParser): PNode =
|
||||
if sonsLen(result) == 0: result = nil
|
||||
|
||||
proc parseIncludeDir(p: var TPasParser): PNode =
|
||||
var filename: string
|
||||
result = newNodeP(nkIncludeStmt, p)
|
||||
getTok(p) # skip `include`
|
||||
filename = ""
|
||||
var filename = ""
|
||||
while true:
|
||||
case p.tok.xkind
|
||||
of pxSymbol, pxDot, pxDotDot, pxSlash:
|
||||
@@ -635,14 +617,11 @@ proc parseStmtList(p: var TPasParser): PNode =
|
||||
if sonsLen(result) == 1: result = result.sons[0]
|
||||
|
||||
proc parseIfDirAux(p: var TPasParser, result: PNode) =
|
||||
var
|
||||
s: PNode
|
||||
endMarker: TPasTokKind
|
||||
addSon(result.sons[0], parseStmtList(p))
|
||||
if p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}:
|
||||
endMarker = succ(p.tok.xkind)
|
||||
var endMarker = succ(p.tok.xkind)
|
||||
if whichKeyword(p.tok.ident) == wElse:
|
||||
s = newNodeP(nkElse, p)
|
||||
var s = newNodeP(nkElse, p)
|
||||
while (p.tok.xkind != pxEof) and (p.tok.xkind != endMarker): getTok(p)
|
||||
eat(p, endMarker)
|
||||
addSon(s, parseStmtList(p))
|
||||
@@ -666,11 +645,10 @@ proc parseIfdefDir(p: var TPasParser, endMarker: TPasTokKind): PNode =
|
||||
parseIfDirAux(p, result)
|
||||
|
||||
proc parseIfndefDir(p: var TPasParser, endMarker: TPasTokKind): PNode =
|
||||
var e: PNode
|
||||
result = newNodeP(nkWhenStmt, p)
|
||||
addSon(result, newNodeP(nkElifBranch, p))
|
||||
getTok(p)
|
||||
e = newNodeP(nkCall, p)
|
||||
var e = newNodeP(nkCall, p)
|
||||
addSon(e, newIdentNodeP(getIdent("not"), p))
|
||||
addSon(e, definedExprAux(p))
|
||||
eat(p, endMarker)
|
||||
@@ -686,21 +664,17 @@ proc parseIfDir(p: var TPasParser, endMarker: TPasTokKind): PNode =
|
||||
parseIfDirAux(p, result)
|
||||
|
||||
proc parseDirective(p: var TPasParser): PNode =
|
||||
var endMarker: TPasTokKind
|
||||
result = nil
|
||||
if not (p.tok.xkind in {pxCurlyDirLe, pxStarDirLe}): return
|
||||
endMarker = succ(p.tok.xkind)
|
||||
var endMarker = succ(p.tok.xkind)
|
||||
if p.tok.ident != nil:
|
||||
case whichKeyword(p.tok.ident)
|
||||
of wInclude:
|
||||
result = parseIncludeDir(p)
|
||||
eat(p, endMarker)
|
||||
of wIf:
|
||||
result = parseIfDir(p, endMarker)
|
||||
of wIfdef:
|
||||
result = parseIfdefDir(p, endMarker)
|
||||
of wIfndef:
|
||||
result = parseIfndefDir(p, endMarker)
|
||||
of wIf: result = parseIfDir(p, endMarker)
|
||||
of wIfdef: result = parseIfdefDir(p, endMarker)
|
||||
of wIfndef: result = parseIfndefDir(p, endMarker)
|
||||
else:
|
||||
# skip unknown compiler directive
|
||||
while (p.tok.xkind != pxEof) and (p.tok.xkind != endMarker): getTok(p)
|
||||
@@ -716,11 +690,10 @@ proc parseRaise(p: var TPasParser): PNode =
|
||||
else: addSon(result, nil)
|
||||
|
||||
proc parseIf(p: var TPasParser): PNode =
|
||||
var branch: PNode
|
||||
result = newNodeP(nkIfStmt, p)
|
||||
while true:
|
||||
getTok(p) # skip ``if``
|
||||
branch = newNodeP(nkElifBranch, p)
|
||||
var branch = newNodeP(nkElifBranch, p)
|
||||
skipCom(p, branch)
|
||||
addSon(branch, parseExpr(p))
|
||||
eat(p, pxThen)
|
||||
@@ -750,26 +723,24 @@ proc parseWhile(p: var TPasParser): PNode =
|
||||
addSon(result, parseStmt(p))
|
||||
|
||||
proc parseRepeat(p: var TPasParser): PNode =
|
||||
var a, b, c, s: PNode
|
||||
result = newNodeP(nkWhileStmt, p)
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
addSon(result, newIdentNodeP(getIdent("true"), p))
|
||||
s = newNodeP(nkStmtList, p)
|
||||
var s = newNodeP(nkStmtList, p)
|
||||
while (p.tok.xkind != pxEof) and (p.tok.xkind != pxUntil):
|
||||
addSon(s, parseStmt(p))
|
||||
eat(p, pxUntil)
|
||||
a = newNodeP(nkIfStmt, p)
|
||||
var a = newNodeP(nkIfStmt, p)
|
||||
skipCom(p, a)
|
||||
b = newNodeP(nkElifBranch, p)
|
||||
c = newNodeP(nkBreakStmt, p)
|
||||
var b = newNodeP(nkElifBranch, p)
|
||||
var c = newNodeP(nkBreakStmt, p)
|
||||
addSon(c, nil)
|
||||
addSon(b, parseExpr(p))
|
||||
skipCom(p, a)
|
||||
addSon(b, c)
|
||||
addSon(a, b)
|
||||
if (b.sons[0].kind == nkIdent) and
|
||||
(b.sons[0].ident.id == getIdent("false").id):
|
||||
if b.sons[0].kind == nkIdent and b.sons[0].ident.id == getIdent("false").id:
|
||||
nil
|
||||
else:
|
||||
addSon(s, a)
|
||||
@@ -800,11 +771,10 @@ proc parseCase(p: var TPasParser): PNode =
|
||||
eat(p, pxEnd)
|
||||
|
||||
proc parseTry(p: var TPasParser): PNode =
|
||||
var b, e: PNode
|
||||
result = newNodeP(nkTryStmt, p)
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
b = newNodeP(nkStmtList, p)
|
||||
var b = newNodeP(nkStmtList, p)
|
||||
while not (p.tok.xkind in {pxFinally, pxExcept, pxEof, pxEnd}):
|
||||
addSon(b, parseStmt(p))
|
||||
addSon(result, b)
|
||||
@@ -813,7 +783,7 @@ proc parseTry(p: var TPasParser): PNode =
|
||||
while p.tok.ident.id == getIdent("on").id:
|
||||
b = newNodeP(nkExceptBranch, p)
|
||||
getTok(p)
|
||||
e = qualifiedIdent(p)
|
||||
var e = qualifiedIdent(p)
|
||||
if p.tok.xkind == pxColon:
|
||||
getTok(p)
|
||||
e = qualifiedIdent(p)
|
||||
@@ -830,7 +800,7 @@ proc parseTry(p: var TPasParser): PNode =
|
||||
if p.tok.xkind == pxFinally:
|
||||
b = newNodeP(nkFinally, p)
|
||||
getTok(p)
|
||||
e = newNodeP(nkStmtList, p)
|
||||
var e = newNodeP(nkStmtList, p)
|
||||
while (p.tok.xkind != pxEof) and (p.tok.xkind != pxEnd):
|
||||
addSon(e, parseStmt(p))
|
||||
if sonsLen(e) == 0: addSon(e, newNodeP(nkNilLit, p))
|
||||
@@ -1062,8 +1032,7 @@ proc parseEnum(p: var TPasParser): PNode =
|
||||
|
||||
proc identVis(p: var TPasParser): PNode =
|
||||
# identifier with visability
|
||||
var a: PNode
|
||||
a = createIdentNodeP(p.tok.ident, p)
|
||||
var a = createIdentNodeP(p.tok.ident, p)
|
||||
if p.section == seInterface:
|
||||
result = newNodeP(nkPostfix, p)
|
||||
addSon(result, newIdentNodeP(getIdent("*"), p))
|
||||
@@ -1079,7 +1048,8 @@ proc rawIdent(p: var TPasParser): PNode =
|
||||
result = createIdentNodeP(p.tok.ident, p)
|
||||
getTok(p)
|
||||
|
||||
proc parseIdentColonEquals(p: var TPasParser, identParser: TSymbolParser): PNode =
|
||||
proc parseIdentColonEquals(p: var TPasParser,
|
||||
identParser: TSymbolParser): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(nkIdentDefs, p)
|
||||
while true:
|
||||
@@ -1171,41 +1141,38 @@ proc parseRecordPart(p: var TPasParser): PNode =
|
||||
break
|
||||
|
||||
proc exSymbol(n: var PNode) =
|
||||
var a: PNode
|
||||
case n.kind
|
||||
of nkPostfix:
|
||||
nil
|
||||
of nkPragmaExpr:
|
||||
exSymbol(n.sons[0])
|
||||
of nkIdent, nkAccQuoted:
|
||||
a = newNodeI(nkPostFix, n.info)
|
||||
var a = newNodeI(nkPostFix, n.info)
|
||||
addSon(a, newIdentNode(getIdent("*"), n.info))
|
||||
addSon(a, n)
|
||||
n = a
|
||||
else: internalError(n.info, "exSymbol(): " & $n.kind)
|
||||
|
||||
proc fixRecordDef(n: var PNode) =
|
||||
var length: int
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkRecCase:
|
||||
fixRecordDef(n.sons[0])
|
||||
for i in countup(1, sonsLen(n) - 1):
|
||||
length = sonsLen(n.sons[i])
|
||||
var length = sonsLen(n.sons[i])
|
||||
fixRecordDef(n.sons[i].sons[length - 1])
|
||||
of nkRecList, nkRecWhen, nkElse, nkOfBranch, nkElifBranch, nkObjectTy:
|
||||
for i in countup(0, sonsLen(n) - 1): fixRecordDef(n.sons[i])
|
||||
of nkIdentDefs:
|
||||
for i in countup(0, sonsLen(n) - 3): exSymbol(n.sons[i])
|
||||
of nkNilLit:
|
||||
nil
|
||||
of nkNilLit: nil
|
||||
else: internalError(n.info, "fixRecordDef(): " & $n.kind)
|
||||
|
||||
proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
|
||||
var e, pragmasNode: PNode
|
||||
var pragmasNode: PNode
|
||||
if ident.kind != nkPragmaExpr:
|
||||
pragmasNode = newNodeI(nkPragma, ident.info)
|
||||
e = newNodeI(nkPragmaExpr, ident.info)
|
||||
var e = newNodeI(nkPragmaExpr, ident.info)
|
||||
addSon(e, ident)
|
||||
addSon(e, pragmasNode)
|
||||
ident = e
|
||||
@@ -1216,9 +1183,8 @@ proc addPragmaToIdent(ident: var PNode, pragma: PNode) =
|
||||
addSon(pragmasNode, pragma)
|
||||
|
||||
proc parseRecordBody(p: var TPasParser, result, definition: PNode) =
|
||||
var a: PNode
|
||||
skipCom(p, result)
|
||||
a = parseRecordPart(p)
|
||||
var a = parseRecordPart(p)
|
||||
if result.kind != nkTupleTy: fixRecordDef(a)
|
||||
addSon(result, a)
|
||||
eat(p, pxEnd)
|
||||
@@ -1242,12 +1208,11 @@ proc parseRecordBody(p: var TPasParser, result, definition: PNode) =
|
||||
|
||||
proc parseRecordOrObject(p: var TPasParser, kind: TNodeKind,
|
||||
definition: PNode): PNode =
|
||||
var a: PNode
|
||||
result = newNodeP(kind, p)
|
||||
getTok(p)
|
||||
addSon(result, nil)
|
||||
if p.tok.xkind == pxParLe:
|
||||
a = newNodeP(nkOfInherit, p)
|
||||
var a = newNodeP(nkOfInherit, p)
|
||||
getTok(p)
|
||||
addSon(a, parseTypeDesc(p))
|
||||
addSon(result, a)
|
||||
@@ -1257,10 +1222,7 @@ proc parseRecordOrObject(p: var TPasParser, kind: TNodeKind,
|
||||
parseRecordBody(p, result, definition)
|
||||
|
||||
proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode =
|
||||
var
|
||||
oldcontext: TPasContext
|
||||
a, r: PNode
|
||||
oldcontext = p.context
|
||||
var oldcontext = p.context
|
||||
p.context = conTypeDesc
|
||||
if p.tok.xkind == pxPacked: getTok(p)
|
||||
case p.tok.xkind
|
||||
@@ -1274,7 +1236,7 @@ proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode =
|
||||
result = parseCommand(p)
|
||||
if result.kind != nkTupleTy: InternalError(result.info, "parseTypeDesc")
|
||||
parseRecordBody(p, result, definition)
|
||||
a = lastSon(result) # embed nkRecList directly into nkTupleTy
|
||||
var a = lastSon(result) # embed nkRecList directly into nkTupleTy
|
||||
for i in countup(0, sonsLen(a) - 1):
|
||||
if i == 0: result.sons[sonsLen(result) - 1] = a.sons[0]
|
||||
else: addSon(result, a.sons[i])
|
||||
@@ -1287,10 +1249,8 @@ proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode =
|
||||
addPragmaToIdent(definition.sons[0], newIdentNodeP(getIdent("final"), p))
|
||||
else:
|
||||
InternalError(result.info, "anonymous record is not supported")
|
||||
of pxObject:
|
||||
result = parseRecordOrObject(p, nkObjectTy, definition)
|
||||
of pxParLe:
|
||||
result = parseEnum(p)
|
||||
of pxObject: result = parseRecordOrObject(p, nkObjectTy, definition)
|
||||
of pxParLe: result = parseEnum(p)
|
||||
of pxArray:
|
||||
result = newNodeP(nkBracketExpr, p)
|
||||
getTok(p)
|
||||
@@ -1320,10 +1280,10 @@ proc parseTypeDesc(p: var TPasParser, definition: PNode = nil): PNode =
|
||||
getTok(p)
|
||||
result = parseTypeDesc(p)
|
||||
else:
|
||||
a = primary(p)
|
||||
var a = primary(p)
|
||||
if p.tok.xkind == pxDotDot:
|
||||
result = newNodeP(nkBracketExpr, p)
|
||||
r = newNodeP(nkRange, p)
|
||||
var r = newNodeP(nkRange, p)
|
||||
addSon(result, newIdentNodeP(getIdent("range"), p))
|
||||
getTok(p)
|
||||
addSon(r, a)
|
||||
@@ -1386,13 +1346,13 @@ proc parseVar(p: var TPasParser): PNode =
|
||||
result = newNodeP(nkVarSection, p)
|
||||
getTok(p)
|
||||
skipCom(p, result)
|
||||
while p.tok.xkind == pxSymbol:
|
||||
while p.tok.xkind == pxSymbol:
|
||||
addSon(result, parseIdentColonEquals(p, identVis))
|
||||
p.lastVarSection = result
|
||||
|
||||
proc parseRoutine(p: var TPasParser): PNode =
|
||||
var
|
||||
a, stmts: PNode
|
||||
stmts: PNode
|
||||
noBody: bool
|
||||
result = newNodeP(nkProcDef, p)
|
||||
getTok(p)
|
||||
@@ -1417,19 +1377,16 @@ proc parseRoutine(p: var TPasParser): PNode =
|
||||
else:
|
||||
parMessage(p, errTokenExpected, "begin")
|
||||
break
|
||||
a = parseStmt(p)
|
||||
var a = parseStmt(p)
|
||||
for i in countup(0, sonsLen(a) - 1): addSon(stmts, a.sons[i])
|
||||
addSon(result, stmts)
|
||||
|
||||
proc fixExit(p: var TPasParser, n: PNode): bool =
|
||||
var
|
||||
length: int
|
||||
a: PNode
|
||||
result = false
|
||||
if (p.tok.ident.id == getIdent("exit").id):
|
||||
length = sonsLen(n)
|
||||
var length = sonsLen(n)
|
||||
if (length <= 0): return
|
||||
a = n.sons[length - 1]
|
||||
var a = n.sons[length-1]
|
||||
if (a.kind == nkAsgn) and (a.sons[0].kind == nkIdent) and
|
||||
(a.sons[0].ident.id == getIdent("result").id):
|
||||
delSon(a, 0)
|
||||
@@ -1440,11 +1397,10 @@ proc fixExit(p: var TPasParser, n: PNode): bool =
|
||||
skipCom(p, a)
|
||||
|
||||
proc fixVarSection(p: var TPasParser, counter: PNode) =
|
||||
var v: PNode
|
||||
if p.lastVarSection == nil: return
|
||||
assert(counter.kind == nkIdent)
|
||||
for i in countup(0, sonsLen(p.lastVarSection) - 1):
|
||||
v = p.lastVarSection.sons[i]
|
||||
var v = p.lastVarSection.sons[i]
|
||||
for j in countup(0, sonsLen(v) - 3):
|
||||
if v.sons[j].ident.id == counter.ident.id:
|
||||
delSon(v, j)
|
||||
@@ -1456,64 +1412,47 @@ proc parseBegin(p: var TPasParser, result: PNode) =
|
||||
getTok(p)
|
||||
while true:
|
||||
case p.tok.xkind
|
||||
of pxComment:
|
||||
addSon(result, parseStmt(p))
|
||||
of pxComment: addSon(result, parseStmt(p))
|
||||
of pxSymbol:
|
||||
if not fixExit(p, result): addSon(result, parseStmt(p))
|
||||
of pxEnd:
|
||||
getTok(p)
|
||||
break
|
||||
of pxSemicolon:
|
||||
getTok(p)
|
||||
of pxEof:
|
||||
parMessage(p, errExprExpected)
|
||||
of pxSemicolon: getTok(p)
|
||||
of pxEof: parMessage(p, errExprExpected)
|
||||
else: addSonIfNotNil(result, parseStmt(p))
|
||||
if sonsLen(result) == 0: addSon(result, newNodeP(nkNilLit, p))
|
||||
|
||||
proc parseStmt(p: var TPasParser): PNode =
|
||||
var oldcontext: TPasContext
|
||||
oldcontext = p.context
|
||||
var oldcontext = p.context
|
||||
p.context = conStmt
|
||||
result = nil
|
||||
case p.tok.xkind
|
||||
of pxBegin:
|
||||
result = newNodeP(nkStmtList, p)
|
||||
parseBegin(p, result)
|
||||
of pxCommand:
|
||||
result = parseCommand(p)
|
||||
of pxCommand: result = parseCommand(p)
|
||||
of pxCurlyDirLe, pxStarDirLe:
|
||||
if isHandledDirective(p): result = parseDirective(p)
|
||||
of pxIf:
|
||||
result = parseIf(p)
|
||||
of pxWhile:
|
||||
result = parseWhile(p)
|
||||
of pxRepeat:
|
||||
result = parseRepeat(p)
|
||||
of pxCase:
|
||||
result = parseCase(p)
|
||||
of pxTry:
|
||||
result = parseTry(p)
|
||||
of pxProcedure, pxFunction:
|
||||
result = parseRoutine(p)
|
||||
of pxType:
|
||||
result = parseTypeSection(p)
|
||||
of pxConst:
|
||||
result = parseConstSection(p)
|
||||
of pxVar:
|
||||
result = parseVar(p)
|
||||
of pxIf: result = parseIf(p)
|
||||
of pxWhile: result = parseWhile(p)
|
||||
of pxRepeat: result = parseRepeat(p)
|
||||
of pxCase: result = parseCase(p)
|
||||
of pxTry: result = parseTry(p)
|
||||
of pxProcedure, pxFunction: result = parseRoutine(p)
|
||||
of pxType: result = parseTypeSection(p)
|
||||
of pxConst: result = parseConstSection(p)
|
||||
of pxVar: result = parseVar(p)
|
||||
of pxFor:
|
||||
result = parseFor(p)
|
||||
fixVarSection(p, result.sons[0])
|
||||
of pxRaise:
|
||||
result = parseRaise(p)
|
||||
of pxUses:
|
||||
result = parseUsesStmt(p)
|
||||
of pxRaise: result = parseRaise(p)
|
||||
of pxUses: result = parseUsesStmt(p)
|
||||
of pxProgram, pxUnit, pxLibrary:
|
||||
# skip the pointless header
|
||||
while not (p.tok.xkind in {pxSemicolon, pxEof}): getTok(p)
|
||||
getTok(p)
|
||||
of pxInitialization:
|
||||
getTok(p) # just skip the token
|
||||
of pxInitialization: getTok(p) # just skip the token
|
||||
of pxImplementation:
|
||||
p.section = seImplementation
|
||||
result = newNodeP(nkCommentStmt, p)
|
||||
@@ -1525,8 +1464,7 @@ proc parseStmt(p: var TPasParser): PNode =
|
||||
of pxComment:
|
||||
result = newNodeP(nkCommentStmt, p)
|
||||
skipCom(p, result)
|
||||
of pxSemicolon:
|
||||
getTok(p)
|
||||
of pxSemicolon: getTok(p)
|
||||
of pxSymbol:
|
||||
if p.tok.ident.id == getIdent("break").id:
|
||||
result = newNodeP(nkBreakStmt, p)
|
||||
@@ -1545,8 +1483,7 @@ proc parseStmt(p: var TPasParser): PNode =
|
||||
addSon(result, nil)
|
||||
else:
|
||||
result = parseExprStmt(p)
|
||||
of pxDot:
|
||||
getTok(p) # BUGFIX for ``end.`` in main program
|
||||
of pxDot: getTok(p) # BUGFIX for ``end.`` in main program
|
||||
else: result = parseExprStmt(p)
|
||||
opt(p, pxSemicolon)
|
||||
if result != nil: skipCom(p, result)
|
||||
@@ -1557,10 +1494,8 @@ proc parseUnit(p: var TPasParser): PNode =
|
||||
getTok(p) # read first token
|
||||
while true:
|
||||
case p.tok.xkind
|
||||
of pxEof, pxEnd:
|
||||
break
|
||||
of pxBegin:
|
||||
parseBegin(p, result)
|
||||
of pxEof, pxEnd: break
|
||||
of pxBegin: parseBegin(p, result)
|
||||
of pxCurlyDirLe, pxStarDirLe:
|
||||
if isHandledDirective(p): addSon(result, parseDirective(p))
|
||||
else: parMessage(p, errXNotAllowedHere, p.tok.ident.s)
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# (c) Copyright 2009 Andreas Rumpf
|
||||
# (c) Copyright 2010 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
@@ -16,33 +16,21 @@
|
||||
import
|
||||
nhashes, strutils, idents
|
||||
|
||||
# Keywords must be kept sorted and within a range
|
||||
|
||||
type
|
||||
TSpecialWord* = enum
|
||||
wInvalid, # these are mapped to Nimrod keywords:
|
||||
#[[[cog
|
||||
#from string import split, capitalize
|
||||
#keywords = split(open("data/keywords.txt").read())
|
||||
#idents = ""
|
||||
#strings = ""
|
||||
#i = 1
|
||||
#for k in keywords:
|
||||
# idents = idents + "w" + capitalize(k) + ", "
|
||||
# strings = strings + "'" + k + "', "
|
||||
# if i % 4 == 0:
|
||||
# idents = idents + "\n"
|
||||
# strings = strings + "\n"
|
||||
# i = i + 1
|
||||
#cog.out(idents)
|
||||
#]]]
|
||||
wInvalid,
|
||||
|
||||
wAddr, wAnd, wAs, wAsm, wBind, wBlock, wBreak, wCase, wCast, wConst,
|
||||
wContinue, wConverter, wDiscard, wDistinct, wDiv, wElif, wElse, wEnd, wEnum,
|
||||
wExcept, wFinally, wFor, wFrom, wGeneric, wIf, wImplies, wImport, wIn,
|
||||
wInclude, wIs, wIsnot, wIterator, wLambda, wMacro, wMethod, wMod, wNil,
|
||||
wNot, wNotin, wObject, wOf, wOr, wOut, wProc, wPtr, wRaise, wRef, wReturn,
|
||||
wShl, wShr, wTemplate, wTry, wTuple, wType, wVar, wWhen, wWhile, wWith,
|
||||
wWithout, wXor, wYield, #[[[end]]]
|
||||
# other special tokens:
|
||||
wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus, # pragmas and command line options:
|
||||
wWithout, wXor, wYield,
|
||||
|
||||
wColon, wEquals, wDot, wDotDot, wHat, wStar, wMinus,
|
||||
wMagic, wTypeCheck, wFinal, wProfiler, wObjChecks, wImportc, wExportc,
|
||||
wAlign, wNodecl, wPure, wVolatile, wRegister, wSideeffect, wHeader,
|
||||
wNosideeffect, wNoreturn, wMerge, wLib, wDynlib, wCompilerproc, wProcVar,
|
||||
@@ -60,39 +48,30 @@ type
|
||||
wPassc, wT, wPassl, wL, wListcmd, wGendoc, wGenmapping, wOs, wCpu,
|
||||
wGenerate, wG, wC, wCpp, wBorrow, wRun, wR, wVerbosity, wV, wHelp, wH,
|
||||
wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced, wSkipcfg, wSkipProjCfg,
|
||||
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar, wAcyclic, wIndex, #
|
||||
# commands:
|
||||
wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar,
|
||||
wAcyclic, wIndex,
|
||||
wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty,
|
||||
wDoc, wPas, wGenDepend, wListDef, wCheck, wParse, wScan, wBoot, wLazy,
|
||||
wRst2html, wRst2tex, wI, # special for the preprocessor of configuration files:
|
||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, # additional Pascal keywords:
|
||||
wArray, wBegin, wClass, wConstructor, wDestructor, wDo, wDownto, wExports,
|
||||
wFinalization, wFunction, wGoto, wImplementation, wInherited,
|
||||
wInitialization, wInterface, wLabel, wLibrary, wPacked, wProcedure,
|
||||
wProgram, wProperty, wRecord, wRepeat, wResourcestring, wSet, wThen,
|
||||
wThreadvar, wTo, wUnit, wUntil, wUses, # Pascal special tokens:
|
||||
wExternal, wOverload, wFar, wAssembler, wForward, wIfdef, wIfndef, wEndif
|
||||
wRst2html, wRst2tex, wI,
|
||||
wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
|
||||
|
||||
TSpecialWords* = set[TSpecialWord]
|
||||
|
||||
const
|
||||
oprLow* = ord(wColon)
|
||||
oprHigh* = ord(wHat)
|
||||
specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["", #
|
||||
# keywords:
|
||||
#
|
||||
#[[[cog
|
||||
#
|
||||
#cog.out(strings)
|
||||
#]]]
|
||||
specialWords*: array[low(TSpecialWord)..high(TSpecialWord), string] = ["",
|
||||
|
||||
"addr", "and", "as", "asm", "bind", "block", "break", "case", "cast",
|
||||
"const", "continue", "converter", "discard", "distinct", "div", "elif",
|
||||
"else", "end", "enum", "except", "finally", "for", "from", "generic", "if",
|
||||
"implies", "import", "in", "include", "is", "isnot", "iterator", "lambda",
|
||||
"macro", "method", "mod", "nil", "not", "notin", "object", "of", "or",
|
||||
"out", "proc", "ptr", "raise", "ref", "return", "shl", "shr", "template",
|
||||
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor", "yield", #[[[end]]]
|
||||
# other special tokens:
|
||||
":", "=", ".", "..", "^", "*", "-", # pragmas and command line options:
|
||||
"try", "tuple", "type", "var", "when", "while", "with", "without", "xor",
|
||||
"yield",
|
||||
|
||||
":", "=", ".", "..", "^", "*", "-",
|
||||
"magic", "typecheck", "final", "profiler", "objchecks", "importc",
|
||||
"exportc", "align", "nodecl", "pure", "volatile", "register", "sideeffect",
|
||||
"header", "nosideeffect", "noreturn", "merge", "lib", "dynlib",
|
||||
@@ -113,18 +92,11 @@ const
|
||||
"cpu", "generate", "g", "c", "cpp", "borrow", "run", "r", "verbosity", "v",
|
||||
"help", "h", "symbolfiles", "fieldchecks", "x", "version", "advanced",
|
||||
"skipcfg", "skipprojcfg", "cc", "genscript", "checkpoint", "checkpoints",
|
||||
"nomain", "subschar", "acyclic", "index", # commands:
|
||||
"nomain", "subschar", "acyclic", "index",
|
||||
"compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm",
|
||||
"pretty", "doc", "pas", "gendepend", "listdef", "check", "parse", "scan",
|
||||
"boot", "lazy", "rst2html", "rst2tex", "i", # special for the preprocessor of configuration files:
|
||||
"write", "putenv", "prependenv", "appendenv", "array", "begin", "class",
|
||||
"constructor", "destructor", "do", "downto", "exports", "finalization",
|
||||
"function", "goto", "implementation", "inherited", "initialization",
|
||||
"interface", "label", "library", "packed", "procedure", "program",
|
||||
"property", "record", "repeat", "resourcestring", "set", "then",
|
||||
"threadvar", "to", "unit", "until", "uses", # Pascal special tokens
|
||||
"external", "overload", "far", "assembler", "forward", "ifdef", "ifndef",
|
||||
"endif"]
|
||||
"boot", "lazy", "rst2html", "rst2tex", "i",
|
||||
"write", "putenv", "prependenv", "appendenv", "threadvar"]
|
||||
|
||||
proc whichKeyword*(id: PIdent): TSpecialWord
|
||||
proc whichKeyword*(id: String): TSpecialWord
|
||||
@@ -149,4 +121,4 @@ proc initSpecials() =
|
||||
for s in countup(succ(low(specialWords)), high(specialWords)):
|
||||
getIdent(specialWords[s], getNormalizedHash(specialWords[s])).id = ord(s)
|
||||
|
||||
initSpecials()
|
||||
initSpecials()
|
||||
|
||||
15
web/news.txt
15
web/news.txt
@@ -5,6 +5,9 @@ News
|
||||
2010-XX-XX Version 0.8.8 released
|
||||
=================================
|
||||
|
||||
Version 0.8.8 has been released! Get it `here <download.html>`_.
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
- The Posix version of ``os.copyFile`` has better error handling.
|
||||
@@ -33,16 +36,18 @@ Changes affecting backwards compatibility
|
||||
|
||||
- Overloading of the subscript operator only works if the type does not provide
|
||||
a built-in one.
|
||||
|
||||
|
||||
- The search order for libraries which is affected by the ``path`` option
|
||||
has been reversed, so that the project's path is searched before
|
||||
the standard library's path.
|
||||
- The compiler does not include a Pascal parser for bootstrapping purposes any
|
||||
more. Instead there is a ``pas2nim`` tool that contains the old functionality.
|
||||
|
||||
|
||||
2009-12-21 Version 0.8.6 released
|
||||
=================================
|
||||
|
||||
Version 0.8.6 has been released! Get it `here <download.html>`_. The version
|
||||
jump from 0.8.2 to 0.8.6 acknowledges the fact that all development of the
|
||||
compiler is now done in Nimrod.
|
||||
The version jump from 0.8.2 to 0.8.6 acknowledges the fact that all development
|
||||
of the compiler is now done in Nimrod.
|
||||
|
||||
|
||||
Bugfixes
|
||||
|
||||
Reference in New Issue
Block a user