Use enums for sym, fail if no toast

This commit is contained in:
Ganesh Viswanathan 2018-11-21 17:24:13 -06:00
commit c0481ac41c
4 changed files with 105 additions and 80 deletions

View file

@ -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)

View file

@ -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

View file

@ -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]

View file

@ -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: