c2nim: added some scope operator parsing

This commit is contained in:
Araq 2013-09-11 00:07:39 +02:00
commit 0a851c869f
3 changed files with 44 additions and 18 deletions

View file

@ -1,7 +1,7 @@
# #
# #
# c2nim - C to Nimrod source converter # c2nim - C to Nimrod source converter
# (c) Copyright 2012 Andreas Rumpf # (c) Copyright 2013 Andreas Rumpf
# #
# See the file "copying.txt", included in this # See the file "copying.txt", included in this
# distribution, for details about the copyright. # distribution, for details about the copyright.
@ -12,9 +12,9 @@
## used to convert the AST to its text representation. ## used to convert the AST to its text representation.
# TODO # TODO
# - implement handling of '::' # - document 'cpp' mode
# - implement handling of '::': function declarations
# - C++'s "operator" still needs some love # - C++'s "operator" still needs some love
# - ignore 'using' statements
# - support '#if' in classes # - support '#if' in classes
import import
@ -46,6 +46,7 @@ type
dynlibSym, header: string dynlibSym, header: string
macros: seq[TMacro] macros: seq[TMacro]
toMangle: PStringTable toMangle: PStringTable
classes: PStringTable
PParserOptions* = ref TParserOptions PParserOptions* = ref TParserOptions
TParser* = object TParser* = object
@ -71,6 +72,7 @@ proc newParserOptions*(): PParserOptions =
result.dynlibSym = "" result.dynlibSym = ""
result.header = "" result.header = ""
result.toMangle = newStringTable(modeCaseSensitive) result.toMangle = newStringTable(modeCaseSensitive)
result.classes = newStringTable(modeCaseSensitive)
proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool = proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool =
result = true result = true
@ -88,6 +90,7 @@ proc setOption*(parserOptions: PParserOptions, key: string, val=""): bool =
of "cpp": incl(parserOptions.flags, pfCpp) of "cpp": incl(parserOptions.flags, pfCpp)
of "keepbodies": incl(parserOptions.flags, pfKeepBodies) of "keepbodies": incl(parserOptions.flags, pfKeepBodies)
of "ignorervaluerefs": incl(parserOptions.flags, pfIgnoreRValueRefs) of "ignorervaluerefs": incl(parserOptions.flags, pfIgnoreRValueRefs)
of "class": parserOptions.classes[val] = "true"
else: result = false else: result = false
proc ParseUnit*(p: var TParser): PNode proc ParseUnit*(p: var TParser): PNode
@ -234,22 +237,22 @@ proc getTok(p: var TParser, n: PNode) =
getTok(p) getTok(p)
skipCom(p, n) skipCom(p, n)
proc ExpectIdent(p: TParser) = proc expectIdent(p: TParser) =
if p.tok.xkind != pxSymbol: parMessage(p, errIdentifierExpected, $(p.tok[])) if p.tok.xkind != pxSymbol: parMessage(p, errIdentifierExpected, $(p.tok[]))
proc Eat(p: var TParser, xkind: TTokKind, n: PNode) = proc eat(p: var TParser, xkind: TTokKind, n: PNode) =
if p.tok.xkind == xkind: getTok(p, n) if p.tok.xkind == xkind: getTok(p, n)
else: parMessage(p, errTokenExpected, TokKindToStr(xkind)) else: parMessage(p, errTokenExpected, TokKindToStr(xkind))
proc Eat(p: var TParser, xkind: TTokKind) = proc eat(p: var TParser, xkind: TTokKind) =
if p.tok.xkind == xkind: getTok(p) if p.tok.xkind == xkind: getTok(p)
else: parMessage(p, errTokenExpected, TokKindToStr(xkind)) else: parMessage(p, errTokenExpected, TokKindToStr(xkind))
proc Eat(p: var TParser, tok: string, n: PNode) = proc eat(p: var TParser, tok: string, n: PNode) =
if p.tok.s == tok: getTok(p, n) if p.tok.s == tok: getTok(p, n)
else: parMessage(p, errTokenExpected, tok) else: parMessage(p, errTokenExpected, tok)
proc Opt(p: var TParser, xkind: TTokKind, n: PNode) = proc opt(p: var TParser, xkind: TTokKind, n: PNode) =
if p.tok.xkind == xkind: getTok(p, n) if p.tok.xkind == xkind: getTok(p, n)
proc addSon(father, a, b: PNode) = proc addSon(father, a, b: PNode) =
@ -361,11 +364,11 @@ proc fieldIdent(ident: string, p: TParser): PNode =
addSon(result, pragmas) addSon(result, pragmas)
addSon(pragmas, newIdentStrLitPair("importc", ident, p)) addSon(pragmas, newIdentStrLitPair("importc", ident, p))
proc DoImport(ident: string, pragmas: PNode, p: TParser) = proc doImport(ident: string, pragmas: PNode, p: TParser) =
if p.options.dynlibSym.len > 0 or p.options.header.len > 0: if p.options.dynlibSym.len > 0 or p.options.header.len > 0:
addImportToPragma(pragmas, ident, p) addImportToPragma(pragmas, ident, p)
proc DoImportCpp(ident: string, pragmas: PNode, p: TParser) = proc doImportCpp(ident: string, pragmas: PNode, p: TParser) =
if p.options.dynlibSym.len > 0 or p.options.header.len > 0: if p.options.dynlibSym.len > 0 or p.options.header.len > 0:
addSon(pragmas, newIdentStrLitPair("importcpp", ident, p)) addSon(pragmas, newIdentStrLitPair("importcpp", ident, p))
if p.options.dynlibSym.len > 0: if p.options.dynlibSym.len > 0:
@ -505,9 +508,21 @@ proc optAngle(p: var TParser, n: PNode): PNode =
else: else:
result = n result = n
proc optScope(p: var TParser, n: PNode): PNode =
result = n
if pfCpp in p.options.flags:
while p.tok.xkind == pxScope:
let a = result
result = newNodeP(nkDotExpr, p)
result.add(a)
getTok(p, result)
expectIdent(p)
result.add(mangledIdent(p.tok.s, p))
getTok(p, result)
proc typeAtom(p: var TParser): PNode = proc typeAtom(p: var TParser): PNode =
skipConst(p) skipConst(p)
ExpectIdent(p) expectIdent(p)
case p.tok.s case p.tok.s
of "void": of "void":
result = newNodeP(nkNilLit, p) # little hack result = newNodeP(nkNilLit, p) # little hack
@ -533,6 +548,7 @@ proc typeAtom(p: var TParser): PNode =
else: else:
result = mangledIdent(p.tok.s, p) result = mangledIdent(p.tok.s, p)
getTok(p, result) getTok(p, result)
result = optScope(p, result)
result = optAngle(p, result) result = optAngle(p, result)
proc newPointerTy(p: TParser, typ: PNode): PNode = proc newPointerTy(p: TParser, typ: PNode): PNode =
@ -1017,6 +1033,7 @@ proc declaration(p: var TParser): PNode =
if pfCpp in p.options.flags and p.tok.xkind == pxSymbol and if pfCpp in p.options.flags and p.tok.xkind == pxSymbol and
p.tok.s == "const": p.tok.s == "const":
addSon(pragmas, newIdentNodeP("noSideEffect", p)) addSon(pragmas, newIdentNodeP("noSideEffect", p))
getTok(p)
if pfCDecl in p.options.flags: if pfCDecl in p.options.flags:
addSon(pragmas, newIdentNodeP("cdecl", p)) addSon(pragmas, newIdentNodeP("cdecl", p))
elif pfStdcall in p.options.flags: elif pfStdcall in p.options.flags:
@ -1169,6 +1186,7 @@ proc primaryExpression(p: var TParser): PNode =
else: else:
result = mangledIdent(p.tok.s, p) result = mangledIdent(p.tok.s, p)
getTok(p, result) getTok(p, result)
result = optScope(p, result)
of pxIntLit: of pxIntLit:
result = newIntNodeP(nkIntLit, p.tok.iNumber, p) result = newIntNodeP(nkIntLit, p.tok.iNumber, p)
setBaseFlags(result, p.tok.base) setBaseFlags(result, p.tok.base)
@ -1925,7 +1943,7 @@ proc parseClass(p: var TParser; isStruct: bool; stmtList: PNode): PNode =
getTok(p, result) getTok(p, result)
eat(p, pxColon, result) eat(p, pxColon, result)
private = false private = false
if p.tok.xkind == pxSymbol and p.tok.s == "friend": if p.tok.xkind == pxSymbol and (p.tok.s == "friend" or p.tok.s == "using"):
# we skip friend declarations: # we skip friend declarations:
while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p) while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p)
eat(p, pxSemicolon) eat(p, pxSemicolon)
@ -2012,7 +2030,9 @@ proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode =
else: else:
p.currentClass = nil p.currentClass = nil
if p.tok.xkind in {pxCurlyLe, pxSemiColon, pxColon}: if p.tok.xkind in {pxCurlyLe, pxSemiColon, pxColon}:
if origName.len > 0: if origName.len > 0:
p.options.classes[origName] = "true"
var typeSection = newNodeP(nkTypeSection, p) var typeSection = newNodeP(nkTypeSection, p)
addSon(result, typeSection) addSon(result, typeSection)
@ -2092,6 +2112,13 @@ proc statement(p: var TParser): PNode =
result = compoundStatement(p) result = compoundStatement(p)
else: else:
result = declarationOrStatement(p) result = declarationOrStatement(p)
of "using":
if pfCpp in p.options.flags:
while p.tok.xkind notin {pxEof, pxSemicolon}: getTok(p)
eat(p, pxSemicolon)
result = newNodeP(nkNilLit, p)
else:
result = declarationOrStatement(p)
else: result = declarationOrStatement(p) else: result = declarationOrStatement(p)
of pxCurlyLe: of pxCurlyLe:
result = compoundStatement(p) result = compoundStatement(p)

