Merge branch 'new_spawn' into devel

Conflicts:
	todo.txt
	web/news.txt
	web/nimrod.ini
This commit is contained in:
Araq 2014-07-15 09:37:45 +02:00
commit 6d3b632b47
39 changed files with 8083 additions and 7242 deletions

View file

@ -417,6 +417,7 @@ type
# efficiency
nfTransf, # node has been transformed
nfSem # node has been checked for semantics
nfLL # node has gone through lambda lifting
nfDotField # the call can use a dot operator
nfDotSetter # the call can use a setter dot operarator
nfExplicitCall # x.y() was used instead of x.y
@ -1505,7 +1506,7 @@ proc isGenericRoutine*(s: PSym): bool =
proc skipGenericOwner*(s: PSym): PSym =
internalAssert s.kind in skProcKinds
## Generic instantiations are owned by their originating generic
## symbol. This proc skips such owners and goes straigh to the owner
## symbol. This proc skips such owners and goes straight to the owner
## of the generic itself (the module or the enclosing proc).
result = if sfFromGeneric in s.flags: s.owner.owner
else: s.owner

View file

@ -1,92 +0,0 @@
#
#
# c2nim - C to Nimrod source converter
# (c) Copyright 2013 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
strutils, os, times, parseopt, llstream, ast, renderer, options, msgs,
clex, cparse
const
Version = NimrodVersion
Usage = """
c2nim - C to Nimrod source converter
(c) 2013 Andreas Rumpf
Usage: c2nim [options] inputfile [options]
Options:
-o, --out:FILE set output filename
--cpp process C++ input file
--dynlib:SYMBOL import from dynlib: SYMBOL will be used for the import
--header:HEADER_FILE import from a HEADER_FILE (discouraged!)
--cdecl annotate procs with ``{.cdecl.}``
--stdcall annotate procs with ``{.stdcall.}``
--ref convert typ* to ref typ (default: ptr typ)
--prefix:PREFIX strip prefix for the generated Nimrod identifiers
(multiple --prefix options are supported)
--suffix:SUFFIX strip suffix for the generated Nimrod identifiers
(multiple --suffix options are supported)
--skipinclude do not convert ``#include`` to ``import``
--typeprefixes generate ``T`` and ``P`` type prefixes
--skipcomments do not copy comments
--ignoreRValueRefs translate C++'s ``T&&`` to ``T`` instead ``of var T``
--keepBodies keep C++'s method bodies
--spliceHeader parse and emit header before source file
-v, --version write c2nim's version
-h, --help show this help
"""
proc parse(infile: string, options: PParserOptions): PNode =
var stream = llStreamOpen(infile, fmRead)
if stream == nil: rawMessage(errCannotOpenFile, infile)
var p: TParser
openParser(p, infile, stream, options)
result = parseUnit(p)
closeParser(p)
proc main(infile, outfile: string, options: PParserOptions, spliceHeader: bool) =
var start = getTime()
if spliceHeader and infile.splitFile.ext == ".c" and existsFile(infile.changeFileExt(".h")):
var header_module = parse(infile.changeFileExt(".h"), options)
var source_module = parse(infile, options)
for n in source_module:
addson(header_module, n)
renderModule(header_module, outfile)
else:
renderModule(parse(infile, options), outfile)
rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start),
formatSize(getTotalMem())])
var
infile = ""
outfile = ""
spliceHeader = false
parserOptions = newParserOptions()
for kind, key, val in getopt():
case kind
of cmdArgument: infile = key
of cmdLongOption, cmdShortOption:
case key.toLower
of "help", "h":
stdout.write(Usage)
quit(0)
of "version", "v":
stdout.write(Version & "\n")
quit(0)
of "o", "out": outfile = val
of "spliceheader": spliceHeader = true
else:
if not parserOptions.setOption(key, val):
stdout.writeln("[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, "h")
main(infile, outfile, parserOptions, spliceHeader)

View file

@ -1,787 +0,0 @@
#
#
# c2nim - C to Nimrod source converter
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# This module implements an Ansi C scanner. This is an adaption from
# the scanner module. Keywords are not handled here, but in the parser to make
# it more flexible.
import
options, msgs, strutils, platform, nimlexbase, llstream
const
MaxLineLength* = 80 # lines longer than this lead to a warning
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'}
type
TTokKind* = enum
pxInvalid, pxEof,
pxMacroParam, # fake token: macro parameter (with its index)
pxStarComment, # /* */ comment
pxLineComment, # // comment
pxDirective, # #define, etc.
pxDirectiveParLe, # #define m( with parle (yes, C is that ugly!)
pxDirConc, # ##
pxNewLine, # newline: end of directive
pxAmp, # &
pxAmpAmp, # &&
pxAmpAsgn, # &=
pxAmpAmpAsgn, # &&=
pxBar, # |
pxBarBar, # ||
pxBarAsgn, # |=
pxBarBarAsgn, # ||=
pxNot, # !
pxPlusPlus, # ++
pxMinusMinus, # --
pxPlus, # +
pxPlusAsgn, # +=
pxMinus, # -
pxMinusAsgn, # -=
pxMod, # %
pxModAsgn, # %=
pxSlash, # /
pxSlashAsgn, # /=
pxStar, # *
pxStarAsgn, # *=
pxHat, # ^
pxHatAsgn, # ^=
pxAsgn, # =
pxEquals, # ==
pxDot, # .
pxDotDotDot, # ...
pxLe, # <=
pxLt, # <
pxGe, # >=
pxGt, # >
pxNeq, # !=
pxConditional, # ?
pxShl, # <<
pxShlAsgn, # <<=
pxShr, # >>
pxShrAsgn, # >>=
pxTilde, # ~
pxTildeAsgn, # ~=
pxArrow, # ->
pxScope, # ::
pxStrLit,
pxCharLit,
pxSymbol, # a symbol
pxIntLit,
pxInt64Lit, # long constant like 0x70fffffff or out of int range
pxFloatLit,
pxParLe, pxBracketLe, pxCurlyLe, # this order is important
pxParRi, pxBracketRi, pxCurlyRi, # for macro argument parsing!
pxComma, pxSemiColon, pxColon,
pxAngleRi # '>' but determined to be the end of a
# template's angle bracket
TTokKinds* = set[TTokKind]
type
TNumericalBase* = enum base10, base2, base8, base16
TToken* = object
xkind*: TTokKind # the type of the token
s*: string # parsed symbol, char or string literal
iNumber*: BiggestInt # the parsed integer literal;
# if xkind == pxMacroParam: parameter's position
fNumber*: BiggestFloat # the parsed floating point literal
base*: TNumericalBase # the numerical base; only valid for int
# or float literals
next*: ref TToken # for C we need arbitrary look-ahead :-(
TLexer* = object of TBaseLexer
fileIdx*: int32
inDirective: bool
proc getTok*(L: var TLexer, tok: var TToken)
proc printTok*(tok: TToken)
proc `$`*(tok: TToken): string
# implementation
var
gLinesCompiled*: int
proc fillToken(L: var TToken) =
L.xkind = pxInvalid
L.iNumber = 0
L.s = ""
L.fNumber = 0.0
L.base = base10
proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) =
openBaseLexer(lex, inputstream)
lex.fileIdx = filename.fileInfoIdx
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.fileIdx, L.linenumber, getColNumber(L, L.bufpos))
proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") =
msgs.GlobalError(getLineInfo(L), msg, arg)
proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") =
var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart)
msgs.GlobalError(info, msg, arg)
proc tokKindToStr*(k: TTokKind): string =
case k
of pxEof: result = "[EOF]"
of pxInvalid: result = "[invalid]"
of pxMacroParam: result = "[macro param]"
of pxStarComment, pxLineComment: result = "[comment]"
of pxStrLit: result = "[string literal]"
of pxCharLit: result = "[char literal]"
of pxDirective, pxDirectiveParLe: result = "#" # #define, etc.
of pxDirConc: result = "##"
of pxNewLine: result = "[NewLine]"
of pxAmp: result = "&" # &
of pxAmpAmp: result = "&&" # &&
of pxAmpAsgn: result = "&=" # &=
of pxAmpAmpAsgn: result = "&&=" # &&=
of pxBar: result = "|" # |
of pxBarBar: result = "||" # ||
of pxBarAsgn: result = "|=" # |=
of pxBarBarAsgn: result = "||=" # ||=
of pxNot: result = "!" # !
of pxPlusPlus: result = "++" # ++
of pxMinusMinus: result = "--" # --
of pxPlus: result = "+" # +
of pxPlusAsgn: result = "+=" # +=
of pxMinus: result = "-" # -
of pxMinusAsgn: result = "-=" # -=
of pxMod: result = "%" # %
of pxModAsgn: result = "%=" # %=
of pxSlash: result = "/" # /
of pxSlashAsgn: result = "/=" # /=
of pxStar: result = "*" # *
of pxStarAsgn: result = "*=" # *=
of pxHat: result = "^" # ^
of pxHatAsgn: result = "^=" # ^=
of pxAsgn: result = "=" # =
of pxEquals: result = "==" # ==
of pxDot: result = "." # .
of pxDotDotDot: result = "..." # ...
of pxLe: result = "<=" # <=
of pxLt: result = "<" # <
of pxGe: result = ">=" # >=
of pxGt: result = ">" # >
of pxNeq: result = "!=" # !=
of pxConditional: result = "?"
of pxShl: result = "<<"
of pxShlAsgn: result = "<<="
of pxShr: result = ">>"
of pxShrAsgn: result = ">>="
of pxTilde: result = "~"
of pxTildeAsgn: result = "~="
of pxArrow: result = "->"
of pxScope: 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 pxCurlyLe: result = "{"
of pxCurlyRi: result = "}"
of pxAngleRi: result = "> [end of template]"
proc `$`(tok: TToken): string =
case tok.xkind
of pxSymbol, pxInvalid, pxStarComment, pxLineComment, pxStrLit: result = tok.s
of pxIntLit, pxInt64Lit: result = $tok.iNumber
of pxFloatLit: result = $tok.fNumber
else: result = tokKindToStr(tok.xkind)
proc printTok(tok: TToken) =
writeln(stdout, $tok)
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
# matches ([chars]_)*
var pos = L.bufpos # use registers for pos, buf
var buf = L.buf
while true:
if buf[pos] in chars:
add(tok.s, buf[pos])
inc(pos)
else:
break
if buf[pos] == '_':
add(tok.s, '_')
inc(pos)
L.bufPos = pos
proc isFloatLiteral(s: string): bool =
for i in countup(0, len(s)-1):
if s[i] in {'.', 'e', 'E'}:
return true
proc getNumber2(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 2 # skip 0b
tok.base = base2
var xi: BiggestInt = 0
var bits = 0
while true:
case L.buf[pos]
of 'A'..'Z', 'a'..'z':
# ignore type suffix:
inc(pos)
of '2'..'9', '.':
lexMessage(L, errInvalidNumber)
inc(pos)
of '_':
inc(pos)
of '0', '1':
xi = `shl`(xi, 1) or (ord(L.buf[pos]) - ord('0'))
inc(pos)
inc(bits)
else: break
tok.iNumber = xi
if (bits > 32): tok.xkind = pxInt64Lit
else: tok.xkind = pxIntLit
L.bufpos = pos
proc getNumber8(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 1 # skip 0
tok.base = base8
var xi: BiggestInt = 0
var bits = 0
while true:
case L.buf[pos]
of 'A'..'Z', 'a'..'z':
# ignore type suffix:
inc(pos)
of '8'..'9', '.':
lexMessage(L, errInvalidNumber)
inc(pos)
of '_':
inc(pos)
of '0'..'7':
xi = `shl`(xi, 3) or (ord(L.buf[pos]) - ord('0'))
inc(pos)
inc(bits)
else: break
tok.iNumber = xi
if (bits > 12): tok.xkind = pxInt64Lit
else: tok.xkind = pxIntLit
L.bufpos = pos
proc getNumber16(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 2 # skip 0x
tok.base = base16
var xi: BiggestInt = 0
var bits = 0
while true:
case L.buf[pos]
of 'G'..'Z', 'g'..'z':
# ignore type suffix:
inc(pos)
of '_': inc(pos)
of '0'..'9':
xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0'))
inc(pos)
inc(bits, 4)
of 'a'..'f':
xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('a') + 10)
inc(pos)
inc(bits, 4)
of 'A'..'F':
xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('A') + 10)
inc(pos)
inc(bits, 4)
else: break
tok.iNumber = xi
if bits > 32: tok.xkind = pxInt64Lit
else: tok.xkind = pxIntLit
L.bufpos = pos
proc getFloating(L: var TLexer, tok: var TToken) =
matchUnderscoreChars(L, tok, {'0'..'9'})
if L.buf[L.bufpos] in {'e', 'E'}:
add(tok.s, L.buf[L.bufpos])
inc(L.bufpos)
if L.buf[L.bufpos] in {'+', '-'}:
add(tok.s, L.buf[L.bufpos])
inc(L.bufpos)
matchUnderscoreChars(L, tok, {'0'..'9'})
proc getNumber(L: var TLexer, tok: var TToken) =
tok.base = base10
if L.buf[L.bufpos] == '.':
add(tok.s, "0.")
inc(L.bufpos)
getFloating(L, tok)
else:
matchUnderscoreChars(L, tok, {'0'..'9'})
if L.buf[L.bufpos] == '.':
add(tok.s, '.')
inc(L.bufpos)
getFloating(L, tok)
try:
if isFloatLiteral(tok.s):
tok.fnumber = parseFloat(tok.s)
tok.xkind = pxFloatLit
else:
tok.iNumber = parseInt(tok.s)
if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)):
tok.xkind = pxInt64Lit
else:
tok.xkind = pxIntLit
except EInvalidValue:
lexMessage(L, errInvalidNumber, tok.s)
except EOverflow:
lexMessage(L, errNumberOutOfRange, tok.s)
# ignore type suffix:
while L.buf[L.bufpos] in {'A'..'Z', 'a'..'z'}: inc(L.bufpos)
proc handleCRLF(L: var TLexer, pos: int): int =
case L.buf[pos]
of CR: result = nimlexbase.handleCR(L, pos)
of LF: result = nimlexbase.handleLF(L, pos)
else: result = pos
proc escape(L: var TLexer, tok: var TToken, allowEmpty=false) =
inc(L.bufpos) # skip \
case L.buf[L.bufpos]
of 'b', 'B':
add(tok.s, '\b')
inc(L.bufpos)
of 't', 'T':
add(tok.s, '\t')
inc(L.bufpos)
of 'n', 'N':
add(tok.s, '\L')
inc(L.bufpos)
of 'f', 'F':
add(tok.s, '\f')
inc(L.bufpos)
of 'r', 'R':
add(tok.s, '\r')
inc(L.bufpos)
of '\'':
add(tok.s, '\'')
inc(L.bufpos)
of '"':
add(tok.s, '"')
inc(L.bufpos)
of '\\':
add(tok.s, '\b')
inc(L.bufpos)
of '0'..'7':
var xi = ord(L.buf[L.bufpos]) - ord('0')
inc(L.bufpos)
if L.buf[L.bufpos] in {'0'..'7'}:
xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0'))
inc(L.bufpos)
if L.buf[L.bufpos] in {'0'..'7'}:
xi = (xi shl 3) or (ord(L.buf[L.bufpos]) - ord('0'))
inc(L.bufpos)
add(tok.s, chr(xi))
of 'x':
var xi = 0
inc(L.bufpos)
while true:
case L.buf[L.bufpos]
of '0'..'9':
xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('0'))
inc(L.bufpos)
of 'a'..'f':
xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('a') + 10)
inc(L.bufpos)
of 'A'..'F':
xi = `shl`(xi, 4) or (ord(L.buf[L.bufpos]) - ord('A') + 10)
inc(L.bufpos)
else:
break
add(tok.s, chr(xi))
elif not allowEmpty:
lexMessage(L, errInvalidCharacterConstant)
proc getCharLit(L: var TLexer, tok: var TToken) =
inc(L.bufpos) # skip '
if L.buf[L.bufpos] == '\\':
escape(L, tok)
else:
add(tok.s, L.buf[L.bufpos])
inc(L.bufpos)
if L.buf[L.bufpos] == '\'':
inc(L.bufpos)
else:
lexMessage(L, errMissingFinalQuote)
tok.xkind = pxCharLit
proc getString(L: var TLexer, tok: var TToken) =
var pos = L.bufPos + 1 # skip "
var buf = L.buf # put `buf` in a register
var line = L.linenumber # save linenumber for better error message
while true:
case buf[pos]
of '\"':
inc(pos)
break
of CR:
pos = nimlexbase.HandleCR(L, pos)
buf = L.buf
of LF:
pos = nimlexbase.HandleLF(L, pos)
buf = L.buf
of nimlexbase.EndOfFile:
var line2 = L.linenumber
L.LineNumber = line
lexMessagePos(L, errClosingQuoteExpected, L.lineStart)
L.LineNumber = line2
break
of '\\':
# we allow an empty \ for line concatenation, but we don't require it
# for line concatenation
L.bufpos = pos
escape(L, tok, allowEmpty=true)
pos = L.bufpos
else:
add(tok.s, buf[pos])
inc(pos)
L.bufpos = pos
tok.xkind = pxStrLit
proc getSymbol(L: var TLexer, tok: var TToken) =
var pos = L.bufpos
var buf = L.buf
while true:
var c = buf[pos]
if c notin SymChars: break
add(tok.s, c)
inc(pos)
L.bufpos = pos
tok.xkind = pxSymbol
proc scanLineComment(L: var TLexer, tok: var TToken) =
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 = pxLineComment
var col = getColNumber(L, pos)
while true:
inc(pos, 2) # skip //
add(tok.s, '#')
while not (buf[pos] in {CR, LF, nimlexbase.EndOfFile}):
add(tok.s, buf[pos])
inc(pos)
pos = handleCRLF(L, pos)
buf = L.buf
var indent = 0
while buf[pos] == ' ':
inc(pos)
inc(indent)
if (col == indent) and (buf[pos] == '/') and (buf[pos + 1] == '/'):
add(tok.s, "\n")
else:
break
L.bufpos = pos
proc scanStarComment(L: var TLexer, tok: var TToken) =
var pos = L.bufpos
var buf = L.buf
tok.s = "#"
tok.xkind = pxStarComment
while true:
case buf[pos]
of CR, LF:
pos = handleCRLF(L, pos)
buf = L.buf
add(tok.s, "\n#")
# skip annoying stars as line prefix: (eg.
# /*
# * ugly comment <-- this star
# */
while buf[pos] in {' ', '\t'}:
add(tok.s, ' ')
inc(pos)
if buf[pos] == '*' and buf[pos+1] != '/': inc(pos)
of '*':
inc(pos)
if buf[pos] == '/':
inc(pos)
break
else:
add(tok.s, '*')
of nimlexbase.EndOfFile:
lexMessage(L, errTokenExpected, "*/")
else:
add(tok.s, buf[pos])
inc(pos)
L.bufpos = pos
proc skip(L: var TLexer, tok: var TToken) =
var pos = L.bufpos
var buf = L.buf
while true:
case buf[pos]
of '\\':
# Ignore \ line continuation characters when not inDirective
inc(pos)
if L.inDirective:
while buf[pos] in {' ', '\t'}: inc(pos)
if buf[pos] in {CR, LF}:
pos = handleCRLF(L, pos)
buf = L.buf
of ' ', Tabulator:
inc(pos) # newline is special:
of CR, LF:
pos = handleCRLF(L, pos)
buf = L.buf
if L.inDirective:
tok.xkind = pxNewLine
L.inDirective = false
else:
break # EndOfFile also leaves the loop
L.bufpos = pos
proc getDirective(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 1
var buf = L.buf
while buf[pos] in {' ', '\t'}: inc(pos)
while buf[pos] in SymChars:
add(tok.s, buf[pos])
inc(pos)
# a HACK: we need to distinguish
# #define x (...)
# from:
# #define x(...)
#
L.bufpos = pos
# look ahead:
while buf[pos] in {' ', '\t'}: inc(pos)
while buf[pos] in SymChars: inc(pos)
if buf[pos] == '(': tok.xkind = pxDirectiveParLe
else: tok.xkind = pxDirective
L.inDirective = true
proc getTok(L: var TLexer, tok: var TToken) =
tok.xkind = pxInvalid
fillToken(tok)
skip(L, tok)
if tok.xkind == pxNewLine: return
var c = L.buf[L.bufpos]
if c in SymStartChars:
getSymbol(L, tok)
elif c == '0':
case L.buf[L.bufpos+1]
of 'x', 'X': getNumber16(L, tok)
of 'b', 'B': getNumber2(L, tok)
of '1'..'7': getNumber8(L, tok)
else: getNumber(L, tok)
elif c in {'1'..'9'} or (c == '.' and L.buf[L.bufpos+1] in {'0'..'9'}):
getNumber(L, tok)
else:
case c
of ';':
tok.xkind = pxSemicolon
inc(L.bufpos)
of '/':
if L.buf[L.bufpos + 1] == '/':
scanLineComment(L, tok)
elif L.buf[L.bufpos+1] == '*':
inc(L.bufpos, 2)
scanStarComment(L, tok)
elif L.buf[L.bufpos+1] == '=':
inc(L.bufpos, 2)
tok.xkind = pxSlashAsgn
else:
tok.xkind = pxSlash
inc(L.bufpos)
of ',':
tok.xkind = pxComma
inc(L.bufpos)
of '(':
inc(L.bufpos)
tok.xkind = pxParLe
of '*':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxStarAsgn
else:
tok.xkind = pxStar
of ')':
inc(L.bufpos)
tok.xkind = pxParRi
of '[':
inc(L.bufpos)
tok.xkind = pxBracketLe
of ']':
inc(L.bufpos)
tok.xkind = pxBracketRi
of '.':
inc(L.bufpos)
if L.buf[L.bufpos] == '.' and L.buf[L.bufpos+1] == '.':
tok.xkind = pxDotDotDot
inc(L.bufpos, 2)
else:
tok.xkind = pxDot
of '{':
inc(L.bufpos)
tok.xkind = pxCurlyLe
of '}':
inc(L.bufpos)
tok.xkind = pxCurlyRi
of '+':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
tok.xkind = pxPlusAsgn
inc(L.bufpos)
elif L.buf[L.bufpos] == '+':
tok.xkind = pxPlusPlus
inc(L.bufpos)
else:
tok.xkind = pxPlus
of '-':
inc(L.bufpos)
case L.buf[L.bufpos]
of '>':
tok.xkind = pxArrow
inc(L.bufpos)
of '=':
tok.xkind = pxMinusAsgn
inc(L.bufpos)
of '-':
tok.xkind = pxMinusMinus
inc(L.bufpos)
else:
tok.xkind = pxMinus
of '?':
inc(L.bufpos)
tok.xkind = pxConditional
of ':':
inc(L.bufpos)
if L.buf[L.bufpos] == ':':
tok.xkind = pxScope
inc(L.bufpos)
else:
tok.xkind = pxColon
of '!':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
tok.xkind = pxNeq
inc(L.bufpos)
else:
tok.xkind = pxNot
of '<':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxLe
elif L.buf[L.bufpos] == '<':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxShlAsgn
else:
tok.xkind = pxShl
else:
tok.xkind = pxLt
of '>':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxGe
elif L.buf[L.bufpos] == '>':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxShrAsgn
else:
tok.xkind = pxShr
else:
tok.xkind = pxGt
of '=':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
tok.xkind = pxEquals
inc(L.bufpos)
else:
tok.xkind = pxAsgn
of '&':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
tok.xkind = pxAmpAsgn
inc(L.bufpos)
elif L.buf[L.bufpos] == '&':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxAmpAmpAsgn
else:
tok.xkind = pxAmpAmp
else:
tok.xkind = pxAmp
of '|':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
tok.xkind = pxBarAsgn
inc(L.bufpos)
elif L.buf[L.bufpos] == '|':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxBarBarAsgn
else:
tok.xkind = pxBarBar
else:
tok.xkind = pxBar
of '^':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
tok.xkind = pxHatAsgn
inc(L.bufpos)
else:
tok.xkind = pxHat
of '%':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
tok.xkind = pxModAsgn
inc(L.bufpos)
else:
tok.xkind = pxMod
of '~':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
tok.xkind = pxTildeAsgn
inc(L.bufpos)
else:
tok.xkind = pxTilde
of '#':
if L.buf[L.bufpos+1] == '#':
inc(L.bufpos, 2)
tok.xkind = pxDirConc
else:
getDirective(L, tok)
of '"': getString(L, tok)
of '\'': getCharLit(L, tok)
of nimlexbase.EndOfFile:
tok.xkind = pxEof
else:
tok.s = $c
tok.xkind = pxInvalid
lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
inc(L.bufpos)

File diff suppressed because it is too large Load diff

View file

@ -1,347 +0,0 @@
#
#
# c2nim - C to Nimrod source converter
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# Preprocessor support
const
c2nimSymbol = "C2NIM"
proc eatNewLine(p: var TParser, n: PNode) =
if p.tok.xkind == pxLineComment:
skipCom(p, n)
if p.tok.xkind == pxNewLine: getTok(p)
elif p.tok.xkind == pxNewLine:
eat(p, pxNewLine)
proc skipLine(p: var TParser) =
while p.tok.xkind notin {pxEof, pxNewLine, pxLineComment}: getTok(p)
eatNewLine(p, nil)
proc parseDefineBody(p: var TParser, tmplDef: PNode): string =
if p.tok.xkind == pxCurlyLe or
(p.tok.xkind == pxSymbol and (
declKeyword(p, p.tok.s) or stmtKeyword(p.tok.s))):
addSon(tmplDef, statement(p))
result = "stmt"
elif p.tok.xkind in {pxLineComment, pxNewLine}:
addSon(tmplDef, buildStmtList(newNodeP(nkNilLit, p)))
result = "stmt"
else:
addSon(tmplDef, buildStmtList(expression(p)))
result = "expr"
proc parseDefine(p: var TParser): PNode =
if p.tok.xkind == pxDirectiveParLe:
# a macro with parameters:
result = newNodeP(nkTemplateDef, p)
getTok(p)
addSon(result, skipIdentExport(p))
addSon(result, ast.emptyNode)
eat(p, pxParLe)
var params = newNodeP(nkFormalParams, p)
# return type; not known yet:
addSon(params, ast.emptyNode)
if p.tok.xkind != pxParRi:
var identDefs = newNodeP(nkIdentDefs, p)
while p.tok.xkind != pxParRi:
addSon(identDefs, skipIdent(p))
skipStarCom(p, nil)
if p.tok.xkind != pxComma: break
getTok(p)
addSon(identDefs, newIdentNodeP("expr", p))
addSon(identDefs, ast.emptyNode)
addSon(params, identDefs)
eat(p, pxParRi)
addSon(result, ast.emptyNode) # no generic parameters
addSon(result, params)
addSon(result, ast.emptyNode) # no pragmas
addSon(result, ast.emptyNode)
var kind = parseDefineBody(p, result)
params.sons[0] = newIdentNodeP(kind, p)
eatNewLine(p, result)
else:
# a macro without parameters:
result = newNodeP(nkConstSection, p)
while p.tok.xkind == pxDirective and p.tok.s == "define":
getTok(p) # skip #define
var c = newNodeP(nkConstDef, p)
addSon(c, skipIdentExport(p))
addSon(c, ast.emptyNode)
skipStarCom(p, c)
if p.tok.xkind in {pxLineComment, pxNewLine, pxEof}:
addSon(c, newIdentNodeP("true", p))
else:
addSon(c, expression(p))
addSon(result, c)
eatNewLine(p, c)
assert result != nil
proc parseDefBody(p: var TParser, m: var TMacro, params: seq[string]) =
m.body = @[]
# A little hack: We safe the context, so that every following token will be
# put into a newly allocated TToken object. Thus we can just save a
# reference to the token in the macro's body.
saveContext(p)
while p.tok.xkind notin {pxEof, pxNewLine, pxLineComment}:
case p.tok.xkind
of pxSymbol:
# is it a parameter reference?
var tok = p.tok
for i in 0..high(params):
if params[i] == p.tok.s:
new(tok)
tok.xkind = pxMacroParam
tok.iNumber = i
break
m.body.add(tok)
of pxDirConc:
# just ignore this token: this implements token merging correctly
discard
else:
m.body.add(p.tok)
# we do not want macro expansion here:
rawGetTok(p)
eatNewLine(p, nil)
closeContext(p)
# newline token might be overwritten, but this is not
# part of the macro body, so it is safe.
proc parseDef(p: var TParser, m: var TMacro) =
var hasParams = p.tok.xkind == pxDirectiveParLe
getTok(p)
expectIdent(p)
m.name = p.tok.s
getTok(p)
var params: seq[string] = @[]
# parse parameters:
if hasParams:
eat(p, pxParLe)
while p.tok.xkind != pxParRi:
expectIdent(p)
params.add(p.tok.s)
getTok(p)
skipStarCom(p, nil)
if p.tok.xkind != pxComma: break
getTok(p)
eat(p, pxParRi)
m.params = params.len
parseDefBody(p, m, params)
proc isDir(p: TParser, dir: string): bool =
result = p.tok.xkind in {pxDirectiveParLe, pxDirective} and p.tok.s == dir
proc parseInclude(p: var TParser): PNode =
result = newNodeP(nkImportStmt, p)
while isDir(p, "include"):
getTok(p) # skip "include"
if p.tok.xkind == pxStrLit and pfSkipInclude notin p.options.flags:
var file = newStrNodeP(nkStrLit, changeFileExt(p.tok.s, ""), p)
addSon(result, file)
getTok(p)
skipStarCom(p, file)
eatNewLine(p, nil)
else:
skipLine(p)
if sonsLen(result) == 0:
# we only parsed includes that we chose to ignore:
result = ast.emptyNode
proc definedExprAux(p: var TParser): PNode =
result = newNodeP(nkCall, p)
addSon(result, newIdentNodeP("defined", p))
addSon(result, skipIdent(p))
proc parseStmtList(p: var TParser): PNode =
result = newNodeP(nkStmtList, p)
while true:
case p.tok.xkind
of pxEof: break
of pxDirectiveParLe, pxDirective:
case p.tok.s
of "else", "endif", "elif": break
else: discard
addSon(result, statement(p))
proc eatEndif(p: var TParser) =
if isDir(p, "endif"):
skipLine(p)
else:
parMessage(p, errXExpected, "#endif")
proc parseIfDirAux(p: var TParser, result: PNode) =
addSon(result.sons[0], parseStmtList(p))
while isDir(p, "elif"):
var b = newNodeP(nkElifBranch, p)
getTok(p)
addSon(b, expression(p))
eatNewLine(p, nil)
addSon(b, parseStmtList(p))
addSon(result, b)
if isDir(p, "else"):
var s = newNodeP(nkElse, p)
skipLine(p)
addSon(s, parseStmtList(p))
addSon(result, s)
eatEndif(p)
proc skipUntilEndif(p: var TParser) =
var nested = 1
while p.tok.xkind != pxEof:
if isDir(p, "ifdef") or isDir(p, "ifndef") or isDir(p, "if"):
inc(nested)
elif isDir(p, "endif"):
dec(nested)
if nested <= 0:
skipLine(p)
return
getTok(p)
parMessage(p, errXExpected, "#endif")
type
TEndifMarker = enum
emElif, emElse, emEndif
proc skipUntilElifElseEndif(p: var TParser): TEndifMarker =
var nested = 1
while p.tok.xkind != pxEof:
if isDir(p, "ifdef") or isDir(p, "ifndef") or isDir(p, "if"):
inc(nested)
elif isDir(p, "elif") and nested <= 1:
return emElif
elif isDir(p, "else") and nested <= 1:
return emElse
elif isDir(p, "endif"):
dec(nested)
if nested <= 0:
return emEndif
getTok(p)
parMessage(p, errXExpected, "#endif")
proc parseIfdef(p: var TParser): PNode =
getTok(p) # skip #ifdef
expectIdent(p)
case p.tok.s
of "__cplusplus":
skipUntilEndif(p)
result = ast.emptyNode
of c2nimSymbol:
skipLine(p)
result = parseStmtList(p)
skipUntilEndif(p)
else:
result = newNodeP(nkWhenStmt, p)
addSon(result, newNodeP(nkElifBranch, p))
addSon(result.sons[0], definedExprAux(p))
eatNewLine(p, nil)
parseIfDirAux(p, result)
proc parseIfndef(p: var TParser): PNode =
result = ast.emptyNode
getTok(p) # skip #ifndef
expectIdent(p)
if p.tok.s == c2nimSymbol:
skipLine(p)
case skipUntilElifElseEndif(p)
of emElif:
result = newNodeP(nkWhenStmt, p)
addSon(result, newNodeP(nkElifBranch, p))
getTok(p)
addSon(result.sons[0], expression(p))
eatNewLine(p, nil)
parseIfDirAux(p, result)
of emElse:
skipLine(p)
result = parseStmtList(p)
eatEndif(p)
of emEndif: skipLine(p)
else:
result = newNodeP(nkWhenStmt, p)
addSon(result, newNodeP(nkElifBranch, p))
var e = newNodeP(nkCall, p)
addSon(e, newIdentNodeP("not", p))
addSon(e, definedExprAux(p))
eatNewLine(p, nil)
addSon(result.sons[0], e)
parseIfDirAux(p, result)
proc parseIfDir(p: var TParser): PNode =
result = newNodeP(nkWhenStmt, p)
addSon(result, newNodeP(nkElifBranch, p))
getTok(p)
addSon(result.sons[0], expression(p))
eatNewLine(p, nil)
parseIfDirAux(p, result)
proc parsePegLit(p: var TParser): TPeg =
var col = getColumn(p.lex) + 2
getTok(p)
if p.tok.xkind != pxStrLit: expectIdent(p)
try:
result = parsePeg(
pattern = if p.tok.xkind == pxStrLit: p.tok.s else: escapePeg(p.tok.s),
filename = p.lex.fileIdx.toFilename,
line = p.lex.linenumber,
col = col)
getTok(p)
except EInvalidPeg:
parMessage(p, errUser, getCurrentExceptionMsg())
proc parseMangleDir(p: var TParser) =
var pattern = parsePegLit(p)
if p.tok.xkind != pxStrLit: expectIdent(p)
p.options.mangleRules.add((pattern, p.tok.s))
getTok(p)
eatNewLine(p, nil)
proc modulePragmas(p: var TParser): PNode =
if p.options.dynlibSym.len > 0 and not p.hasDeadCodeElimPragma:
p.hasDeadCodeElimPragma = true
result = newNodeP(nkPragma, p)
var e = newNodeP(nkExprColonExpr, p)
addSon(e, newIdentNodeP("deadCodeElim", p), newIdentNodeP("on", p))
addSon(result, e)
else:
result = ast.emptyNode
proc parseDir(p: var TParser): PNode =
result = ast.emptyNode
assert(p.tok.xkind in {pxDirective, pxDirectiveParLe})
case p.tok.s
of "define": result = parseDefine(p)
of "include": result = parseInclude(p)
of "ifdef": result = parseIfdef(p)
of "ifndef": result = parseIfndef(p)
of "if": result = parseIfDir(p)
of "cdecl", "stdcall", "ref", "skipinclude", "typeprefixes", "skipcomments":
discard setOption(p.options, p.tok.s)
getTok(p)
eatNewLine(p, nil)
of "dynlib", "header", "prefix", "suffix", "class":
var key = p.tok.s
getTok(p)
if p.tok.xkind != pxStrLit: expectIdent(p)
discard setOption(p.options, key, p.tok.s)
getTok(p)
eatNewLine(p, nil)
result = modulePragmas(p)
of "mangle":
parseMangleDir(p)
of "def":
var L = p.options.macros.len
setLen(p.options.macros, L+1)
parseDef(p, p.options.macros[L])
of "private":
var pattern = parsePegLit(p)
p.options.privateRules.add(pattern)
eatNewLine(p, nil)
else:
# ignore unimportant/unknown directive ("undef", "pragma", "error")
skipLine(p)

View file

@ -1,4 +0,0 @@
# Use the modules of the compiler
path: "$nimrod/compiler"

View file

@ -1,40 +0,0 @@
enum vehicles
{
car = 0x10,
truck,
boat = 0x01,
ship = 1,
speedboat = 1,
bicycle = 4,
bobycar
};
enum
{
red = 4,
green = 2,
blue
};
typedef enum food
{
bread = 4,
toast = 4,
bun = 0x04,
cucumber = 2,
chocolate = 6
};
typedef enum numbers
{
one = 1,
two,
nten = - 10,
nnine,
four = 4,
three = + 3,
positivenine = + 9,
nfour = - 4,
negativeten = -10
};

View file

@ -1,240 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
// Name: wx/matrix.h
// Purpose: wxTransformMatrix class. NOT YET USED
// Author: Chris Breeze, Julian Smart
// Modified by: Klaas Holwerda
// Created: 01/02/97
// RCS-ID: $Id$
// Copyright: (c) Julian Smart, Chris Breeze
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
#ifndef _WX_MATRIXH__
#define _WX_MATRIXH__
//! headerfiles="matrix.h wx/object.h"
#include "wx/object.h"
#include "wx/math.h"
//! codefiles="matrix.cpp"
// A simple 3x3 matrix. This may be replaced by a more general matrix
// class some day.
//
// Note: this is intended to be used in wxDC at some point to replace
// the current system of scaling/translation. It is not yet used.
#def WXDLLIMPEXP_CORE
#header "wxmatrix.h"
//:definition
// A 3x3 matrix to do 2D transformations.
// It can be used to map data to window coordinates,
// and also for manipulating your own data.
// For example drawing a picture (composed of several primitives)
// at a certain coordinate and angle within another parent picture.
// At all times m_isIdentity is set if the matrix itself is an Identity matrix.
// It is used where possible to optimize calculations.
class WXDLLIMPEXP_CORE wxTransformMatrix: public wxObject<string, string<ubyte>>
{
public:
wxTransformMatrix(void);
wxTransformMatrix(const wxTransformMatrix& mat);
~wxTransformMatrix(void);
//get the value in the matrix at col,row
//rows are horizontal (second index of m_matrix member)
//columns are vertical (first index of m_matrix member)
double GetValue(int col, int row) const;
//set the value in the matrix at col,row
//rows are horizontal (second index of m_matrix member)
//columns are vertical (first index of m_matrix member)
void SetValue(int col, int row, double value);
void operator = (const wxTransformMatrix& mat);
bool operator == (const wxTransformMatrix& mat) const;
bool operator != (const module::gah::wxTransformMatrix& mat) const;
//multiply every element by t
wxTransformMatrix& operator*=(const double& t);
//divide every element by t
wxTransformMatrix& operator/=(const double& t);
//add matrix m to this t
wxTransformMatrix& operator+=(const wxTransformMatrix& m);
//subtract matrix m from this
wxTransformMatrix& operator-=(const wxTransformMatrix& m);
//multiply matrix m with this
wxTransformMatrix& operator*=(const wxTransformMatrix& m);
// constant operators
//multiply every element by t and return result
wxTransformMatrix operator*(const double& t) const;
//divide this matrix by t and return result
wxTransformMatrix operator/(const double& t) const;
//add matrix m to this and return result
wxTransformMatrix operator+(const wxTransformMatrix& m) const;
//subtract matrix m from this and return result
wxTransformMatrix operator-(const wxTransformMatrix& m) const;
//multiply this by matrix m and return result
wxTransformMatrix operator*(const wxTransformMatrix& m) const;
wxTransformMatrix operator-() const;
//rows are horizontal (second index of m_matrix member)
//columns are vertical (first index of m_matrix member)
double& operator()(int col, int row);
//rows are horizontal (second index of m_matrix member)
//columns are vertical (first index of m_matrix member)
double operator()(int col, int row) const;
// Invert matrix
bool Invert(void);
// Make into identity matrix
bool Identity(void);
// Is the matrix the identity matrix?
// Only returns a flag, which is set whenever an operation
// is done.
inline bool IsIdentity(void) const { return m_isIdentity; }
// This does an actual check.
inline bool IsIdentity1(void) const ;
//Scale by scale (isotropic scaling i.e. the same in x and y):
//!ex:
//!code: | scale 0 0 |
//!code: matrix' = | 0 scale 0 | x matrix
//!code: | 0 0 scale |
bool Scale(double scale);
//Scale with center point and x/y scale
//
//!ex:
//!code: | xs 0 xc(1-xs) |
//!code: matrix' = | 0 ys yc(1-ys) | x matrix
//!code: | 0 0 1 |
wxTransformMatrix& Scale(const double &xs, const double &ys,const double &xc, const double &yc);
// mirror a matrix in x, y
//!ex:
//!code: | -1 0 0 |
//!code: matrix' = | 0 -1 0 | x matrix
//!code: | 0 0 1 |
wxTransformMatrix<float>& Mirror(bool x=true, bool y=false);
// Translate by dx, dy:
//!ex:
//!code: | 1 0 dx |
//!code: matrix' = | 0 1 dy | x matrix
//!code: | 0 0 1 |
bool Translate(double x, double y);
// Rotate clockwise by the given number of degrees:
//!ex:
//!code: | cos sin 0 |
//!code: matrix' = | -sin cos 0 | x matrix
//!code: | 0 0 1 |
bool Rotate(double angle);
//Rotate counter clockwise with point of rotation
//
//!ex:
//!code: | cos(r) -sin(r) x(1-cos(r))+y(sin(r)|
//!code: matrix' = | sin(r) cos(r) y(1-cos(r))-x(sin(r)| x matrix
//!code: | 0 0 1 |
wxTransformMatrix& Rotate(const double &r, const double &x, const double &y);
// Transform X value from logical to device
inline double TransformX(double x) const;
// Transform Y value from logical to device
inline double TransformY(double y) const;
// Transform a point from logical to device coordinates
bool TransformPoint(double x, double y, double& tx, double& ty) const;
// Transform a point from device to logical coordinates.
// Example of use:
// wxTransformMatrix mat = dc.GetTransformation();
// mat.Invert();
// mat.InverseTransformPoint(x, y, x1, y1);
// OR (shorthand:)
// dc.LogicalToDevice(x, y, x1, y1);
// The latter is slightly less efficient if we're doing several
// conversions, since the matrix is inverted several times.
// N.B. 'this' matrix is the inverse at this point
bool InverseTransformPoint(double x, double y, double& tx, double& ty) const;
double Get_scaleX();
double Get_scaleY();
double GetRotation();
void SetRotation(double rotation);
public:
double m_matrix[3][3];
bool m_isIdentity;
};
/*
Chris Breeze reported, that
some functions of wxTransformMatrix cannot work because it is not
known if he matrix has been inverted. Be careful when using it.
*/
// Transform X value from logical to device
// warning: this function can only be used for this purpose
// because no rotation is involved when mapping logical to device coordinates
// mirror and scaling for x and y will be part of the matrix
// if you have a matrix that is rotated, eg a shape containing a matrix to place
// it in the logical coordinate system, use TransformPoint
inline double wxTransformMatrix::TransformX(double x) const
{
//normally like this, but since no rotation is involved (only mirror and scale)
//we can do without Y -> m_matrix[1]{0] is -sin(rotation angle) and therefore zero
//(x * m_matrix[0][0] + y * m_matrix[1][0] + m_matrix[2][0]))
return (m_isIdentity ? x : (x * m_matrix[0][0] + m_matrix[2][0]));
}
// Transform Y value from logical to device
// warning: this function can only be used for this purpose
// because no rotation is involved when mapping logical to device coordinates
// mirror and scaling for x and y will be part of the matrix
// if you have a matrix that is rotated, eg a shape containing a matrix to place
// it in the logical coordinate system, use TransformPoint
inline double wxTransformMatrix::TransformY(double y) const
{
//normally like this, but since no rotation is involved (only mirror and scale)
//we can do without X -> m_matrix[0]{1] is sin(rotation angle) and therefore zero
//(x * m_matrix[0][1] + y * m_matrix[1][1] + m_matrix[2][1]))
return (m_isIdentity ? y : (y * m_matrix[1][1] + m_matrix[2][1]));
}
// Is the matrix the identity matrix?
// Each operation checks whether the result is still the identity matrix and sets a flag.
inline bool wxTransformMatrix::IsIdentity1(void) const
{
return
( wxIsSameDouble(m_matrix[0][0], 1.0) &&
wxIsSameDouble(m_matrix[1][1], 1.0) &&
wxIsSameDouble(m_matrix[2][2], 1.0) &&
wxIsSameDouble(m_matrix[1][0], 0.0) &&
wxIsSameDouble(m_matrix[2][0], 0.0) &&
wxIsSameDouble(m_matrix[0][1], 0.0) &&
wxIsSameDouble(m_matrix[2][1], 0.0) &&
wxIsSameDouble(m_matrix[0][2], 0.0) &&
wxIsSameDouble(m_matrix[1][2], 0.0) );
}
// Calculates the determinant of a 2 x 2 matrix
inline double wxCalculateDet(double a11, double a21, double a12, double a22)
{
return a11 * a22 - a12 * a21;
}
#endif // _WX_MATRIXH__

View file

@ -1,27 +0,0 @@
struct normal{
int a;
int b;
};
typedef struct outerStruct {
struct normal a_nomal_one;
int a;
struct {
union {
int b;
} a_union_in_the_struct;
int c;
};
union {
int d;
struct {
int e;
} a_struct_in_the_union;
} a_union;
};

View file

@ -1,622 +0,0 @@
/* This file has been written by Blablub.
*
* Another comment line.
*/
#ifdef __cplusplus
# ifdef __SOME_OTHER_CRAP
extern "C" {
# endif
#endif
#define interrupts() sei()
enum
{
/* 8bit, color or not */
CV_LOAD_IMAGE_UNCHANGED =-1,
/* 8bit, gray */
CV_LOAD_IMAGE_GRAYSCALE =0,
/* ?, color */
CV_LOAD_IMAGE_COLOR =1,
/* any depth, ? */
CV_LOAD_IMAGE_ANYDEPTH =2,
/* ?, any color */
CV_LOAD_IMAGE_ANYCOLOR =4
};
typedef void (*callback_t) (int rc);
typedef const char* (*callback2)(int rc, long L, const char* buffer);
int aw_callback_set (AW_CALLBACK c, callback_t callback );
int aw_instance_callback_set (AW_CALLBACK c, callback_t callback);
unsigned long int wawa;
#define MAX(x, y) ((x) < (y)? (y) : (x))
#define AW_BUILD 85 // AW 5.0
// Limits
#define AW_MAX_AVCHANGE_PER_SECOND 10
#private expatDll
#if !defined(expatDll)
# if defined(windows)
# define expatDll "expat.dll"
# elif defined(macosx)
# define expatDll "libexpat.dynlib"
# else
# define expatDll "libexpat.so(.1|)"
# endif
#endif
#mangle "'XML_'{.*}" "$1"
#private "'XML_ParserStruct'"
#mangle cuint cint
unsigned int uiVar;
#private "@('_'!.)"
unsigned int myPrivateVar__;
struct XML_ParserStruct;
#def XMLCALL __cdecl
typedef void (XMLCALL *XML_ElementDeclHandler) (void *userData,
const XML_Char *name,
XML_Content *model);
void* x;
void* fn(void);
void (*fn)(void);
void* (*fn)(void);
void* (*fn)(void*);
/*
* Very ugly real world code ahead:
*/
#def JMETHOD(rettype, name, params) rettype (*name) params
typedef struct cjpeg_source_struct * cjpeg_source_ptr;
struct cjpeg_source_struct {
JMETHOD(void, start_input, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
JMETHOD(void, finish_input, (j_compress_ptr cinfo,
cjpeg_source_ptr sinfo));
FILE *input_file;
JSAMPARRAY buffer;
JDIMENSION buffer_height;
};
// Test standalone structs:
union myunion {
char x, y, *z;
myint a, b;
} u;
struct mystruct {
char x, y, *z;
myint a, b;
};
struct mystruct fn(i32 x, i64 y);
struct mystruct {
char x, y, *z;
myint a, b;
} *myvar = NULL, **myvar2 = NULL;
// anonymous struct:
struct {
char x, y, *z;
myint a, b;
} varX, **varY;
// empty anonymous struct:
struct {
} varX, **varY;
// Test C2NIM skipping:
#define MASK(x) ((x) & 0xff)
#define CAST1(x) ((int) &x)
#define CAST2(x) (typ*) &x
#define CAST3(x) ((const unsigned char**) &x)
#ifndef C2NIM
#if someNestedCond
This is an invalid text that should generate a parser error, if not
#endif
skipped correctly.
#endif
#ifndef C2NIM
#if someNestedCond
This is an invalid text that should generate a parser error, if not
#endif
skipped correctly.
#else
typedef char gchar;
typedef unsigned int gunsignedint;
typedef unsigned char guchar;
#endif
#ifdef C2NIM
# mangle "'those'" "these"
int those;
#elif abc
#if someNestedCond
This is an invalid text that should generate a parser error, if not
#else
skipped correctly.
#endif
#else
Another crappy input line.
#endif
point* newPoint(void) {
for (int i = 0; i < 89; ++i) echo("test" " string " "concatenation");
for (; j < 54; j++) {}
for (;; j--) ;
for (;;) {}
mytype * x = y * z;
if (**p == ' ') {
--p;
} else if (**p == '\t') {
p += 3;
} else {
p = 45 + (mytype*)45;
p = 45 + ((mytype*)45);
p = 45 + ((mytype)45);
// BUG: This does not parse:
// p = 45 + (mytype)45;
}
while (x >= 6 && x <= 20)
--x;
switch (*p) {
case 'A'...'Z':
case 'a'...'z':
++p;
break;
case '0':
++p;
break;
default:
return NULL;
}
}
enum {
a1, a2 = 4, a3
};
typedef enum crazyTAG {
x1, x2, x3 = 8, x4, x5
} myEnum, *pMyEnum;
typedef enum {
x1, x2, x3 = 8, x4, x5
} myEnum, *pMyEnum;
// Test multi-line macro:
#define MUILTILINE "abc" \
"xyz" \
"def"
#define MULTILINE(x, y) do { \
++y; ++x; \
} while (0)
#ifdef C2NIM
# dynlib iupdll
# cdecl
# mangle "'GTK_'{.*}" "TGtk$1"
# mangle "'PGTK_'{.*}" "PGtk$1"
# if defined(windows)
# define iupdll "iup.dll"
# elif defined(macosx)
# define iupdll "libiup.dynlib"
# else
# define iupdll "libiup.so"
# endif
#endif
typedef struct stupidTAG {
mytype a, b;
} GTK_MyStruct, *PGTK_MyStruct;
typedef struct {
mytype a, b;
} GTK_MyStruct, *PGTK_MyStruct;
int IupConvertXYToPos(PIhandle ih, int x, int y);
#ifdef DEBUG
# define OUT(x) printf("%s\n", x)
#else
# define OUT(x)
#endif
#ifdef C2NIM
# def EXTERN(x) static x
# def TWO_ARGS(x, y) x* y
#endif
// parses now!
EXTERN(int) f(void);
EXTERN(int) g(void);
#def EXPORT
// does parse now!
EXPORT int f(void);
EXPORT int g(void);
static TWO_ARGS(int, x) = TWO_ARGS(56, 45);
# define abc 34
# define xyz 42
# define wuseldusel "my string\nconstant"
#undef ignoreThis
char* x;
typedef struct {
char x, y, *z;
} point;
char* __stdcall printf(char* frmt, const char* const** ptrToStrArray,
const int* const dummy, ...);
inline char* myinlineProc(char* frmt, const char* const* strArray,
const int* const dummy, ...);
// Test void parameter list:
void myVoidProc(void);
void emptyReturn(void) { return; }
// POSIX stuff:
#ifdef C2NIM
#prefix posix_
int c2nimBranch;
#elif defined(MACOSX)
int* x, y, z;
#else
int dummy;
#endif
#ifndef C2NIM
int dontTranslateThis;
#elif defined(Windows)
int WindowsTrue = true;
#endif
int posix_spawn(pid_t *restrict, const char *restrict,
const posix_spawn_file_actions_t *,
const posix_spawnattr_t *restrict, char *const [restrict],
char *const [restrict]);
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *,
int);
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *,
int, int);
int posix_spawn_file_actions_addopen(posix_spawn_file_actions_t *restrict,
int, const char *restrict, int, mode_t);
int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *);
int posix_spawn_file_actions_init(posix_spawn_file_actions_t *);
int posix_spawnattr_destroy(posix_spawnattr_t *);
int posix_spawnattr_getsigdefault(const posix_spawnattr_t *restrict,
sigset_t *restrict);
int posix_spawnattr_getflags(const posix_spawnattr_t *restrict,
short *restrict);
int posix_spawnattr_getpgroup(const posix_spawnattr_t *restrict,
pid_t *restrict);
int posix_spawnattr_getschedparam(const posix_spawnattr_t *restrict,
struct sched_param *restrict);
int posix_spawnattr_getschedpolicy(const posix_spawnattr_t *restrict,
int *restrict);
int posix_spawnattr_getsigmask(const posix_spawnattr_t *restrict,
sigset_t *restrict);
int posix_spawnattr_init(posix_spawnattr_t *);
int posix_spawnattr_setsigdefault(posix_spawnattr_t *restrict,
const sigset_t *restrict);
int posix_spawnattr_setflags(posix_spawnattr_t *, short);
int posix_spawnattr_setpgroup(posix_spawnattr_t *, pid_t);
int posix_spawnattr_setschedparam(posix_spawnattr_t *restrict,
const struct sched_param *restrict);
int posix_spawnattr_setschedpolicy(posix_spawnattr_t *, int);
int posix_spawnattr_setsigmask(posix_spawnattr_t *restrict,
const sigset_t *restrict);
int posix_spawnp(pid_t *restrict, const char *restrict,
const posix_spawn_file_actions_t *,
const posix_spawnattr_t *restrict,
char *const [restrict], char *const [restrict]);
typedef struct
{
float R, G, B;
}
RGBType;
typedef struct
{
float H, W, B;
}
HWBType;
static HWBType *
RGB_to_HWB (RGBType RGB, HWBType * HWB)
{
HWBType* myArray[20];
/*
* RGB are each on [0, 1]. W and B are returned on [0, 1] and H is
* returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B.
*/
float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f;
int i;
w = MIN3 (R, G, B);
v = MAX3 (R, G, B);
b &= 1 - v;
if (v == w)
RETURN_HWB (HWB_UNDEFINED, w, b);
f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
i = (R == w) ? 3 : ((G == w) ? 5 : 1);
RETURN_HWB (i - f / (v - w), w, b);
}
static int
clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim)
{
double m; // gradient of line
if (*x0 < mindim)
{ // start of line is left of window
if (*x1 < mindim) // as is the end, so the line never cuts the window
return 0;
m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line
// adjust x0 to be on the left boundary (ie to be zero), and y0 to match
*y0 -= m * (*x0 - mindim);
*x0 = mindim;
// now, perhaps, adjust the far end of the line as well
if (*x1 > maxdim)
{
*y1 += m * (maxdim - *x1);
*x1 = maxdim;
}
return 1;
}
if (*x0 > maxdim)
{ // start of line is right of window - complement of above
if (*x1 > maxdim) // as is the end, so the line misses the window
return 0;
m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line
*y0 += m * (maxdim - *x0); // adjust so point is on the right
// boundary
*x0 = maxdim;
// now, perhaps, adjust the end of the line
if (*x1 < mindim)
{
*y1 -= m * (*x1 - mindim);
*x1 = mindim;
}
return 1;
}
// the final case - the start of the line is inside the window
if (*x1 > maxdim)
{ // other end is outside to the right
m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of the line
*y1 += m * (maxdim - *x1);
*x1 = maxdim;
return 1;
}
if (*x1 < mindim)
{ // other end is outside to the left
m = (*y1 - *y0) / (double) (*x1 - *x0); // calculate the slope of line
*y1 -= m * (*x1 - mindim);
*x1 = mindim;
return 1;
}
// only get here if both points are inside the window
return 1;
}
// end of line clipping code
static void
gdImageBrushApply (gdImagePtr im, int x, int y)
{
int lx, ly;
int hy;
int hx;
int x1, y1, x2, y2;
int srcx, srcy;
if (!im->brush)
{
return;
}
hy = gdImageSY (im->brush) / 2;
y1 = y - hy;
y2 = y1 + gdImageSY (im->brush);
hx = gdImageSX (im->brush) / 2;
x1 = x - hx;
x2 = x1 + gdImageSX (im->brush);
srcy = 0;
if (im->trueColor)
{
if (im->brush->trueColor)
{
for (ly = y1; (ly < y2); ly++)
{
srcx = 0;
for (lx = x1; (lx < x2); lx++)
{
int p;
p = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
// 2.0.9, Thomas Winzig: apply simple full transparency
if (p != gdImageGetTransparent (im->brush))
{
gdImageSetPixel (im, lx, ly, p);
}
srcx++;
}
srcy++;
}
}
else
{
// 2.0.12: Brush palette, image truecolor (thanks to Thorben Kundinger
// for pointing out the issue)
for (ly = y1; (ly < y2); ly++)
{
srcx = 0;
for (lx = x1; (lx < x2); lx++)
{
int p, tc;
p = gdImageGetPixel (im->brush, srcx, srcy);
tc = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
// 2.0.9, Thomas Winzig: apply simple full transparency
if (p != gdImageGetTransparent (im->brush))
{
gdImageSetPixel (im, lx, ly, tc);
}
srcx++;
}
srcy++;
}
}
}
else
{
for (ly = y1; (ly < y2); ly++)
{
srcx = 0;
for (lx = x1; (lx < x2); lx++)
{
int p;
p = gdImageGetPixel (im->brush, srcx, srcy);
// Allow for non-square brushes!
if (p != gdImageGetTransparent (im->brush))
{
// Truecolor brush. Very slow
// on a palette destination.
if (im->brush->trueColor)
{
gdImageSetPixel (im, lx, ly,
gdImageColorResolveAlpha(im,
gdTrueColorGetRed(p),
gdTrueColorGetGreen(p),
gdTrueColorGetBlue(p),
gdTrueColorGetAlpha(p)));
}
else
{
gdImageSetPixel (im, lx, ly, im->brushColorMap[p]);
}
}
srcx++;
}
srcy++;
}
}
}
void gdImageSetPixel (gdImagePtr im, int x, int y, int color)
{
int p;
switch (color)
{
case gdStyled:
if (!im->style)
{
// Refuse to draw if no style is set.
return;
}
else
{
p = im->style[im->stylePos++];
}
if (p != (gdTransparent))
{
gdImageSetPixel (im, x, y, p);
}
im->stylePos = im->stylePos % im->styleLength;
break;
case gdStyledBrushed:
if (!im->style)
{
// Refuse to draw if no style is set.
return;
}
p = im->style[im->stylePos++];
if ((p != gdTransparent) && (p != 0))
{
gdImageSetPixel (im, x, y, gdBrushed);
}
im->stylePos = im->stylePos % im->styleLength;
break;
case gdBrushed:
gdImageBrushApply (im, x, y);
break;
case gdTiled:
gdImageTileApply (im, x, y);
break;
case gdAntiAliased:
// This shouldn't happen (2.0.26) because we just call
// gdImageAALine now, but do something sane.
gdImageSetPixel(im, x, y, im->AA_color);
break;
default:
if (gdImageBoundsSafeMacro (im, x, y))
{
if (im->trueColor)
{
if (im->alphaBlendingFlag)
{
im->tpixels[y][x] = gdAlphaBlend (im->tpixels[y][x], color);
}
else
{
im->tpixels[y][x] = color;
}
}
else
{
im->pixels[y][x] = color;
}
}
break;
}
}
#ifdef __cplusplus
}
#endif

View file

@ -1,17 +0,0 @@
#ifdef C2NIM
# header "iup.h"
# cdecl
# mangle "'GTK_'{.*}" "TGtk$1"
# mangle "'PGTK_'{.*}" "PGtk$1"
#endif
typedef struct stupidTAG {
mytype a, b;
} GTK_MyStruct, *PGTK_MyStruct;
typedef struct {
mytype a, b;
} GTK_MyStruct, *PGTK_MyStruct;
int IupConvertXYToPos(PIhandle ih, int x, int y);

View file

@ -1,33 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
int rand(void);
int id2(void) {
return (int *)1;
}
int id(void (*f)(void)) {
f();
((void (*)(int))f)(10);
return 10;
return (20+1);
return (int *)id;
}
int main() {
float f = .2,
g = 2.,
h = 1.0+rand(),
i = 1.0e+3;
int j, a;
for(j = 0, a = 10; j < 0; j++, a++) ;
do {
printf("howdy");
} while(--i, 0);
if(1)
printf("1"); // error from this comment
else
printf("2");
return '\x00';
}

View file

@ -1,3 +0,0 @@
struct foo {
int x,y,z;
};

File diff suppressed because it is too large Load diff

View file

@ -64,6 +64,22 @@ proc createObj*(owner: PSym, info: TLineInfo): PType =
incl result.flags, tfFinal
result.n = newNodeI(nkRecList, info)
proc rawAddField*(obj: PType; field: PSym) =
assert field.kind == skField
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
proc rawIndirectAccess*(a: PNode; field: PSym; info: TLineInfo): PNode =
# returns a[].field as a node
assert field.kind == skField
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst).sons[0]
addSon(deref, a)
result = newNodeI(nkDotExpr, info)
addSon(result, deref)
addSon(result, newSymNode(field))
result.typ = field.typ
proc addField*(obj: PType; s: PSym) =
# because of 'gensym' support, we have to mangle the name with its ID.
# This is hacky but the clean solution is much more complex than it looks.
@ -74,6 +90,16 @@ proc addField*(obj: PType; s: PSym) =
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
proc addUniqueField*(obj: PType; s: PSym) =
let fieldName = getIdent(s.name.s & $s.id)
if lookupInRecord(obj.n, fieldName) == nil:
var field = newSym(skField, fieldName, s.owner, s.info)
let t = skipIntLit(s.typ)
field.typ = t
assert t.kind != tyStmt
field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field))
proc newDotExpr(obj, b: PSym): PNode =
result = newNodeI(nkDotExpr, obj.info)
let field = getSymFromList(obj.typ.n, getIdent(b.name.s & $b.id))
@ -95,13 +121,28 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
t = t.sons[0]
if t == nil: break
t = t.skipTypes(abstractInst)
assert field != nil, b
#if field == nil:
# debug deref.typ
# echo deref.typ.id
internalAssert field != nil
addSon(deref, a)
result = newNodeI(nkDotExpr, info)
addSon(result, deref)
addSon(result, newSymNode(field))
result.typ = field.typ
proc getFieldFromObj*(t: PType; v: PSym): PSym =
assert v.kind != skField
let fieldName = getIdent(v.name.s & $v.id)
var t = t
while true:
assert t.kind == tyObject
result = getSymFromList(t.n, fieldName)
if result != nil: break
t = t.sons[0]
if t == nil: break
t = t.skipTypes(abstractInst)
proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
# returns a[].b as a node
result = indirectAccess(a, b.name.s & $b.id, info)

View file

@ -27,6 +27,8 @@ var
gSysTypes: array[TTypeKind, PType]
compilerprocs: TStrTable
proc nilOrSysInt*: PType = gSysTypes[tyInt]
proc registerSysType(t: PType) =
if gSysTypes[t.kind] == nil: gSysTypes[t.kind] = t

View file

@ -1,4 +0,0 @@
# Use the modules of the compiler
path: "$nimrod/compiler"

View file

@ -1,64 +0,0 @@
#
#
# Pas2nim - Pascal to Nimrod source converter
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import
strutils, os, parseopt, llstream, ast, renderer, options, msgs,
paslex, pasparse
const
Version = "0.8"
Usage = """
pas2nim - Pascal to Nimrod source converter
(c) 2012 Andreas Rumpf
Usage: pas2nim [options] inputfile [options]
Options:
-o, --out:FILE set output filename
--ref convert ^typ to ref typ (default: ptr typ)
--boot use special translation rules for the Nimrod compiler
-v, --version write pas2nim's version
-h, --help show this help
"""
proc main(infile, outfile: string, flags: set[TParserFlag]) =
var stream = llStreamOpen(infile, fmRead)
if stream == nil: rawMessage(errCannotOpenFile, infile)
var p: TParser
openParser(p, infile, stream, flags)
var module = parseUnit(p)
closeParser(p)
renderModule(module, outfile)
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 = val
of "ref": incl(flags, pfRefs)
of "boot": flags = flags + {pfRefs, pfMoreReplacements, pfImportBlackList}
else: stdout.writeln("[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

@ -1,570 +0,0 @@
#
#
# Pas2nim - Pascal to Nimrod source converter
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# This module implements a FreePascal scanner. This is an adaption from
# the scanner module.
import
hashes, options, msgs, strutils, platform, idents, nimlexbase, llstream
const
MaxLineLength* = 80 # lines longer than this lead to a warning
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'}
# keywords are sorted!
type
TTokKind* = enum
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,
pxImplementation, pxIn, pxInherited, pxInitialization, pxInline,
pxInterface, pxIs, pxLabel, pxLibrary, pxMod, pxNil, pxNot, pxObject, pxOf,
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,
pxComment, # ordinary comment
pxCommand, # {@}
pxAmp, # {&}
pxPer, # {%}
pxStrLit, pxSymbol, # a symbol
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,
pxLe, pxLt, pxGe, pxGt, pxNeq, pxAt, pxStarDirLe, pxStarDirRi, pxCurlyDirLe,
pxCurlyDirRi
TTokKinds* = set[TTokKind]
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",
"interface", "is", "label", "library", "mod", "nil", "not", "object", "of",
"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"]
firstKeyword = pxAnd
lastKeyword = pxXor
type
TNumericalBase* = enum base10, base2, base8, base16
TToken* = object
xkind*: TTokKind # 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
TLexer* = object of TBaseLexer
filename*: string
proc getTok*(L: var TLexer, tok: var TToken)
proc printTok*(tok: TToken)
proc `$`*(tok: TToken): string
# implementation
var
dummyIdent: PIdent
gLinesCompiled: int
proc fillToken(L: var TToken) =
L.xkind = pxInvalid
L.iNumber = 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.filename = filename
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.globalError(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.globalError(info, msg, arg)
proc tokKindToStr*(k: TTokKind): string =
case k
of pxEof: result = "[EOF]"
of firstKeyword..lastKeyword:
result = Keywords[ord(k)-ord(firstKeyword)]
of pxInvalid, pxComment, pxStrLit: result = "string literal"
of pxCommand: result = "{@"
of pxAmp: result = "{&"
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 `$`(tok: TToken): string =
case tok.xkind
of pxInvalid, pxComment, pxStrLit: result = tok.literal
of pxSymbol: result = tok.ident.s
of pxIntLit, pxInt64Lit: result = $tok.iNumber
of pxFloatLit: result = $tok.fNumber
else: result = tokKindToStr(tok.xkind)
proc printTok(tok: TToken) =
writeln(stdout, $tok)
proc setKeyword(L: var TLexer, tok: var TToken) =
var x = binaryStrSearch(keywords, toLower(tok.ident.s))
if x < 0: tok.xkind = pxSymbol
else: tok.xKind = TTokKind(x + ord(firstKeyword))
proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) =
# matches ([chars]_)*
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])
inc(pos)
else:
break
if buf[pos] == '_':
add(tok.literal, '_')
inc(pos)
L.bufPos = pos
proc isFloatLiteral(s: string): bool =
for i in countup(0, len(s)-1):
if s[i] in {'.', 'e', 'E'}:
return true
proc getNumber2(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 1 # skip %
if not (L.buf[pos] in {'0'..'1'}):
# BUGFIX for %date%
tok.xkind = pxInvalid
add(tok.literal, '%')
inc(L.bufpos)
return
tok.base = base2
var xi: BiggestInt = 0
var bits = 0
while true:
case L.buf[pos]
of 'A'..'Z', 'a'..'z', '2'..'9', '.':
lexMessage(L, errInvalidNumber)
inc(pos)
of '_':
inc(pos)
of '0', '1':
xi = `shl`(xi, 1) or (ord(L.buf[pos]) - ord('0'))
inc(pos)
inc(bits)
else: break
tok.iNumber = xi
if (bits > 32): tok.xkind = pxInt64Lit
else: tok.xkind = pxIntLit
L.bufpos = pos
proc getNumber16(L: var TLexer, tok: var TToken) =
var pos = L.bufpos + 1 # skip $
tok.base = base16
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 '0'..'9':
xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('0'))
inc(pos)
inc(bits, 4)
of 'a'..'f':
xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('a') + 10)
inc(pos)
inc(bits, 4)
of 'A'..'F':
xi = `shl`(xi, 4) or (ord(L.buf[pos]) - ord('A') + 10)
inc(pos)
inc(bits, 4)
else: break
tok.iNumber = xi
if (bits > 32):
tok.xkind = pxInt64Lit
else:
tok.xkind = pxIntLit
L.bufpos = pos
proc getNumber10(L: var TLexer, tok: var TToken) =
tok.base = base10
matchUnderscoreChars(L, tok, {'0'..'9'})
if (L.buf[L.bufpos] == '.') and (L.buf[L.bufpos + 1] in {'0'..'9'}):
add(tok.literal, '.')
inc(L.bufpos)
matchUnderscoreChars(L, tok, {'e', 'E', '+', '-', '0'..'9'})
try:
if isFloatLiteral(tok.literal):
tok.fnumber = parseFloat(tok.literal)
tok.xkind = pxFloatLit
else:
tok.iNumber = parseInt(tok.literal)
if (tok.iNumber < low(int32)) or (tok.iNumber > high(int32)):
tok.xkind = pxInt64Lit
else:
tok.xkind = pxIntLit
except EInvalidValue:
lexMessage(L, errInvalidNumber, tok.literal)
except EOverflow:
lexMessage(L, errNumberOutOfRange, tok.literal)
proc handleCRLF(L: var TLexer, pos: int): int =
case L.buf[pos]
of CR: result = nimlexbase.handleCR(L, pos)
of LF: result = nimlexbase.handleLF(L, pos)
else: result = pos
proc getString(L: var TLexer, tok: var TToken) =
var xi: int
var pos = L.bufPos
var buf = L.buf
while true:
if buf[pos] == '\'':
inc(pos)
while true:
case buf[pos]
of CR, LF, nimlexbase.EndOfFile:
lexMessage(L, errClosingQuoteExpected)
break
of '\'':
inc(pos)
if buf[pos] == '\'':
inc(pos)
add(tok.literal, '\'')
else:
break
else:
add(tok.literal, buf[pos])
inc(pos)
elif buf[pos] == '#':
inc(pos)
xi = 0
case buf[pos]
of '$':
inc(pos)
xi = 0
while true:
case buf[pos]
of '0'..'9': xi = (xi shl 4) or (ord(buf[pos]) - ord('0'))
of 'a'..'f': xi = (xi shl 4) or (ord(buf[pos]) - ord('a') + 10)
of 'A'..'F': xi = (xi shl 4) or (ord(buf[pos]) - ord('A') + 10)
else: break
inc(pos)
of '0'..'9':
xi = 0
while buf[pos] in {'0'..'9'}:
xi = (xi * 10) + (ord(buf[pos]) - ord('0'))
inc(pos)
else: lexMessage(L, errInvalidCharacterConstant)
if (xi <= 255): add(tok.literal, chr(xi))
else: lexMessage(L, errInvalidCharacterConstant)
else:
break
tok.xkind = pxStrLit
L.bufpos = pos
proc getSymbol(L: var TLexer, tok: var TToken) =
var h: THash = 0
var pos = L.bufpos
var buf = L.buf
while true:
var c = buf[pos]
case c
of 'a'..'z', '0'..'9', '\x80'..'\xFF':
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
of 'A'..'Z':
c = chr(ord(c) + (ord('a') - ord('A'))) # toLower()
h = h +% ord(c)
h = h +% h shl 10
h = h xor (h shr 6)
of '_': discard
else: break
inc(pos)
h = h +% h shl 3
h = h xor (h shr 11)
h = h +% h shl 15
tok.ident = getIdent(addr(L.buf[L.bufpos]), pos - L.bufpos, h)
L.bufpos = pos
setKeyword(L, tok)
proc scanLineComment(L: var TLexer, tok: var TToken) =
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
var col = getColNumber(L, pos)
while true:
inc(pos, 2) # skip //
add(tok.literal, '#')
while not (buf[pos] in {CR, LF, nimlexbase.EndOfFile}):
add(tok.literal, buf[pos])
inc(pos)
pos = handleCRLF(L, pos)
buf = L.buf
var indent = 0
while buf[pos] == ' ':
inc(pos)
inc(indent)
if (col == indent) and (buf[pos] == '/') and (buf[pos + 1] == '/'):
tok.literal = tok.literal & "\n"
else:
break
L.bufpos = pos
proc scanCurlyComment(L: var TLexer, tok: var TToken) =
var pos = L.bufpos
var buf = L.buf
tok.literal = "#"
tok.xkind = pxComment
while true:
case buf[pos]
of CR, LF:
pos = handleCRLF(L, pos)
buf = L.buf
add(tok.literal, "\n#")
of '}':
inc(pos)
break
of nimlexbase.EndOfFile: lexMessage(L, errTokenExpected, "}")
else:
add(tok.literal, buf[pos])
inc(pos)
L.bufpos = pos
proc scanStarComment(L: var TLexer, tok: var TToken) =
var pos = L.bufpos
var buf = L.buf
tok.literal = "#"
tok.xkind = pxComment
while true:
case buf[pos]
of CR, LF:
pos = handleCRLF(L, pos)
buf = L.buf
add(tok.literal, "\n#")
of '*':
inc(pos)
if buf[pos] == ')':
inc(pos)
break
else:
add(tok.literal, '*')
of nimlexbase.EndOfFile:
lexMessage(L, errTokenExpected, "*)")
else:
add(tok.literal, buf[pos])
inc(pos)
L.bufpos = pos
proc skip(L: var TLexer, tok: var TToken) =
var pos = L.bufpos
var buf = L.buf
while true:
case buf[pos]
of ' ', Tabulator:
inc(pos) # newline is special:
of CR, LF:
pos = handleCRLF(L, pos)
buf = L.buf
else:
break # EndOfFile also leaves the loop
L.bufpos = pos
proc getTok(L: var TLexer, tok: var TToken) =
tok.xkind = pxInvalid
fillToken(tok)
skip(L, tok)
var c = L.buf[L.bufpos]
if c in SymStartChars:
getSymbol(L, tok)
elif c in {'0'..'9'}:
getNumber10(L, tok)
else:
case c
of ';':
tok.xkind = pxSemicolon
inc(L.bufpos)
of '/':
if L.buf[L.bufpos + 1] == '/':
scanLineComment(L, tok)
else:
tok.xkind = pxSlash
inc(L.bufpos)
of ',':
tok.xkind = pxComma
inc(L.bufpos)
of '(':
inc(L.bufpos)
if (L.buf[L.bufPos] == '*'):
if (L.buf[L.bufPos + 1] == '$'):
inc(L.bufpos, 2)
skip(L, tok)
getSymbol(L, tok)
tok.xkind = pxStarDirLe
else:
inc(L.bufpos)
scanStarComment(L, tok)
else:
tok.xkind = pxParLe
of '*':
inc(L.bufpos)
if L.buf[L.bufpos] == ')':
inc(L.bufpos)
tok.xkind = pxStarDirRi
else:
tok.xkind = pxStar
of ')':
tok.xkind = pxParRi
inc(L.bufpos)
of '[':
inc(L.bufpos)
tok.xkind = pxBracketLe
of ']':
inc(L.bufpos)
tok.xkind = pxBracketRi
of '.':
inc(L.bufpos)
if L.buf[L.bufpos] == '.':
tok.xkind = pxDotDot
inc(L.bufpos)
else:
tok.xkind = pxDot
of '{':
inc(L.bufpos)
case L.buf[L.bufpos]
of '$':
inc(L.bufpos)
skip(L, tok)
getSymbol(L, tok)
tok.xkind = pxCurlyDirLe
of '&':
inc(L.bufpos)
tok.xkind = pxAmp
of '%':
inc(L.bufpos)
tok.xkind = pxPer
of '@':
inc(L.bufpos)
tok.xkind = pxCommand
else: scanCurlyComment(L, tok)
of '+':
tok.xkind = pxPlus
inc(L.bufpos)
of '-':
tok.xkind = pxMinus
inc(L.bufpos)
of ':':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxAsgn
else:
tok.xkind = pxColon
of '<':
inc(L.bufpos)
if L.buf[L.bufpos] == '>':
inc(L.bufpos)
tok.xkind = pxNeq
elif L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxLe
else:
tok.xkind = pxLt
of '>':
inc(L.bufpos)
if L.buf[L.bufpos] == '=':
inc(L.bufpos)
tok.xkind = pxGe
else:
tok.xkind = pxGt
of '=':
tok.xkind = pxEquals
inc(L.bufpos)
of '@':
tok.xkind = pxAt
inc(L.bufpos)
of '^':
tok.xkind = pxHat
inc(L.bufpos)
of '}':
tok.xkind = pxCurlyDirRi
inc(L.bufpos)
of '\'', '#':
getString(L, tok)
of '$':
getNumber16(L, tok)
of '%':
getNumber2(L, tok)
of nimlexbase.EndOfFile:
tok.xkind = pxEof
else:
tok.literal = c & ""
tok.xkind = pxInvalid
lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
inc(L.bufpos)

File diff suppressed because it is too large Load diff