From 33eeb66ea276a532782464638aff6d001fbef4de Mon Sep 17 00:00:00 2001 From: enurlyx Date: Sat, 31 May 2014 16:02:15 +0200 Subject: [PATCH 1/5] Add support for structs/unions defined in structs/unions --- compiler/c2nim/cparse.nim | 140 ++++++++++++++++++++++++++++---------- 1 file changed, 103 insertions(+), 37 deletions(-) diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim index 52d50ca39a..09b2c01f15 100644 --- a/compiler/c2nim/cparse.nim +++ b/compiler/c2nim/cparse.nim @@ -19,7 +19,7 @@ import os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs, - options, strtabs + options, strtabs, times type TParserFlag = enum @@ -63,6 +63,15 @@ type ERetryParsing = object of ESynch + + +proc addTypeDef(section, name, t: PNode) +proc parseStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode +proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool, + kind: TNodeKind = nkRecList): PNode + + + proc newParserOptions*(): PParserOptions = new(result) result.prefixes = @[] @@ -682,23 +691,10 @@ proc parseField(p: var TParser, kind: TNodeKind): PNode = else: result = mangledIdent(p.tok.s, p) getTok(p, result) -proc parseStructBody(p: var TParser, isUnion: bool, - kind: TNodeKind = nkRecList): PNode = - result = newNodeP(kind, p) - eat(p, pxCurlyLe, result) - while p.tok.xkind notin {pxEof, pxCurlyRi}: - var baseTyp = typeAtom(p) - while true: - var def = newNodeP(nkIdentDefs, p) - var t = pointer(p, baseTyp) - var i = parseField(p, kind) - t = parseTypeSuffix(p, t) - addSon(def, i, t, ast.emptyNode) - addSon(result, def) - if p.tok.xkind != pxComma: break - getTok(p, def) - eat(p, pxSemicolon, lastSon(result)) - eat(p, pxCurlyRi, result) +proc getNewModuleWideId(): int = + var id {.global.} = 0 + id.inc + id proc structPragmas(p: TParser, name: PNode, origName: string): PNode = assert name.kind == nkIdent @@ -712,6 +708,73 @@ proc structPragmas(p: TParser, name: PNode, origName: string): PNode = if pragmas.len > 0: addSon(result, pragmas) else: addSon(result, ast.emptyNode) +proc parseInnerStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode = + getTok(p, nil) + if p.tok.xkind != pxCurlyLe: + parMessage(p, errUser, "Expected '{' but found '" & $(p.tok[]) & "'") + + let time = getTime().int + let id = getNewModuleWideId() + let structName = if isUnion: "INNER_C_UNION_" & $time & "_" & $id + else: "INNER_C_STRUCT_" & $time & "_" & $id + let typeSection = newNodeP(nkTypeSection, p) + let newStruct = newNodeP(nkObjectTy, p) + var pragmas = ast.emptyNode + if isUnion: + pragmas = newNodeP(nkPragma, p) + addSon(pragmas, newIdentNodeP("union", p)) + addSon(newStruct, pragmas, ast.emptyNode) # no inheritance + result = newNodeP(nkIdent, p) + result.ident = getIdent(structName) + let struct = parseStructBody(p, stmtList, isUnion) + let defName = newNodeP(nkIdent, p) + defName.ident = getIdent(structName) + addSon(newStruct, struct) + addTypeDef(typeSection, structPragmas(p, defName, "no_name"), newStruct) + addSon(stmtList, typeSection) + +proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool, + kind: TNodeKind = nkRecList): PNode = + result = newNodeP(kind, p) + eat(p, pxCurlyLe, result) + while p.tok.xkind notin {pxEof, pxCurlyRi}: + skipConst(p) + var baseTyp: PNode + if p.tok.xkind == pxSymbol and (p.tok.s == "struct" or p.tok.s == "union"): + let gotUnion = if p.tok.s == "union": true else: false + saveContext(p) + getTok(p, nil) + if p.tok.xkind == pxSymbol: + backtrackContext(p) + baseTyp = typeAtom(p) + else: + backtrackContext(p) + baseTyp = parseInnerStruct(p, stmtList, gotUnion) + if p.tok.xkind == pxSemiColon: + let id = getNewModuleWideId() + let def = newNodeP(nkIdentDefs, p) + var t = pointer(p, baseTyp) + let i = fieldIdent("ano_" & $id, p) + t = parseTypeSuffix(p, t) + addSon(def, i, t, ast.emptyNode) + addSon(result, def) + getTok(p, nil) + continue + else: + baseTyp = typeAtom(p) + + while true: + var def = newNodeP(nkIdentDefs, p) + var t = pointer(p, baseTyp) + var i = parseField(p, kind) + t = parseTypeSuffix(p, t) + addSon(def, i, t, ast.emptyNode) + addSon(result, def) + if p.tok.xkind != pxComma: break + getTok(p, def) + eat(p, pxSemicolon, lastSon(result)) + eat(p, pxCurlyRi, result) + proc enumPragmas(p: TParser, name: PNode): PNode = result = newNodeP(nkPragmaExpr, p) addSon(result, name) @@ -722,7 +785,7 @@ proc enumPragmas(p: TParser, name: PNode): PNode = addSon(pragmas, e) addSon(result, pragmas) -proc parseStruct(p: var TParser, isUnion: bool): PNode = +proc parseStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode = result = newNodeP(nkObjectTy, p) var pragmas = ast.emptyNode if isUnion: @@ -730,7 +793,7 @@ proc parseStruct(p: var TParser, isUnion: bool): PNode = addSon(pragmas, newIdentNodeP("union", p)) addSon(result, pragmas, ast.emptyNode) # no inheritance if p.tok.xkind == pxCurlyLe: - addSon(result, parseStructBody(p, isUnion)) + addSon(result, parseStructBody(p, stmtList, isUnion)) else: addSon(result, newNodeP(nkRecList, p)) @@ -874,10 +937,10 @@ proc enumFields(p: var TParser): PNode = # allow trailing comma: if p.tok.xkind == pxCurlyRi: break -proc parseTypedefStruct(p: var TParser, result: PNode, isUnion: bool) = +proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion: bool) = getTok(p, result) if p.tok.xkind == pxCurlyLe: - var t = parseStruct(p, isUnion) + var t = parseStruct(p, stmtList, isUnion) var origName = p.tok.s markTypeIdent(p, nil) var name = skipIdent(p) @@ -890,7 +953,7 @@ proc parseTypedefStruct(p: var TParser, result: PNode, isUnion: bool) = var nameOrType = skipIdent(p) case p.tok.xkind of pxCurlyLe: - var t = parseStruct(p, isUnion) + var t = parseStruct(p, stmtList, isUnion) if p.tok.xkind == pxSymbol: # typedef struct tagABC {} abc, *pabc; # --> abc is a better type name than tagABC! @@ -960,27 +1023,30 @@ proc parseTypedefEnum(p: var TParser, result: PNode) = expectIdent(p) proc parseTypeDef(p: var TParser): PNode = - result = newNodeP(nkTypeSection, p) + result = newNodeP(nkStmtList, p) + var typeSection = newNodeP(nkTypeSection, p) while p.tok.xkind == pxSymbol and p.tok.s == "typedef": - getTok(p, result) + getTok(p, typeSection) inc(p.inTypeDef) expectIdent(p) case p.tok.s - of "struct": parseTypedefStruct(p, result, isUnion=false) - of "union": parseTypedefStruct(p, result, isUnion=true) - of "enum": parseTypedefEnum(p, result) + of "struct": parseTypedefStruct(p, typeSection, result, isUnion=false) + of "union": parseTypedefStruct(p, typeSection, result, isUnion=true) + of "enum": parseTypedefEnum(p, typeSection) of "class": if pfCpp in p.options.flags: - parseTypedefStruct(p, result, isUnion=false) + parseTypedefStruct(p, typeSection, result, isUnion=false) else: var t = typeAtom(p) - otherTypeDef(p, result, t) + otherTypeDef(p, typeSection, t) else: var t = typeAtom(p) - otherTypeDef(p, result, t) + otherTypeDef(p, typeSection, t) eat(p, pxSemicolon) dec(p.inTypeDef) - + + addSon(result, typeSection) + proc skipDeclarationSpecifiers(p: var TParser) = while p.tok.xkind == pxSymbol: case p.tok.s @@ -1608,8 +1674,8 @@ proc declarationOrStatement(p: var TParser): PNode = result = expressionStatement(p) assert result != nil -proc parseTuple(p: var TParser, isUnion: bool): PNode = - result = parseStructBody(p, isUnion, nkTupleTy) +proc parseTuple(p: var TParser, statements: PNode, isUnion: bool): PNode = + parseStructBody(p, statements, isUnion, nkTupleTy) proc parseTrailingDefinedIdents(p: var TParser, result, baseTyp: PNode) = var varSection = newNodeP(nkVarSection, p) @@ -1640,13 +1706,13 @@ proc parseStandaloneStruct(p: var TParser, isUnion: bool): PNode = if p.tok.xkind in {pxCurlyLe, pxSemiColon}: if origName.len > 0: var name = mangledIdent(origName, p) - var t = parseStruct(p, isUnion) + var t = parseStruct(p, result, isUnion) var typeSection = newNodeP(nkTypeSection, p) addTypeDef(typeSection, structPragmas(p, name, origName), t) addSon(result, typeSection) parseTrailingDefinedIdents(p, result, name) else: - var t = parseTuple(p, isUnion) + var t = parseTuple(p, result, isUnion) parseTrailingDefinedIdents(p, result, t) else: backtrackContext(p) @@ -2034,7 +2100,7 @@ proc parseStandaloneClass(p: var TParser, isStruct: bool): PNode = addTypeDef(typeSection, structPragmas(p, name, origName), t) parseTrailingDefinedIdents(p, result, name) else: - var t = parseTuple(p, isUnion=false) + var t = parseTuple(p, result, isUnion=false) parseTrailingDefinedIdents(p, result, t) else: backtrackContext(p) From 3648680f28245d5b184a9365d426b47ad769b5fe Mon Sep 17 00:00:00 2001 From: enurlyx Date: Tue, 10 Jun 2014 22:16:04 +0200 Subject: [PATCH 2/5] Added test for anonymous structs and unions --- compiler/c2nim/tests/struct_anonym.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 compiler/c2nim/tests/struct_anonym.h diff --git a/compiler/c2nim/tests/struct_anonym.h b/compiler/c2nim/tests/struct_anonym.h new file mode 100644 index 0000000000..859bfc206f --- /dev/null +++ b/compiler/c2nim/tests/struct_anonym.h @@ -0,0 +1,27 @@ + +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; +}; \ No newline at end of file From 788cfb3f59df97eed17cbd757f2b282633f882bf Mon Sep 17 00:00:00 2001 From: enurlyx Date: Sat, 14 Jun 2014 17:10:51 +0200 Subject: [PATCH 3/5] Removed time and added a hash based on filename, line and column for creating a unique struct id --- compiler/c2nim/cparse.nim | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim index 09b2c01f15..f121610d4e 100644 --- a/compiler/c2nim/cparse.nim +++ b/compiler/c2nim/cparse.nim @@ -19,7 +19,7 @@ import os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs, - options, strtabs, times + options, strtabs, hashes type TParserFlag = enum @@ -691,11 +691,6 @@ proc parseField(p: var TParser, kind: TNodeKind): PNode = else: result = mangledIdent(p.tok.s, p) getTok(p, result) -proc getNewModuleWideId(): int = - var id {.global.} = 0 - id.inc - id - proc structPragmas(p: TParser, name: PNode, origName: string): PNode = assert name.kind == nkIdent result = newNodeP(nkPragmaExpr, p) @@ -708,15 +703,18 @@ proc structPragmas(p: TParser, name: PNode, origName: string): PNode = if pragmas.len > 0: addSon(result, pragmas) else: addSon(result, ast.emptyNode) +proc hashPosition(p: TParser): string = + let lineInfo = parLineInfo(p) + let fileInfo = fileInfos[lineInfo.fileIndex] + result = $hash(fileInfo.shortName & "_" & $lineInfo.line & "_" & $lineInfo.col).uint + proc parseInnerStruct(p: var TParser, stmtList: PNode, isUnion: bool): PNode = getTok(p, nil) if p.tok.xkind != pxCurlyLe: parMessage(p, errUser, "Expected '{' but found '" & $(p.tok[]) & "'") - let time = getTime().int - let id = getNewModuleWideId() - let structName = if isUnion: "INNER_C_UNION_" & $time & "_" & $id - else: "INNER_C_STRUCT_" & $time & "_" & $id + let structName = if isUnion: "INNER_C_UNION_" & p.hashPosition + else: "INNER_C_STRUCT_" & p.hashPosition let typeSection = newNodeP(nkTypeSection, p) let newStruct = newNodeP(nkObjectTy, p) var pragmas = ast.emptyNode @@ -751,10 +749,9 @@ proc parseStructBody(p: var TParser, stmtList: PNode, isUnion: bool, backtrackContext(p) baseTyp = parseInnerStruct(p, stmtList, gotUnion) if p.tok.xkind == pxSemiColon: - let id = getNewModuleWideId() let def = newNodeP(nkIdentDefs, p) var t = pointer(p, baseTyp) - let i = fieldIdent("ano_" & $id, p) + let i = fieldIdent("ano_" & p.hashPosition, p) t = parseTypeSuffix(p, t) addSon(def, i, t, ast.emptyNode) addSon(result, def) From bd3f6b51d0be7e8cc360e32b778086c5326a8eca Mon Sep 17 00:00:00 2001 From: enurlyx Date: Sun, 15 Jun 2014 22:18:17 +0200 Subject: [PATCH 4/5] Sorting enumerations and generation of consts for enumfields with the same value + test --- compiler/c2nim/cparse.nim | 65 ++++++++++++++++++++++++++++--------- compiler/c2nim/tests/enum.h | 27 +++++++++++++++ 2 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 compiler/c2nim/tests/enum.h diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim index f121610d4e..cbfe23a44e 100644 --- a/compiler/c2nim/cparse.nim +++ b/compiler/c2nim/cparse.nim @@ -19,7 +19,7 @@ import os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs, - options, strtabs, hashes + options, strtabs, hashes, algorithm type TParserFlag = enum @@ -915,9 +915,16 @@ proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) = newTyp = parseTypeSuffix(p, newTyp) addTypeDef(section, newName, newTyp) -proc enumFields(p: var TParser): PNode = +proc createConst(name, typ, val: PNode, p: TParser): PNode = + result = newNodeP(nkConstDef, p) + addSon(result, name, typ, val) + +proc enumFields(p: var TParser, constList: PNode): PNode = result = newNodeP(nkEnumTy, p) addSon(result, ast.emptyNode) # enum does not inherit from anything + var i: BiggestInt = 0 + var field: tuple[id: BiggestInt, node: PNode] + var fields = newSeq[type(field)]() while true: var e = skipIdent(p) if p.tok.xkind == pxAsgn: @@ -927,12 +934,34 @@ proc enumFields(p: var TParser): PNode = e = newNodeP(nkEnumFieldDef, p) addSon(e, a, c) skipCom(p, e) - - addSon(result, e) + i = c.intVal + else: + inc(i) + field.id = i + field.node = e + fields.add(field) if p.tok.xkind != pxComma: break getTok(p, e) # allow trailing comma: if p.tok.xkind == pxCurlyRi: break + fields.sort do (x, y: type(field)) -> int: + cmp(x.id, y.id) + var lastId: BiggestInt = -1 + var lastIdent: PNode + for f in fields: + if f.id == lastId: + var currentIdent: PNode + case f.node.kind: + of nkEnumFieldDef: currentIdent = f.node.sons[0] + else: currentIdent = f.node + var constant = createConst( currentIdent, ast.emptyNode, lastIdent, p) + constList.addSon(constant) + else: + addSon(result, f.node) + lastId = f.id + case f.node.kind: + of nkEnumFieldDef: lastIdent = f.node.sons[0] + else: lastIdent = f.node proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion: bool) = getTok(p, result) @@ -974,11 +1003,11 @@ proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion: else: expectIdent(p) -proc parseTypedefEnum(p: var TParser, result: PNode) = +proc parseTypedefEnum(p: var TParser, result, constSection: PNode) = getTok(p, result) if p.tok.xkind == pxCurlyLe: getTok(p, result) - var t = enumFields(p) + var t = enumFields(p, constSection) eat(p, pxCurlyRi, t) var origName = p.tok.s markTypeIdent(p, nil) @@ -993,7 +1022,7 @@ proc parseTypedefEnum(p: var TParser, result: PNode) = case p.tok.xkind of pxCurlyLe: getTok(p, result) - var t = enumFields(p) + var t = enumFields(p, constSection) eat(p, pxCurlyRi, t) if p.tok.xkind == pxSymbol: # typedef enum tagABC {} abc, *pabc; @@ -1022,6 +1051,7 @@ proc parseTypedefEnum(p: var TParser, result: PNode) = proc parseTypeDef(p: var TParser): PNode = result = newNodeP(nkStmtList, p) var typeSection = newNodeP(nkTypeSection, p) + var afterStatements = newNodeP(nkStmtList, p) while p.tok.xkind == pxSymbol and p.tok.s == "typedef": getTok(p, typeSection) inc(p.inTypeDef) @@ -1029,7 +1059,10 @@ proc parseTypeDef(p: var TParser): PNode = case p.tok.s of "struct": parseTypedefStruct(p, typeSection, result, isUnion=false) of "union": parseTypedefStruct(p, typeSection, result, isUnion=true) - of "enum": parseTypedefEnum(p, typeSection) + of "enum": + var constSection = newNodeP(nkConstSection, p) + parseTypedefEnum(p, typeSection, constSection) + addSon(afterStatements, constSection) of "class": if pfCpp in p.options.flags: parseTypedefStruct(p, typeSection, result, isUnion=false) @@ -1043,6 +1076,8 @@ proc parseTypeDef(p: var TParser): PNode = dec(p.inTypeDef) addSon(result, typeSection) + for s in afterStatements: + addSon(result, s) proc skipDeclarationSpecifiers(p: var TParser) = while p.tok.xkind == pxSymbol: @@ -1155,10 +1190,6 @@ proc declaration(p: var TParser): PNode = result = parseVarDecl(p, baseTyp, rettyp, origName) assert result != nil -proc createConst(name, typ, val: PNode, p: TParser): PNode = - result = newNodeP(nkConstDef, p) - addSon(result, name, typ, val) - proc enumSpecifier(p: var TParser): PNode = saveContext(p) getTok(p, nil) # skip "enum" @@ -1204,12 +1235,16 @@ proc enumSpecifier(p: var TParser): PNode = closeContext(p) var name = result # create a type section containing the enum - result = newNodeP(nkTypeSection, p) + result = newNodeP(nkStmtList, p) + var tSection = newNodeP(nkTypeSection, p) var t = newNodeP(nkTypeDef, p) getTok(p, t) - var e = enumFields(p) + var constSection = newNodeP(nkConstSection, p) + var e = enumFields(p, constSection) addSon(t, exportSym(p, name, origName), ast.emptyNode, e) - addSon(result, t) + addSon(tSection, t) + addSon(result, tSection) + addSon(result, constSection) eat(p, pxCurlyRi, result) eat(p, pxSemicolon) of pxSemicolon: diff --git a/compiler/c2nim/tests/enum.h b/compiler/c2nim/tests/enum.h new file mode 100644 index 0000000000..c9c055e148 --- /dev/null +++ b/compiler/c2nim/tests/enum.h @@ -0,0 +1,27 @@ + +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 +}; \ No newline at end of file From 2940aa5ee200354f2bfd06eddbe51a16a7397d3d Mon Sep 17 00:00:00 2001 From: enurlyx Date: Tue, 17 Jun 2014 21:42:16 +0200 Subject: [PATCH 5/5] Made the code more robust and detect nkPrefix as number (-1 or +4) for enum sorting. Added also a new test for enums. --- compiler/c2nim/cparse.nim | 50 ++++++++++++++++++++++++++++++------- compiler/c2nim/tests/enum.h | 13 ++++++++++ 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/compiler/c2nim/cparse.nim b/compiler/c2nim/cparse.nim index cbfe23a44e..2e31af5285 100644 --- a/compiler/c2nim/cparse.nim +++ b/compiler/c2nim/cparse.nim @@ -919,11 +919,23 @@ proc createConst(name, typ, val: PNode, p: TParser): PNode = result = newNodeP(nkConstDef, p) addSon(result, name, typ, val) +proc exprToNumber(n: PNode not nil): tuple[succ: bool, val: BiggestInt] = + result = (false, 0.BiggestInt) + case n.kind: + of nkPrefix: + # Check for negative/positive numbers -3 or +6 + if n.sons.len == 2 and n.sons[0].kind == nkIdent and n.sons[1].kind == nkIntLit: + let pre = n.sons[0] + let num = n.sons[1] + if pre.ident.s == "-": result = (true, - num.intVal) + elif pre.ident.s == "+": result = (true, num.intVal) + else: discard + proc enumFields(p: var TParser, constList: PNode): PNode = result = newNodeP(nkEnumTy, p) addSon(result, ast.emptyNode) # enum does not inherit from anything var i: BiggestInt = 0 - var field: tuple[id: BiggestInt, node: PNode] + var field: tuple[id: BiggestInt, isNumber: bool, node: PNode] var fields = newSeq[type(field)]() while true: var e = skipIdent(p) @@ -934,9 +946,19 @@ proc enumFields(p: var TParser, constList: PNode): PNode = e = newNodeP(nkEnumFieldDef, p) addSon(e, a, c) skipCom(p, e) - i = c.intVal + if c.kind == nkIntLit: + i = c.intVal + field.isNumber = true + else: + var (success, number) = exprToNumber(c) + if success: + i = number + field.isNumber = true + else: + field.isNumber = false else: inc(i) + field.isNumber = true field.id = i field.node = e fields.add(field) @@ -946,22 +968,32 @@ proc enumFields(p: var TParser, constList: PNode): PNode = if p.tok.xkind == pxCurlyRi: break fields.sort do (x, y: type(field)) -> int: cmp(x.id, y.id) - var lastId: BiggestInt = -1 + var lastId: BiggestInt var lastIdent: PNode - for f in fields: - if f.id == lastId: + for count, f in fields: + if not f.isNumber: + addSon(result, f.node) + elif f.id == lastId and count > 0: var currentIdent: PNode case f.node.kind: - of nkEnumFieldDef: currentIdent = f.node.sons[0] - else: currentIdent = f.node + of nkEnumFieldDef: + if f.node.sons.len > 0 and f.node.sons[0].kind == nkIdent: + currentIdent = f.node.sons[0] + else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") + of nkIdent: currentIdent = f.node + else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") var constant = createConst( currentIdent, ast.emptyNode, lastIdent, p) constList.addSon(constant) else: addSon(result, f.node) lastId = f.id case f.node.kind: - of nkEnumFieldDef: lastIdent = f.node.sons[0] - else: lastIdent = f.node + of nkEnumFieldDef: + if f.node.sons.len > 0 and f.node.sons[0].kind == nkIdent: + lastIdent = f.node.sons[0] + else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") + of nkIdent: lastIdent = f.node + else: parMessage(p, errGenerated, "Warning: When sorting enum fields an expected nkIdent was not found. Check the fields!") proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion: bool) = getTok(p, result) diff --git a/compiler/c2nim/tests/enum.h b/compiler/c2nim/tests/enum.h index c9c055e148..16bc59058f 100644 --- a/compiler/c2nim/tests/enum.h +++ b/compiler/c2nim/tests/enum.h @@ -24,4 +24,17 @@ typedef enum food 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 }; \ No newline at end of file