Use enums for sym, fail if no toast
This commit is contained in:
parent
01c295a41c
commit
c0481ac41c
4 changed files with 105 additions and 80 deletions
151
nimterop/ast.nim
151
nimterop/ast.nim
|
|
@ -20,30 +20,30 @@ proc addHeader*(fullpath: string) =
|
||||||
# Preprocessor
|
# Preprocessor
|
||||||
#
|
#
|
||||||
|
|
||||||
proc preprocDef(node: ref Ast) =
|
proc pPreprocDef(node: ref Ast) =
|
||||||
if node.children.len() == 2:
|
if node.children.len() == 2:
|
||||||
let
|
let
|
||||||
name = getNodeValIf(node.children[0], "identifier")
|
name = getNodeValIf(node.children[0], identifier)
|
||||||
val = getNodeValIf(node.children[1], "preproc_arg")
|
val = getNodeValIf(node.children[1], preproc_arg)
|
||||||
|
|
||||||
if name.nBl and val.nBl and name notin gConsts:
|
if name.nBl and val.nBl and name notin gConsts:
|
||||||
gConsts.add(name)
|
gConsts.add(name)
|
||||||
if val.getLit().nBl:
|
if val.getLit().nBl:
|
||||||
# #define NAME VALUE
|
# #define NAME VALUE
|
||||||
gConstStr &= &" {name.getIdentifier()}* = {val} # preprocDef()\n"
|
gConstStr &= &" {name.getIdentifier()}* = {val} # pPreprocDef()\n"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Types
|
# Types
|
||||||
#
|
#
|
||||||
|
|
||||||
proc typeScan(node: ref Ast, sym, identifier, offset: string): string =
|
proc typeScan(node: ref Ast, sym, id: Sym, offset: string): string =
|
||||||
if node.sym != sym or node.children.len() != 2:
|
if node.sym != sym or node.children.len() != 2:
|
||||||
return
|
return
|
||||||
|
|
||||||
let
|
let
|
||||||
pname = getNodeValIf(node.children[1], identifier)
|
pname = getNodeValIf(node.children[1], id)
|
||||||
ptyp = getNodeValIf(node.children[0], "primitive_type")
|
ptyp = getNodeValIf(node.children[0], primitive_type)
|
||||||
ttyp = getNodeValIf(node.children[0], "type_identifier")
|
ttyp = getNodeValIf(node.children[0], type_identifier)
|
||||||
|
|
||||||
if pname.len() == 0:
|
if pname.len() == 0:
|
||||||
return
|
return
|
||||||
|
|
@ -51,48 +51,51 @@ proc typeScan(node: ref Ast, sym, identifier, offset: string): string =
|
||||||
result = &"{offset}{pname.getIdentifier()}: {ptyp.getType()}"
|
result = &"{offset}{pname.getIdentifier()}: {ptyp.getType()}"
|
||||||
elif ttyp.nBl:
|
elif ttyp.nBl:
|
||||||
result = &"{offset}{pname.getIdentifier()}: {ttyp}"
|
result = &"{offset}{pname.getIdentifier()}: {ttyp}"
|
||||||
elif node.children[0].sym in ["struct_specifier", "enum_specifier"] and node.children[0].children.len() == 1:
|
elif node.children[0].sym in [struct_specifier, enum_specifier] and node.children[0].children.len() == 1:
|
||||||
let styp = getNodeValIf(node.children[0].children[0], "type_identifier")
|
let styp = getNodeValIf(node.children[0].children[0], type_identifier)
|
||||||
if styp.nBl:
|
if styp.nBl:
|
||||||
result = &"{offset}{pname.getIdentifier()}: {styp}"
|
result = &"{offset}{pname.getIdentifier()}: {styp}"
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
proc structSpecifier(node: ref Ast, name = "") =
|
proc pStructSpecifier(node: ref Ast, name = "") =
|
||||||
var stmt: string
|
var stmt: string
|
||||||
if node.children.len() == 1 and name notin gTypes:
|
if node.children.len() == 1 and name notin gTypes:
|
||||||
case node.children[0].sym:
|
case node.children[0].sym:
|
||||||
of "type_identifier":
|
of type_identifier:
|
||||||
let typ = getNodeValIf(node.children[0], "type_identifier")
|
let typ = getNodeValIf(node.children[0], type_identifier)
|
||||||
if typ.nBl:
|
if typ.nBl:
|
||||||
gTypes.add(name)
|
gTypes.add(name)
|
||||||
if name != typ:
|
if name != typ:
|
||||||
# typedef struct X Y
|
# typedef struct X Y
|
||||||
gTypeStr &= &" {name}* = {typ} #1 structSpecifier()\n"
|
gTypeStr &= &" {name}* = {typ} #1 pStructSpecifier()\n"
|
||||||
else:
|
else:
|
||||||
# typedef struct X X
|
# typedef struct X X
|
||||||
gTypeStr &= &" {name}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #2 structSpecifier()\n"
|
gTypeStr &= &" {name}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #2 pStructSpecifier()\n"
|
||||||
|
|
||||||
of "field_declaration_list":
|
of field_declaration_list:
|
||||||
# typedef struct { fields } X
|
# typedef struct { fields } X
|
||||||
stmt = &" {name}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #3 structSpecifier()\n"
|
stmt = &" {name}* {{.importc: \"{name}\", header: {gCurrentHeader}, bycopy.}} = object #3 pStructSpecifier()\n"
|
||||||
|
|
||||||
for field in node.children[0].children:
|
for field in node.children[0].children:
|
||||||
let ts = typeScan(field, "field_declaration", "field_identifier", " ")
|
let ts = typeScan(field, field_declaration, field_identifier, " ")
|
||||||
if ts.len() == 0:
|
if ts.len() == 0:
|
||||||
return
|
return
|
||||||
stmt &= ts & "\n"
|
stmt &= ts & "\n"
|
||||||
|
|
||||||
gTypes.add(name)
|
gTypes.add(name)
|
||||||
gTypeStr &= stmt
|
gTypeStr &= stmt
|
||||||
elif name.len() == 0 and node.children.len() == 2 and node.children[1].sym == "field_declaration_list":
|
else:
|
||||||
let ename = getNodeValIf(node.children[0], "type_identifier")
|
discard
|
||||||
|
|
||||||
|
elif name.len() == 0 and node.children.len() == 2 and node.children[1].sym == field_declaration_list:
|
||||||
|
let ename = getNodeValIf(node.children[0], type_identifier)
|
||||||
if ename.nBl and ename notin gTypes:
|
if ename.nBl and ename notin gTypes:
|
||||||
# struct X { fields }
|
# struct X { fields }
|
||||||
stmt &= &" {ename}* {{.importc: \"struct {ename}\", header: {gCurrentHeader}, bycopy.}} = object #4 structSpecifier()\n"
|
stmt &= &" {ename}* {{.importc: \"struct {ename}\", header: {gCurrentHeader}, bycopy.}} = object #4 pStructSpecifier()\n"
|
||||||
|
|
||||||
for field in node.children[1].children:
|
for field in node.children[1].children:
|
||||||
let ts = typeScan(field, "field_declaration", "field_identifier", " ")
|
let ts = typeScan(field, field_declaration, field_identifier, " ")
|
||||||
if ts.len() == 0:
|
if ts.len() == 0:
|
||||||
return
|
return
|
||||||
stmt &= ts & "\n"
|
stmt &= ts & "\n"
|
||||||
|
|
@ -100,33 +103,33 @@ proc structSpecifier(node: ref Ast, name = "") =
|
||||||
gTypes.add(name)
|
gTypes.add(name)
|
||||||
gTypeStr &= stmt
|
gTypeStr &= stmt
|
||||||
|
|
||||||
proc enumSpecifier(node: ref Ast, name = "") =
|
proc pEnumSpecifier(node: ref Ast, name = "") =
|
||||||
var
|
var
|
||||||
ename: string
|
ename: string
|
||||||
elid: int
|
elid: int
|
||||||
stmt: string
|
stmt: string
|
||||||
|
|
||||||
if node.children.len() == 1 and node.children[0].sym == "enumerator_list":
|
if node.children.len() == 1 and node.children[0].sym == enumerator_list:
|
||||||
# typedef enum { fields } X
|
# typedef enum { fields } X
|
||||||
ename = name
|
ename = name
|
||||||
elid = 0
|
elid = 0
|
||||||
stmt = &" {name}* = enum #1 enumSpecifier()\n"
|
stmt = &" {name}* = enum #1 pEnumSpecifier()\n"
|
||||||
elif name.len() == 0 and node.children.len() == 2 and node.children[1].sym == "enumerator_list":
|
elif name.len() == 0 and node.children.len() == 2 and node.children[1].sym == enumerator_list:
|
||||||
ename = getNodeValIf(node.children[0], "type_identifier")
|
ename = getNodeValIf(node.children[0], type_identifier)
|
||||||
elid = 1
|
elid = 1
|
||||||
if ename.nBl:
|
if ename.nBl:
|
||||||
# enum X { fields }
|
# enum X { fields }
|
||||||
stmt = &" {ename}* = enum #2 enumSpecifier()\n"
|
stmt = &" {ename}* = enum #2 pEnumSpecifier()\n"
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
for field in node.children[elid].children:
|
for field in node.children[elid].children:
|
||||||
if field.sym == "enumerator":
|
if field.sym == enumerator:
|
||||||
let fname = getNodeValIf(field.children[0], "identifier")
|
let fname = getNodeValIf(field.children[0], identifier)
|
||||||
if field.children.len() == 1:
|
if field.children.len() == 1:
|
||||||
stmt &= &" {fname}\n"
|
stmt &= &" {fname}\n"
|
||||||
elif field.children.len() == 2 and field.children[1].sym == "number_literal":
|
elif field.children.len() == 2 and field.children[1].sym == number_literal:
|
||||||
let num = getNodeValIf(field.children[1], "number_literal")
|
let num = getNodeValIf(field.children[1], number_literal)
|
||||||
stmt &= &" {fname} = {num}\n"
|
stmt &= &" {fname} = {num}\n"
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
@ -135,44 +138,46 @@ proc enumSpecifier(node: ref Ast, name = "") =
|
||||||
gTypes.add(name)
|
gTypes.add(name)
|
||||||
gTypeStr &= stmt
|
gTypeStr &= stmt
|
||||||
|
|
||||||
proc typeDefinition(node: ref Ast) =
|
proc pTypeDefinition(node: ref Ast) =
|
||||||
if node.children.len() == 2:
|
if node.children.len() == 2:
|
||||||
var
|
var
|
||||||
name = getNodeValIf(node.children[1], "type_identifier")
|
name = getNodeValIf(node.children[1], type_identifier)
|
||||||
pname = getNodeValIf(node.children[1], "pointer_declarator")
|
pname = getNodeValIf(node.children[1], pointer_declarator)
|
||||||
ptyp = getNodeValIf(node.children[0], "primitive_type")
|
ptyp = getNodeValIf(node.children[0], primitive_type)
|
||||||
ttyp = getNodeValIf(node.children[0], "type_identifier")
|
ttyp = getNodeValIf(node.children[0], type_identifier)
|
||||||
|
|
||||||
if name.len() == 0 and node.children[1].sym == "pointer_declarator" and node.children[1].children.len() == 1:
|
if name.len() == 0 and node.children[1].sym == pointer_declarator and node.children[1].children.len() == 1:
|
||||||
name = getNodeValIf(node.children[1].children[0], "type_identifier")
|
name = getNodeValIf(node.children[1].children[0], type_identifier)
|
||||||
|
|
||||||
if name.nBl and name notin gTypes:
|
if name.nBl and name notin gTypes:
|
||||||
if ptyp.nBl:
|
if ptyp.nBl:
|
||||||
# typedef int X
|
# typedef int X
|
||||||
gTypes.add(name)
|
gTypes.add(name)
|
||||||
gTypeStr &= &" {name}* = {ptyp.getType()} #1 typeDefinition()\n"
|
gTypeStr &= &" {name}* = {ptyp.getType()} #1 pTypeDefinition()\n"
|
||||||
elif ttyp.nBl:
|
elif ttyp.nBl:
|
||||||
# typedef X Y
|
# typedef X Y
|
||||||
gTypes.add(name)
|
gTypes.add(name)
|
||||||
gTypeStr &= &" {name}* = {ttyp} #2 typeDefinition()\n"
|
gTypeStr &= &" {name}* = {ttyp} #2 pTypeDefinition()\n"
|
||||||
else:
|
else:
|
||||||
case node.children[0].sym:
|
case node.children[0].sym:
|
||||||
of "struct_specifier":
|
of struct_specifier:
|
||||||
structSpecifier(node.children[0], name)
|
pStructSpecifier(node.children[0], name)
|
||||||
of "enum_specifier":
|
of enum_specifier:
|
||||||
enumSpecifier(node.children[0], name)
|
pEnumSpecifier(node.children[0], name)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
proc functionDeclarator(node: ref Ast, typ: string) =
|
proc pFunctionDeclarator(node: ref Ast, typ: string) =
|
||||||
if node.children.len() == 2:
|
if node.children.len() == 2:
|
||||||
let
|
let
|
||||||
name = getNodeValIf(node.children[0], "identifier")
|
name = getNodeValIf(node.children[0], identifier)
|
||||||
|
|
||||||
if name.nBl and name notin gProcs and node.children[1].sym == "parameter_list":
|
if name.nBl and name notin gProcs and node.children[1].sym == parameter_list:
|
||||||
# typ function(typ param1, ...)
|
# typ function(typ param1, ...)
|
||||||
var stmt = &"# functionDeclarator()\nproc {name}*("
|
var stmt = &"# pFunctionDeclarator()\nproc {name}*("
|
||||||
|
|
||||||
for i in 0 .. node.children[1].children.len()-1:
|
for i in 0 .. node.children[1].children.len()-1:
|
||||||
let ts = typeScan(node.children[1].children[i], "parameter_declaration", "identifier", "")
|
let ts = typeScan(node.children[1].children[i], parameter_declaration, identifier, "")
|
||||||
if ts.len() == 0:
|
if ts.len() == 0:
|
||||||
return
|
return
|
||||||
stmt &= ts
|
stmt &= ts
|
||||||
|
|
@ -189,38 +194,40 @@ proc functionDeclarator(node: ref Ast, typ: string) =
|
||||||
gProcs.add(name)
|
gProcs.add(name)
|
||||||
gProcStr &= stmt
|
gProcStr &= stmt
|
||||||
|
|
||||||
proc declaration*(node: ref Ast) =
|
proc pDeclaration*(node: ref Ast) =
|
||||||
if node.children.len() == 2 and node.children[1].sym == "function_declarator":
|
if node.children.len() == 2 and node.children[1].sym == function_declarator:
|
||||||
let
|
let
|
||||||
ptyp = getNodeValIf(node.children[0], "primitive_type")
|
ptyp = getNodeValIf(node.children[0], primitive_type)
|
||||||
ttyp = getNodeValIf(node.children[0], "type_identifier")
|
ttyp = getNodeValIf(node.children[0], type_identifier)
|
||||||
|
|
||||||
if ptyp.nBl:
|
if ptyp.nBl:
|
||||||
functionDeclarator(node.children[1], ptyp.getType())
|
pFunctionDeclarator(node.children[1], ptyp.getType())
|
||||||
elif ttyp.nBl:
|
elif ttyp.nBl:
|
||||||
functionDeclarator(node.children[1], ttyp)
|
pFunctionDeclarator(node.children[1], ttyp)
|
||||||
elif node.children[0].sym == "struct_specifier" and node.children[0].children.len() == 1:
|
elif node.children[0].sym == struct_specifier and node.children[0].children.len() == 1:
|
||||||
let styp = getNodeValIf(node.children[0].children[0], "type_identifier")
|
let styp = getNodeValIf(node.children[0].children[0], type_identifier)
|
||||||
if styp.nBl:
|
if styp.nBl:
|
||||||
functionDeclarator(node.children[1], styp)
|
pFunctionDeclarator(node.children[1], styp)
|
||||||
|
|
||||||
proc genNimAst*(node: ref Ast) =
|
proc genNimAst*(node: ref Ast) =
|
||||||
case node.sym:
|
case node.sym:
|
||||||
of "ERROR":
|
of ERROR:
|
||||||
let (line, col) = getLineCol(node)
|
let (line, col) = getLineCol(node)
|
||||||
echo &"Potentially invalid syntax at line {line} column {col}"
|
echo &"Potentially invalid syntax at line {line} column {col}"
|
||||||
of "preproc_def":
|
of preproc_def:
|
||||||
preprocDef(node)
|
pPreprocDef(node)
|
||||||
of "type_definition":
|
of type_definition:
|
||||||
typeDefinition(node)
|
pTypeDefinition(node)
|
||||||
of "declaration":
|
of declaration:
|
||||||
declaration(node)
|
pDeclaration(node)
|
||||||
of "struct_specifier":
|
of struct_specifier:
|
||||||
if node.parent.sym notin ["type_definition", "declaration"]:
|
if node.parent.sym notin [type_definition, declaration]:
|
||||||
structSpecifier(node)
|
pStructSpecifier(node)
|
||||||
of "enum_specifier":
|
of enum_specifier:
|
||||||
if node.parent.sym notin ["type_definition", "declaration"]:
|
if node.parent.sym notin [type_definition, declaration]:
|
||||||
enumSpecifier(node)
|
pEnumSpecifier(node)
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
for child in node.children:
|
for child in node.children:
|
||||||
genNimAst(child)
|
genNimAst(child)
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ proc getLit*(str: string): string =
|
||||||
str.contains(re"^0x[\d]+$"):
|
str.contains(re"^0x[\d]+$"):
|
||||||
return str
|
return str
|
||||||
|
|
||||||
proc getNodeValIf*(node: ref Ast, esym: string): string =
|
proc getNodeValIf*(node: ref Ast, esym: Sym): string =
|
||||||
if esym != node.sym:
|
if esym != node.sym:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,20 @@
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
type
|
type
|
||||||
|
Sym* = enum
|
||||||
|
ERROR, IGNORED,
|
||||||
|
enumerator, enumerator_list, enum_specifier,
|
||||||
|
declaration,
|
||||||
|
field_declaration, field_declaration_list, field_identifier, function_declarator,
|
||||||
|
identifier,
|
||||||
|
number_literal,
|
||||||
|
parameter_declaration, parameter_list, pointer_declarator, preproc_arg, preproc_def, primitive_type,
|
||||||
|
struct_specifier,
|
||||||
|
type_definition, type_identifier
|
||||||
|
|
||||||
Ast* = object
|
Ast* = object
|
||||||
sym*: string
|
sym*: Sym
|
||||||
start*, stop*: int
|
start*, stop*: uint32
|
||||||
parent*: ref Ast
|
parent*: ref Ast
|
||||||
children*: seq[ref Ast]
|
children*: seq[ref Ast]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@ proc tokenize(fullpath: string) =
|
||||||
else:
|
else:
|
||||||
collect &= $i
|
collect &= $i
|
||||||
|
|
||||||
|
if gTokens.len() == 0:
|
||||||
|
echo "toast binary not installed - nimble install nimterop to force build"
|
||||||
|
quit(1)
|
||||||
|
|
||||||
proc readFromTokens(): ref Ast =
|
proc readFromTokens(): ref Ast =
|
||||||
if idx == gTokens.len():
|
if idx == gTokens.len():
|
||||||
echo "Bad AST"
|
echo "Bad AST"
|
||||||
|
|
@ -35,14 +39,17 @@ proc readFromTokens(): ref Ast =
|
||||||
quit(1)
|
quit(1)
|
||||||
if gTokens[idx+1] != "comment":
|
if gTokens[idx+1] != "comment":
|
||||||
result = new(Ast)
|
result = new(Ast)
|
||||||
result.sym = gTokens[idx+1]
|
try:
|
||||||
result.start = gTokens[idx+2].parseInt()
|
result.sym = parseEnum[Sym](gTokens[idx+1])
|
||||||
result.stop = gTokens[idx+3].parseInt()
|
except:
|
||||||
|
result.sym = IGNORED
|
||||||
|
result.start = gTokens[idx+2].parseInt().uint32
|
||||||
|
result.stop = gTokens[idx+3].parseInt().uint32
|
||||||
result.children = @[]
|
result.children = @[]
|
||||||
idx += 4
|
idx += 4
|
||||||
while gTokens[idx] != ")":
|
while gTokens[idx] != ")":
|
||||||
var res = readFromTokens()
|
var res = readFromTokens()
|
||||||
if not res.isNil() and res.sym.nBl:
|
if not res.isNil():
|
||||||
res.parent = result
|
res.parent = result
|
||||||
result.children.add(res)
|
result.children.add(res)
|
||||||
elif gTokens[idx] == ")":
|
elif gTokens[idx] == ")":
|
||||||
|
|
@ -52,7 +59,7 @@ proc readFromTokens(): ref Ast =
|
||||||
idx += 1
|
idx += 1
|
||||||
|
|
||||||
proc printAst*(node: ref Ast, offset=""): string =
|
proc printAst*(node: ref Ast, offset=""): string =
|
||||||
result = offset & "(" & node.sym & " " & $node.start & " " & $node.stop
|
result = offset & "(" & $node.sym & " " & $node.start & " " & $node.stop
|
||||||
if node.children.len() != 0:
|
if node.children.len() != 0:
|
||||||
result &= "\n"
|
result &= "\n"
|
||||||
for child in node.children:
|
for child in node.children:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue