big repo cleanup
This commit is contained in:
parent
46c41e4369
commit
cd292568d7
246 changed files with 28 additions and 74652 deletions
344
compiler/c2nim/cpp.nim
Executable file
344
compiler/c2nim/cpp.nim
Executable file
|
|
@ -0,0 +1,344 @@
|
|||
#
|
||||
#
|
||||
# c2nim - C to Nimrod source converter
|
||||
# (c) Copyright 2011 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.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))
|
||||
eat(p, pxParLe)
|
||||
var params = newNodeP(nkFormalParams, p)
|
||||
# return type; not known yet:
|
||||
addSon(params, ast.emptyNode)
|
||||
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
|
||||
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
|
||||
nil
|
||||
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: nil
|
||||
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.filename,
|
||||
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":
|
||||
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)
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue