Sorting enumerations and generation of consts for enumfields with the same value + test
This commit is contained in:
parent
788cfb3f59
commit
bd3f6b51d0
2 changed files with 77 additions and 15 deletions
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs,
|
os, llstream, renderer, clex, idents, strutils, pegs, ast, astalgo, msgs,
|
||||||
options, strtabs, hashes
|
options, strtabs, hashes, algorithm
|
||||||
|
|
||||||
type
|
type
|
||||||
TParserFlag = enum
|
TParserFlag = enum
|
||||||
|
|
@ -915,9 +915,16 @@ proc parseTrailingDefinedTypes(p: var TParser, section, typ: PNode) =
|
||||||
newTyp = parseTypeSuffix(p, newTyp)
|
newTyp = parseTypeSuffix(p, newTyp)
|
||||||
addTypeDef(section, newName, 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)
|
result = newNodeP(nkEnumTy, p)
|
||||||
addSon(result, ast.emptyNode) # enum does not inherit from anything
|
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:
|
while true:
|
||||||
var e = skipIdent(p)
|
var e = skipIdent(p)
|
||||||
if p.tok.xkind == pxAsgn:
|
if p.tok.xkind == pxAsgn:
|
||||||
|
|
@ -927,12 +934,34 @@ proc enumFields(p: var TParser): PNode =
|
||||||
e = newNodeP(nkEnumFieldDef, p)
|
e = newNodeP(nkEnumFieldDef, p)
|
||||||
addSon(e, a, c)
|
addSon(e, a, c)
|
||||||
skipCom(p, e)
|
skipCom(p, e)
|
||||||
|
i = c.intVal
|
||||||
addSon(result, e)
|
else:
|
||||||
|
inc(i)
|
||||||
|
field.id = i
|
||||||
|
field.node = e
|
||||||
|
fields.add(field)
|
||||||
if p.tok.xkind != pxComma: break
|
if p.tok.xkind != pxComma: break
|
||||||
getTok(p, e)
|
getTok(p, e)
|
||||||
# allow trailing comma:
|
# allow trailing comma:
|
||||||
if p.tok.xkind == pxCurlyRi: break
|
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) =
|
proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion: bool) =
|
||||||
getTok(p, result)
|
getTok(p, result)
|
||||||
|
|
@ -974,11 +1003,11 @@ proc parseTypedefStruct(p: var TParser, result: PNode, stmtList: PNode, isUnion:
|
||||||
else:
|
else:
|
||||||
expectIdent(p)
|
expectIdent(p)
|
||||||
|
|
||||||
proc parseTypedefEnum(p: var TParser, result: PNode) =
|
proc parseTypedefEnum(p: var TParser, result, constSection: PNode) =
|
||||||
getTok(p, result)
|
getTok(p, result)
|
||||||
if p.tok.xkind == pxCurlyLe:
|
if p.tok.xkind == pxCurlyLe:
|
||||||
getTok(p, result)
|
getTok(p, result)
|
||||||
var t = enumFields(p)
|
var t = enumFields(p, constSection)
|
||||||
eat(p, pxCurlyRi, t)
|
eat(p, pxCurlyRi, t)
|
||||||
var origName = p.tok.s
|
var origName = p.tok.s
|
||||||
markTypeIdent(p, nil)
|
markTypeIdent(p, nil)
|
||||||
|
|
@ -993,7 +1022,7 @@ proc parseTypedefEnum(p: var TParser, result: PNode) =
|
||||||
case p.tok.xkind
|
case p.tok.xkind
|
||||||
of pxCurlyLe:
|
of pxCurlyLe:
|
||||||
getTok(p, result)
|
getTok(p, result)
|
||||||
var t = enumFields(p)
|
var t = enumFields(p, constSection)
|
||||||
eat(p, pxCurlyRi, t)
|
eat(p, pxCurlyRi, t)
|
||||||
if p.tok.xkind == pxSymbol:
|
if p.tok.xkind == pxSymbol:
|
||||||
# typedef enum tagABC {} abc, *pabc;
|
# typedef enum tagABC {} abc, *pabc;
|
||||||
|
|
@ -1022,6 +1051,7 @@ proc parseTypedefEnum(p: var TParser, result: PNode) =
|
||||||
proc parseTypeDef(p: var TParser): PNode =
|
proc parseTypeDef(p: var TParser): PNode =
|
||||||
result = newNodeP(nkStmtList, p)
|
result = newNodeP(nkStmtList, p)
|
||||||
var typeSection = newNodeP(nkTypeSection, p)
|
var typeSection = newNodeP(nkTypeSection, p)
|
||||||
|
var afterStatements = newNodeP(nkStmtList, p)
|
||||||
while p.tok.xkind == pxSymbol and p.tok.s == "typedef":
|
while p.tok.xkind == pxSymbol and p.tok.s == "typedef":
|
||||||
getTok(p, typeSection)
|
getTok(p, typeSection)
|
||||||
inc(p.inTypeDef)
|
inc(p.inTypeDef)
|
||||||
|
|
@ -1029,7 +1059,10 @@ proc parseTypeDef(p: var TParser): PNode =
|
||||||
case p.tok.s
|
case p.tok.s
|
||||||
of "struct": parseTypedefStruct(p, typeSection, result, isUnion=false)
|
of "struct": parseTypedefStruct(p, typeSection, result, isUnion=false)
|
||||||
of "union": parseTypedefStruct(p, typeSection, result, isUnion=true)
|
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":
|
of "class":
|
||||||
if pfCpp in p.options.flags:
|
if pfCpp in p.options.flags:
|
||||||
parseTypedefStruct(p, typeSection, result, isUnion=false)
|
parseTypedefStruct(p, typeSection, result, isUnion=false)
|
||||||
|
|
@ -1043,6 +1076,8 @@ proc parseTypeDef(p: var TParser): PNode =
|
||||||
dec(p.inTypeDef)
|
dec(p.inTypeDef)
|
||||||
|
|
||||||
addSon(result, typeSection)
|
addSon(result, typeSection)
|
||||||
|
for s in afterStatements:
|
||||||
|
addSon(result, s)
|
||||||
|
|
||||||
proc skipDeclarationSpecifiers(p: var TParser) =
|
proc skipDeclarationSpecifiers(p: var TParser) =
|
||||||
while p.tok.xkind == pxSymbol:
|
while p.tok.xkind == pxSymbol:
|
||||||
|
|
@ -1155,10 +1190,6 @@ proc declaration(p: var TParser): PNode =
|
||||||
result = parseVarDecl(p, baseTyp, rettyp, origName)
|
result = parseVarDecl(p, baseTyp, rettyp, origName)
|
||||||
assert result != nil
|
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 =
|
proc enumSpecifier(p: var TParser): PNode =
|
||||||
saveContext(p)
|
saveContext(p)
|
||||||
getTok(p, nil) # skip "enum"
|
getTok(p, nil) # skip "enum"
|
||||||
|
|
@ -1204,12 +1235,16 @@ proc enumSpecifier(p: var TParser): PNode =
|
||||||
closeContext(p)
|
closeContext(p)
|
||||||
var name = result
|
var name = result
|
||||||
# create a type section containing the enum
|
# 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)
|
var t = newNodeP(nkTypeDef, p)
|
||||||
getTok(p, t)
|
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(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, pxCurlyRi, result)
|
||||||
eat(p, pxSemicolon)
|
eat(p, pxSemicolon)
|
||||||
of pxSemicolon:
|
of pxSemicolon:
|
||||||
|
|
|
||||||
27
compiler/c2nim/tests/enum.h
Normal file
27
compiler/c2nim/tests/enum.h
Normal file
|
|
@ -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
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue