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