View file

@ -323,7 +323,7 @@ proc parseDir(p: var TParser): PNode =
discard setOption(p.options, p.tok.s) discard setOption(p.options, p.tok.s)
getTok(p) getTok(p)
eatNewLine(p, nil) eatNewLine(p, nil)
of "dynlib", "header", "prefix", "suffix": of "dynlib", "header", "prefix", "suffix", "class":
var key = p.tok.s var key = p.tok.s
getTok(p) getTok(p)
if p.tok.xkind != pxStrLit: ExpectIdent(p) if p.tok.xkind != pxStrLit: ExpectIdent(p)

View file

@ -55,7 +55,7 @@ public:
void operator = (const wxTransformMatrix& mat); void operator = (const wxTransformMatrix& mat);
bool operator == (const wxTransformMatrix& mat) const; bool operator == (const wxTransformMatrix& mat) const;
bool operator != (const wxTransformMatrix& mat) const; bool operator != (const module::gah::wxTransformMatrix& mat) const;
//multiply every element by t //multiply every element by t
wxTransformMatrix& operator*=(const double& t); wxTransformMatrix& operator*=(const double& t);
@ -184,7 +184,7 @@ public:
Chris Breeze reported, that Chris Breeze reported, that
some functions of wxTransformMatrix cannot work because it is not some functions of wxTransformMatrix cannot work because it is not
known if he matrix has been inverted. Be careful when using it. known if he matrix has been inverted. Be careful when using it.
*/
// Transform X value from logical to device // Transform X value from logical to device
// warning: this function can only be used for this purpose // warning: this function can only be used for this purpose
@ -235,7 +235,6 @@ inline bool wxTransformMatrix::IsIdentity1(void) const
inline double wxCalculateDet(double a11, double a21, double a12, double a22) inline double wxCalculateDet(double a11, double a21, double a12, double a22)
{ {
return a11 * a22 - a12 * a21; return a11 * a22 - a12 * a21;
} }
*/
#endif // _WX_MATRIXH__ #endif // _WX_MATRIXH__