Fix #42 - duplicate stylistic identifiers

This commit is contained in:
Ganesh Viswanathan 2019-01-28 00:30:59 -06:00
commit 70aa3e2b5e
5 changed files with 205 additions and 199 deletions

View file

@ -4,7 +4,7 @@ import regex
import "."/[getters, globals, grammar, treesitter/runtime] import "."/[getters, globals, grammar, treesitter/runtime]
proc saveNodeData(node: TSNode): bool = proc saveNodeData(node: TSNode, nimState: NimState): bool =
let name = $node.tsNodeType() let name = $node.tsNodeType()
if name in gAtoms: if name in gAtoms:
var var
@ -27,32 +27,32 @@ proc saveNodeData(node: TSNode): bool =
if node.tsNodePrevNamedSibling().tsNodeIsNull(): if node.tsNodePrevNamedSibling().tsNodeIsNull():
if pname == "pointer_declarator": if pname == "pointer_declarator":
if ppname notin ["function_declarator", "array_declarator"]: if ppname notin ["function_declarator", "array_declarator"]:
gStateRT.data.add(("pointer_declarator", "")) nimState.data.add(("pointer_declarator", ""))
elif ppname == "array_declarator": elif ppname == "array_declarator":
gStateRT.data.add(("array_pointer_declarator", "")) nimState.data.add(("array_pointer_declarator", ""))
elif pname in ["function_declarator", "array_declarator"]: elif pname in ["function_declarator", "array_declarator"]:
if ppname == "pointer_declarator": if ppname == "pointer_declarator":
gStateRT.data.add(("pointer_declarator", "")) nimState.data.add(("pointer_declarator", ""))
gStateRT.data.add((name, val)) nimState.data.add((name, val))
if node.tsNodeType() == "field_identifier" and if node.tsNodeType() == "field_identifier" and
pname == "pointer_declarator" and pname == "pointer_declarator" and
ppname == "function_declarator": ppname == "function_declarator":
if pppname == "pointer_declarator": if pppname == "pointer_declarator":
gStateRT.data.insert(("pointer_declarator", ""), gStateRT.data.len-1) nimState.data.insert(("pointer_declarator", ""), nimState.data.len-1)
gStateRT.data.add(("function_declarator", "")) nimState.data.add(("function_declarator", ""))
elif name in gExpressions: elif name in gExpressions:
if $node.tsNodeParent.tsNodeType() notin gExpressions: if $node.tsNodeParent.tsNodeType() notin gExpressions:
gStateRT.data.add((name, node.getNodeVal())) nimState.data.add((name, node.getNodeVal()))
elif name in ["abstract_pointer_declarator", "enumerator", "field_declaration", "function_declarator"]: elif name in ["abstract_pointer_declarator", "enumerator", "field_declaration", "function_declarator"]:
gStateRT.data.add((name.replace("abstract_", ""), "")) nimState.data.add((name.replace("abstract_", ""), ""))
return true return true
proc searchAstForNode(ast: ref Ast, node: TSNode): bool = proc searchAstForNode(ast: ref Ast, node: TSNode, nimState: NimState): bool =
let let
childNames = node.getTSNodeNamedChildNames().join() childNames = node.getTSNodeNamedChildNames().join()
@ -73,18 +73,18 @@ proc searchAstForNode(ast: ref Ast, node: TSNode): bool =
ast.getAstChildByName($nodeChild.tsNodeType()) ast.getAstChildByName($nodeChild.tsNodeType())
else: else:
ast ast
if not searchAstForNode(astChild, nodeChild): if not searchAstForNode(astChild, nodeChild, nimState):
flag = false flag = false
break break
if flag: if flag:
return node.saveNodeData() return node.saveNodeData(nimState)
else: else:
return node.saveNodeData() return node.saveNodeData(nimState)
elif node.getTSNodeNamedChildCountSansComments() == 0: elif node.getTSNodeNamedChildCountSansComments() == 0:
return node.saveNodeData() return node.saveNodeData(nimState)
proc searchAst(root: TSNode) = proc searchAst(root: TSNode, astTable: AstTable, nimState: NimState) =
var var
node = root node = root
nextnode: TSNode nextnode: TSNode
@ -94,18 +94,18 @@ proc searchAst(root: TSNode) =
if not node.tsNodeIsNull() and depth > -1: if not node.tsNodeIsNull() and depth > -1:
let let
name = $node.tsNodeType() name = $node.tsNodeType()
if name in gStateRT.ast: if name in astTable:
for ast in gStateRT.ast[name]: for ast in astTable[name]:
if searchAstForNode(ast, node): if searchAstForNode(ast, node, nimState):
ast.tonim(ast, node) ast.tonim(ast, node, nimState)
if gStateRT.debug: if gStateRT.debug:
gStateRT.debugStr &= "\n\n# " & gStateRT.data.join("\n# ") nimState.debugStr &= "\n\n# " & nimState.data.join("\n# ")
break break
gStateRT.data = @[] nimState.data = @[]
else: else:
break break
if $node.tsNodeType() notin gStateRT.ast and node.tsNodeNamedChildCount() != 0: if $node.tsNodeType() notin astTable and node.tsNodeNamedChildCount() != 0:
nextnode = node.tsNodeNamedChild(0) nextnode = node.tsNodeNamedChild(0)
depth += 1 depth += 1
else: else:
@ -128,28 +128,30 @@ proc searchAst(root: TSNode) =
if node == root: if node == root:
break break
proc printNim*(fullpath: string, root: TSNode) = proc printNim*(fullpath: string, root: TSNode, astTable: AstTable) =
parseGrammar()
echo "{.experimental: \"codeReordering\".}" echo "{.experimental: \"codeReordering\".}"
var fp = fullpath.replace("\\", "/") var
gStateRT.currentHeader = getCurrentHeader(fullpath) nimState = new(NimState)
gStateRT.constStr &= &" {gStateRT.currentHeader} = \"{fp}\"\n" fp = fullpath.replace("\\", "/")
nimState.identifiers = newTable[string, string]()
root.searchAst() nimState.currentHeader = getCurrentHeader(fullpath)
nimState.constStr &= &" {nimState.currentHeader} = \"{fp}\"\n"
if gStateRT.enumStr.nBl: root.searchAst(astTable, nimState)
echo gStateRT.enumStr
if gStateRT.constStr.nBl: if nimState.enumStr.nBl:
echo "const\n" & gStateRT.constStr echo nimState.enumStr
if gStateRT.typeStr.nBl: if nimState.constStr.nBl:
echo "type\n" & gStateRT.typeStr echo "const\n" & nimState.constStr
if gStateRT.procStr.nBl: if nimState.typeStr.nBl:
echo gStateRT.procStr echo "type\n" & nimState.typeStr
if gStateRT.debug and gStateRT.debugStr.nBl: if nimState.procStr.nBl:
echo gStateRT.debugStr echo nimState.procStr
if gStateRT.debug and nimState.debugStr.nBl:
echo nimState.debugStr

View file

@ -103,15 +103,15 @@ proc getIdentifier*(str: string, kind: NimSymKind): string =
checkUnderscores(result, &"Identifier '{str}' still contains leading/trailing underscores '_' after 'cPlugin:onSymbol()': result '{result}'") checkUnderscores(result, &"Identifier '{str}' still contains leading/trailing underscores '_' after 'cPlugin:onSymbol()': result '{result}'")
else: else:
result = str result = str
checkUnderscores(result, &"Identifier '{result}' contains unsupported leading/trailing underscores '_': use 'cPlugin:onSymbol()' to handle") checkUnderscores(result, &"Identifier '{result}' contains unsupported leading/trailing underscores '_': use 'cPlugin:onSymbol()' to remove")
if result in gReserved: if result in gReserved:
result = &"`{result}`" result = &"`{result}`"
proc getUniqueIdentifier*(existing: HashSet[string], prefix = ""): string = proc getUniqueIdentifier*(existing: TableRef[string, string], prefix = ""): string =
var var
name = prefix & "_" & gStateRT.sourceFile.extractFilename().multiReplace([(".", ""), ("-", "")]) name = prefix & "_" & gStateRT.sourceFile.extractFilename().multiReplace([(".", ""), ("-", "")])
nimName = name.replace("_", "").toLowerAscii nimName = name[0] & name[1 .. ^1].replace("_", "").toLowerAscii
count = 1 count = 1
while (nimName & $count) in existing: while (nimName & $count) in existing:
@ -119,16 +119,17 @@ proc getUniqueIdentifier*(existing: HashSet[string], prefix = ""): string =
return name & $count return name & $count
proc addNewIdentifer*(existing: var HashSet[string], name: string): bool = proc addNewIdentifer*(existing: var TableRef[string, string], name: string): bool =
if name notin gStateRT.symOverride: if name notin gStateRT.symOverride:
let let
nimName = nimName = name[0] & name[1 .. ^1].replace("_", "").toLowerAscii
if existing == gStateRT.types:
name[0] & name[1 .. ^1].replace("_", "").toLowerAscii
else:
name.replace("_", "").toLowerAscii
return not existing.containsOrIncl(nimName) if existing.hasKey(nimName):
doAssert name == existing[nimName], &"Identifier '{name}' is a stylistic duplicate of identifier '{existing[nimName]}', use 'cPlugin:onSymbol()' to rename"
result = false
else:
existing[nimName] = name
result = true
proc getPtrType*(str: string): string = proc getPtrType*(str: string): string =
result = case str: result = case str:

View file

@ -44,25 +44,29 @@ type
recursive*: bool recursive*: bool
children*: seq[ref Ast] children*: seq[ref Ast]
when not declared(CIMPORT): when not declared(CIMPORT):
tonim*: proc (ast: ref Ast, node: TSNode) tonim*: proc (ast: ref Ast, node: TSNode, nimState: NimState)
regex*: Regex regex*: Regex
AstTable = TableRef[string, seq[ref Ast]]
State = object State = object
compile*, defines*, headers*, includeDirs*, searchDirs*, symOverride*: seq[string] compile*, defines*, headers*, includeDirs*, searchDirs*, symOverride*: seq[string]
nocache*, debug*, past*, preprocess*, pnim*, pretty*, recurse*: bool nocache*, debug*, past*, preprocess*, pnim*, pretty*, recurse*: bool
consts*, enums*, procs*, types*: HashSet[string] code*, mode*, pluginSourcePath*, sourceFile*: string
constStr*, debugStr*, enumStr*, procStr*, typeStr*: string
code*, currentHeader*, mode*, pluginSourcePath*, sourceFile*: string
ast*: Table[string, seq[ref Ast]]
data*: seq[tuple[name, val: string]]
when not declared(CIMPORT):
grammar*: seq[tuple[grammar: string, call: proc(ast: ref Ast, node: TSNode) {.nimcall.}]]
onSymbol*: OnSymbol onSymbol*: OnSymbol
NimState = ref object
identifiers*: TableRef[string, string]
constStr*, debugStr*, enumStr*, procStr*, typeStr*: string
currentHeader*: string
data*: seq[tuple[name, val: string]]
var var
gStateCT {.compiletime, used.}: State gStateCT {.compiletime, used.}: State
gStateRT {.used.}: State gStateRT {.used.}: State
@ -78,4 +82,4 @@ type CompileMode = enum
const modeDefault {.used.} = $cpp # TODO: USE this everywhere relevant const modeDefault {.used.} = $cpp # TODO: USE this everywhere relevant
when not declared(CIMPORT): when not declared(CIMPORT):
export gAtoms, gExpressions, gEnumVals, Kind, Ast, State, gStateRT, nBl, CompileMode, modeDefault export gAtoms, gExpressions, gEnumVals, Kind, Ast, AstTable, State, NimState, gStateRT, nBl, CompileMode, modeDefault

View file

@ -4,21 +4,24 @@ import regex
import "."/[getters, globals, lisp, treesitter/runtime] import "."/[getters, globals, lisp, treesitter/runtime]
proc initGrammar() = type
Grammar = seq[tuple[grammar: string, call: proc(ast: ref Ast, node: TSNode, nimState: NimState) {.nimcall.}]]
proc initGrammar(): Grammar =
# #define X Y # #define X Y
gStateRT.grammar.add((""" result.add(("""
(preproc_def (preproc_def
(identifier) (identifier)
(preproc_arg) (preproc_arg)
) )
""", """,
proc (ast: ref Ast, node: TSNode) = proc (ast: ref Ast, node: TSNode, nimState: NimState) =
let let
name = gStateRT.data[0].val.getIdentifier(nskConst) name = nimState.data[0].val.getIdentifier(nskConst)
val = gStateRT.data[1].val.getLit() val = nimState.data[1].val.getLit()
if name.nBl and val.nBl and gStateRT.consts.addNewIdentifer(name): if name.nBl and val.nBl and nimState.identifiers.addNewIdentifer(name):
gStateRT.constStr &= &" {name}* = {val}\n" nimState.constStr &= &" {name}* = {val}\n"
)) ))
let let
@ -67,18 +70,18 @@ proc initGrammar() =
""" """
template funcParamCommon(fname, pname, ptyp, pptr, pout, count, i: untyped): untyped = template funcParamCommon(fname, pname, ptyp, pptr, pout, count, i: untyped): untyped =
ptyp = gStateRT.data[i].val.getIdentifier(nskType) ptyp = nimState.data[i].val.getIdentifier(nskType)
doAssert ptyp.nBl, &"Blank param type for '{fname}', originally '{gStateRT.data[i].val}'" doAssert ptyp.nBl, &"Blank param type for '{fname}', originally '{nimState.data[i].val}'"
if i+1 < gStateRT.data.len and gStateRT.data[i+1].name == "pointer_declarator": if i+1 < nimState.data.len and nimState.data[i+1].name == "pointer_declarator":
pptr = "ptr " pptr = "ptr "
i += 1 i += 1
else: else:
pptr = "" pptr = ""
if i+1 < gStateRT.data.len and gStateRT.data[i+1].name == "identifier": if i+1 < nimState.data.len and nimState.data[i+1].name == "identifier":
pname = gStateRT.data[i+1].val.getIdentifier(nskParam) pname = nimState.data[i+1].val.getIdentifier(nskParam)
doAssert pname.nBl, &"Blank param name for '{fname}', originally '{gStateRT.data[i+1].val}'" doAssert pname.nBl, &"Blank param name for '{fname}', originally '{nimState.data[i+1].val}'"
i += 2 i += 2
else: else:
pname = "a" & $count pname = "a" & $count
@ -92,7 +95,7 @@ proc initGrammar() =
# typedef X Y # typedef X Y
# typedef struct X Y # typedef struct X Y
# typedef ?* Y # typedef ?* Y
gStateRT.grammar.add((&""" result.add((&"""
(type_definition (type_definition
{typeGrammar} {typeGrammar}
(type_identifier!) (type_identifier!)
@ -105,17 +108,17 @@ proc initGrammar() =
{funcGrammar} {funcGrammar}
) )
""", """,
proc (ast: ref Ast, node: TSNode) = proc (ast: ref Ast, node: TSNode, nimState: NimState) =
var var
i = 0 i = 0
typ = gStateRT.data[i].val.getIdentifier(nskType) typ = nimState.data[i].val.getIdentifier(nskType)
name = "" name = ""
tptr = "" tptr = ""
aptr = "" aptr = ""
i += 1 i += 1
if i < gStateRT.data.len: if i < nimState.data.len:
case gStateRT.data[i].name: case nimState.data[i].name:
of "pointer_declarator": of "pointer_declarator":
tptr = "ptr " tptr = "ptr "
i += 1 i += 1
@ -123,19 +126,19 @@ proc initGrammar() =
aptr = "ptr " aptr = "ptr "
i += 1 i += 1
if i < gStateRT.data.len: if i < nimState.data.len:
name = gStateRT.data[i].val.getIdentifier(nskType) name = nimState.data[i].val.getIdentifier(nskType)
i += 1 i += 1
if typ.nBl and name.nBl and gStateRT.types.addNewIdentifer(name): if typ.nBl and name.nBl and nimState.identifiers.addNewIdentifer(name):
if i < gStateRT.data.len and gStateRT.data[^1].name == "function_declarator": if i < nimState.data.len and nimState.data[^1].name == "function_declarator":
var var
fname = name fname = name
pout, pname, ptyp, pptr = "" pout, pname, ptyp, pptr = ""
count = 1 count = 1
while i < gStateRT.data.len: while i < nimState.data.len:
if gStateRT.data[i].name == "function_declarator": if nimState.data[i].name == "function_declarator":
break break
funcParamCommon(fname, pname, ptyp, pptr, pout, count, i) funcParamCommon(fname, pname, ptyp, pptr, pout, count, i)
@ -144,29 +147,29 @@ proc initGrammar() =
pout = pout[0 .. ^2] pout = pout[0 .. ^2]
if tptr == "ptr " or typ != "object": if tptr == "ptr " or typ != "object":
gStateRT.typeStr &= &" {name}* = proc({pout}): {getPtrType(tptr&typ)} {{.nimcall.}}\n" nimState.typeStr &= &" {name}* = proc({pout}): {getPtrType(tptr&typ)} {{.nimcall.}}\n"
else: else:
gStateRT.typeStr &= &" {name}* = proc({pout}) {{.nimcall.}}\n" nimState.typeStr &= &" {name}* = proc({pout}) {{.nimcall.}}\n"
else: else:
if i < gStateRT.data.len and gStateRT.data[i].name in ["identifier", "number_literal"]: if i < nimState.data.len and nimState.data[i].name in ["identifier", "number_literal"]:
var var
flen = gStateRT.data[i].val flen = nimState.data[i].val
if gStateRT.data[i].name == "identifier": if nimState.data[i].name == "identifier":
flen = flen.getIdentifier(nskConst) flen = flen.getIdentifier(nskConst)
doAssert flen.len != 0, &"Blank array length for '{name}', originally '{gStateRT.data[i].val}'" doAssert flen.len != 0, &"Blank array length for '{name}', originally '{nimState.data[i].val}'"
gStateRT.typeStr &= &" {name}* = {aptr}array[{flen}, {getPtrType(tptr&typ)}]\n" nimState.typeStr &= &" {name}* = {aptr}array[{flen}, {getPtrType(tptr&typ)}]\n"
else: else:
if name == typ: if name == typ:
gStateRT.typeStr &= &" {name}* = object\n" nimState.typeStr &= &" {name}* = object\n"
else: else:
gStateRT.typeStr &= &" {name}* = {getPtrType(tptr&typ)}\n" nimState.typeStr &= &" {name}* = {getPtrType(tptr&typ)}\n"
)) ))
proc pDupTypeCommon(nname: string, fend: int, isEnum=false) = proc pDupTypeCommon(nname: string, fend: int, nimState: NimState, isEnum=false) =
var var
dname = gStateRT.data[^1].val dname = nimState.data[^1].val
ndname = gStateRT.data[^1].val.getIdentifier(nskType) ndname = nimState.data[^1].val.getIdentifier(nskType)
dptr = dptr =
if fend == 2: if fend == 2:
"ptr " "ptr "
@ -175,14 +178,14 @@ proc initGrammar() =
if ndname.nBl and ndname != nname: if ndname.nBl and ndname != nname:
if isEnum: if isEnum:
if gStateRT.enums.addNewIdentifer(ndname): if nimState.identifiers.addNewIdentifer(ndname):
gStateRT.enumStr &= &"type {ndname}* = {dptr}{nname}\n" nimState.enumStr &= &"type {ndname}* = {dptr}{nname}\n"
else: else:
if gStateRT.types.addNewIdentifer(ndname): if nimState.identifiers.addNewIdentifer(ndname):
gStateRT.typeStr &= nimState.typeStr &=
&" {ndname}* {{.importc: \"{dname}\", header: {gStateRT.currentHeader}, bycopy.}} = {dptr}{nname}\n" &" {ndname}* {{.importc: \"{dname}\", header: {nimState.currentHeader}, bycopy.}} = {dptr}{nname}\n"
proc pStructCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int) = proc pStructCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int, nimState: NimState) =
var var
nname = name.getIdentifier(nskType) nname = name.getIdentifier(nskType)
prefix = "" prefix = ""
@ -210,29 +213,29 @@ proc initGrammar() =
union = " {.union.}" union = " {.union.}"
break break
if nname.nBl and gStateRT.types.addNewIdentifer(nname): if nname.nBl and nimState.identifiers.addNewIdentifer(nname):
if gStateRT.data.len == 1: if nimState.data.len == 1:
gStateRT.typeStr &= &" {nname}* {{.bycopy.}} = object{union}\n" nimState.typeStr &= &" {nname}* {{.bycopy.}} = object{union}\n"
else: else:
gStateRT.typeStr &= &" {nname}* {{.importc: \"{prefix}{name}\", header: {gStateRT.currentHeader}, bycopy.}} = object{union}\n" nimState.typeStr &= &" {nname}* {{.importc: \"{prefix}{name}\", header: {nimState.currentHeader}, bycopy.}} = object{union}\n"
var var
i = fstart i = fstart
ftyp, fname: string ftyp, fname: string
fptr = "" fptr = ""
aptr = "" aptr = ""
while i < gStateRT.data.len-fend: while i < nimState.data.len-fend:
fptr = "" fptr = ""
aptr = "" aptr = ""
if gStateRT.data[i].name == "field_declaration": if nimState.data[i].name == "field_declaration":
i += 1 i += 1
continue continue
if gStateRT.data[i].name notin ["field_identifier", "pointer_declarator", "array_pointer_declarator"]: if nimState.data[i].name notin ["field_identifier", "pointer_declarator", "array_pointer_declarator"]:
ftyp = gStateRT.data[i].val.getType() ftyp = nimState.data[i].val.getType()
i += 1 i += 1
case gStateRT.data[i].name: case nimState.data[i].name:
of "pointer_declarator": of "pointer_declarator":
fptr = "ptr " fptr = "ptr "
i += 1 i += 1
@ -240,26 +243,26 @@ proc initGrammar() =
aptr = "ptr " aptr = "ptr "
i += 1 i += 1
fname = gStateRT.data[i].val.getIdentifier(nskField) fname = nimState.data[i].val.getIdentifier(nskField)
doAssert fname.len != 0, &"Blank field name for '{nname}', originally '{gStateRT.data[i].val}'" doAssert fname.len != 0, &"Blank field name for '{nname}', originally '{nimState.data[i].val}'"
if i+1 < gStateRT.data.len-fend and gStateRT.data[i+1].name in gEnumVals: if i+1 < nimState.data.len-fend and nimState.data[i+1].name in gEnumVals:
let let
flen = gStateRT.data[i+1].val.getNimExpression() flen = nimState.data[i+1].val.getNimExpression()
gStateRT.typeStr &= &" {fname}*: {aptr}array[{flen}, {getPtrType(fptr&ftyp)}]\n" nimState.typeStr &= &" {fname}*: {aptr}array[{flen}, {getPtrType(fptr&ftyp)}]\n"
i += 2 i += 2
elif i+1 < gStateRT.data.len-fend and gStateRT.data[i+1].name == "function_declarator": elif i+1 < nimState.data.len-fend and nimState.data[i+1].name == "function_declarator":
var var
pout, pname, ptyp, pptr = "" pout, pname, ptyp, pptr = ""
count = 1 count = 1
i += 2 i += 2
while i < gStateRT.data.len-fend: while i < nimState.data.len-fend:
if gStateRT.data[i].name == "function_declarator": if nimState.data[i].name == "function_declarator":
i += 1 i += 1
continue continue
if gStateRT.data[i].name == "field_declaration": if nimState.data[i].name == "field_declaration":
break break
funcParamCommon(fname, pname, ptyp, pptr, pout, count, i) funcParamCommon(fname, pname, ptyp, pptr, pout, count, i)
@ -267,20 +270,20 @@ proc initGrammar() =
if pout.len != 0 and pout[^1] == ',': if pout.len != 0 and pout[^1] == ',':
pout = pout[0 .. ^2] pout = pout[0 .. ^2]
if fptr == "ptr " or ftyp != "object": if fptr == "ptr " or ftyp != "object":
gStateRT.typeStr &= &" {fname}*: proc({pout}): {getPtrType(fptr&ftyp)} {{.nimcall.}}\n" nimState.typeStr &= &" {fname}*: proc({pout}): {getPtrType(fptr&ftyp)} {{.nimcall.}}\n"
else: else:
gStateRT.typeStr &= &" {fname}*: proc({pout}) {{.nimcall.}}\n" nimState.typeStr &= &" {fname}*: proc({pout}) {{.nimcall.}}\n"
i += 1 i += 1
else: else:
if ftyp == "object": if ftyp == "object":
gStateRT.typeStr &= &" {fname}*: pointer\n" nimState.typeStr &= &" {fname}*: pointer\n"
else: else:
gStateRT.typeStr &= &" {fname}*: {getPtrType(fptr&ftyp)}\n" nimState.typeStr &= &" {fname}*: {getPtrType(fptr&ftyp)}\n"
i += 1 i += 1
if node.tsNodeType() == "type_definition" and if node.tsNodeType() == "type_definition" and
gStateRT.data[^1].name == "type_identifier" and gStateRT.data[^1].val.len != 0: nimState.data[^1].name == "type_identifier" and nimState.data[^1].val.len != 0:
pDupTypeCommon(nname, fend, false) pDupTypeCommon(nname, fend, nimState, false)
let let
fieldGrammar = &""" fieldGrammar = &"""
@ -313,18 +316,18 @@ proc initGrammar() =
""" """
# struct X {} # struct X {}
gStateRT.grammar.add((&""" result.add((&"""
(struct_specifier|union_specifier (struct_specifier|union_specifier
(type_identifier) (type_identifier)
{fieldListGrammar} {fieldListGrammar}
) )
""", """,
proc (ast: ref Ast, node: TSNode) = proc (ast: ref Ast, node: TSNode, nimState: NimState) =
pStructCommon(ast, node, gStateRT.data[0].val, 1, 1) pStructCommon(ast, node, nimState.data[0].val, 1, 1, nimState)
)) ))
# typedef struct X {} # typedef struct X {}
gStateRT.grammar.add((&""" result.add((&"""
(type_definition (type_definition
(struct_specifier|union_specifier (struct_specifier|union_specifier
(type_identifier?) (type_identifier?)
@ -336,67 +339,67 @@ proc initGrammar() =
) )
) )
""", """,
proc (ast: ref Ast, node: TSNode) = proc (ast: ref Ast, node: TSNode, nimState: NimState) =
var var
fstart = 0 fstart = 0
fend = 1 fend = 1
if gStateRT.data[^2].name == "pointer_declarator": if nimState.data[^2].name == "pointer_declarator":
fend = 2 fend = 2
if gStateRT.data.len > 1 and if nimState.data.len > 1 and
gStateRT.data[0].name == "type_identifier" and nimState.data[0].name == "type_identifier" and
gStateRT.data[1].name != "field_identifier": nimState.data[1].name != "field_identifier":
fstart = 1 fstart = 1
pStructCommon(ast, node, gStateRT.data[0].val, fstart, fend) pStructCommon(ast, node, nimState.data[0].val, fstart, fend, nimState)
else: else:
pStructCommon(ast, node, gStateRT.data[^1].val, fstart, fend) pStructCommon(ast, node, nimState.data[^1].val, fstart, fend, nimState)
)) ))
proc pEnumCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int) = proc pEnumCommon(ast: ref Ast, node: TSNode, name: string, fstart, fend: int, nimState: NimState) =
let nname = let nname =
if name.len == 0: if name.len == 0:
getUniqueIdentifier(gStateRT.enums, "Enum") getUniqueIdentifier(nimState.identifiers, "Enum")
else: else:
name.getIdentifier(nskType) name.getIdentifier(nskType)
if nname.nBl and gStateRT.enums.addNewIdentifer(nname): if nname.nBl and nimState.identifiers.addNewIdentifer(nname):
gStateRT.enumStr &= &"\ntype {nname}* = distinct int" nimState.enumStr &= &"\ntype {nname}* = distinct int"
gStateRT.enumStr &= &"\nconverter enumToInt(en: {nname}): int {{.used.}} = en.int\n" nimState.enumStr &= &"\nconverter enumToInt(en: {nname}): int {{.used.}} = en.int\n"
var var
i = fstart i = fstart
count = 0 count = 0
while i < gStateRT.data.len-fend: while i < nimState.data.len-fend:
if gStateRT.data[i].name == "enumerator": if nimState.data[i].name == "enumerator":
i += 1 i += 1
continue continue
let let
fname = gStateRT.data[i].val.getIdentifier(nskEnumField) fname = nimState.data[i].val.getIdentifier(nskEnumField)
if i+1 < gStateRT.data.len-fend and if i+1 < nimState.data.len-fend and
gStateRT.data[i+1].name in gEnumVals: nimState.data[i+1].name in gEnumVals:
if fname.nBl and gStateRT.consts.addNewIdentifer(fname): if fname.nBl and nimState.identifiers.addNewIdentifer(fname):
gStateRT.constStr &= &" {fname}* = ({gStateRT.data[i+1].val.getNimExpression()}).{nname}\n" nimState.constStr &= &" {fname}* = ({nimState.data[i+1].val.getNimExpression()}).{nname}\n"
try: try:
count = gStateRT.data[i+1].val.parseInt() + 1 count = nimState.data[i+1].val.parseInt() + 1
except: except:
count += 1 count += 1
i += 2 i += 2
else: else:
if fname.nBl and gStateRT.consts.addNewIdentifer(fname): if fname.nBl and nimState.identifiers.addNewIdentifer(fname):
gStateRT.constStr &= &" {fname}* = {count}.{nname}\n" nimState.constStr &= &" {fname}* = {count}.{nname}\n"
i += 1 i += 1
count += 1 count += 1
if node.tsNodeType() == "type_definition" and if node.tsNodeType() == "type_definition" and
gStateRT.data[^1].name == "type_identifier" and gStateRT.data[^1].val.len != 0: nimState.data[^1].name == "type_identifier" and nimState.data[^1].val.len != 0:
pDupTypeCommon(nname, fend, true) pDupTypeCommon(nname, fend, nimState, true)
# enum X {} # enum X {}
gStateRT.grammar.add((""" result.add(("""
(enum_specifier (enum_specifier
(type_identifier?) (type_identifier?)
(enumerator_list (enumerator_list
@ -407,46 +410,46 @@ proc initGrammar() =
) )
) )
""" % gEnumVals.join("|"), """ % gEnumVals.join("|"),
proc (ast: ref Ast, node: TSNode) = proc (ast: ref Ast, node: TSNode, nimState: NimState) =
var var
name = "" name = ""
offset = 0 offset = 0
if gStateRT.data[0].name == "type_identifier": if nimState.data[0].name == "type_identifier":
name = gStateRT.data[0].val name = nimState.data[0].val
offset = 1 offset = 1
pEnumCommon(ast, node, name, offset, 0) pEnumCommon(ast, node, name, offset, 0, nimState)
)) ))
# typedef enum {} X # typedef enum {} X
gStateRT.grammar.add((&""" result.add((&"""
(type_definition (type_definition
{gStateRT.grammar[^1].grammar} {result[^1].grammar}
(type_identifier!) (type_identifier!)
(pointer_declarator (pointer_declarator
(type_identifier) (type_identifier)
) )
) )
""", """,
proc (ast: ref Ast, node: TSNode) = proc (ast: ref Ast, node: TSNode, nimState: NimState) =
var var
fstart = 0 fstart = 0
fend = 1 fend = 1
if gStateRT.data[^2].name == "pointer_declarator": if nimState.data[^2].name == "pointer_declarator":
fend = 2 fend = 2
if gStateRT.data[0].name == "type_identifier": if nimState.data[0].name == "type_identifier":
fstart = 1 fstart = 1
pEnumCommon(ast, node, gStateRT.data[0].val, fstart, fend) pEnumCommon(ast, node, nimState.data[0].val, fstart, fend, nimState)
else: else:
pEnumCommon(ast, node, gStateRT.data[^1].val, fstart, fend) pEnumCommon(ast, node, nimState.data[^1].val, fstart, fend, nimState)
)) ))
# typ function(typ param1, ...) # typ function(typ param1, ...)
gStateRT.grammar.add((&""" result.add((&"""
(declaration (declaration
(storage_class_specifier?) (storage_class_specifier?)
{typeGrammar} {typeGrammar}
@ -456,32 +459,32 @@ proc initGrammar() =
{funcGrammar} {funcGrammar}
) )
""", """,
proc (ast: ref Ast, node: TSNode) = proc (ast: ref Ast, node: TSNode, nimState: NimState) =
var var
ftyp = gStateRT.data[0].val.getIdentifier(nskType) ftyp = nimState.data[0].val.getIdentifier(nskType)
fptr = "" fptr = ""
i = 1 i = 1
while i < gStateRT.data.len: while i < nimState.data.len:
if gStateRT.data[i].name == "function_declarator": if nimState.data[i].name == "function_declarator":
i += 1 i += 1
continue continue
if gStateRT.data[i].name == "pointer_declarator": if nimState.data[i].name == "pointer_declarator":
fptr = "ptr " fptr = "ptr "
i += 1 i += 1
else: else:
fptr = "" fptr = ""
var var
fname = gStateRT.data[i].val fname = nimState.data[i].val
fnname = fname.getIdentifier(nskProc) fnname = fname.getIdentifier(nskProc)
pout, pname, ptyp, pptr = "" pout, pname, ptyp, pptr = ""
count = 1 count = 1
i += 1 i += 1
while i < gStateRT.data.len: while i < nimState.data.len:
if gStateRT.data[i].name == "function_declarator": if nimState.data[i].name == "function_declarator":
break break
funcParamCommon(fnname, pname, ptyp, pptr, pout, count, i) funcParamCommon(fnname, pname, ptyp, pptr, pout, count, i)
@ -489,11 +492,11 @@ proc initGrammar() =
if pout.len != 0 and pout[^1] == ',': if pout.len != 0 and pout[^1] == ',':
pout = pout[0 .. ^2] pout = pout[0 .. ^2]
if ftyp.nBl and fnname.nBl and gStateRT.procs.addNewIdentifer(fnname): if ftyp.nBl and fnname.nBl and nimState.identifiers.addNewIdentifer(fnname):
if fptr == "ptr " or ftyp != "object": if fptr == "ptr " or ftyp != "object":
gStateRT.procStr &= &"proc {fnname}*({pout}): {getPtrType(fptr&ftyp)} {{.importc: \"{fname}\", header: {gStateRT.currentHeader}.}}\n" nimState.procStr &= &"proc {fnname}*({pout}): {getPtrType(fptr&ftyp)} {{.importc: \"{fname}\", header: {nimState.currentHeader}.}}\n"
else: else:
gStateRT.procStr &= &"proc {fnname}*({pout}) {{.importc: \"{fname}\", header: {gStateRT.currentHeader}.}}\n" nimState.procStr &= &"proc {fnname}*({pout}) {{.importc: \"{fname}\", header: {nimState.currentHeader}.}}\n"
)) ))
@ -512,28 +515,23 @@ proc initRegex(ast: ref Ast) =
echo reg echo reg
raise newException(Exception, getCurrentExceptionMsg()) raise newException(Exception, getCurrentExceptionMsg())
proc parseGrammar*() = proc parseGrammar*(): AstTable =
gStateRT.consts.init() let grammars = initGrammar()
gStateRT.enums.init()
gStateRT.procs.init()
gStateRT.types.init()
initGrammar() result = newTable[string, seq[ref Ast]]()
for i in 0 .. grammars.len-1:
gStateRT.ast = initTable[string, seq[ref Ast]]()
for i in 0 .. gStateRT.grammar.len-1:
var var
ast = gStateRT.grammar[i].grammar.parseLisp() ast = grammars[i].grammar.parseLisp()
ast.tonim = gStateRT.grammar[i].call ast.tonim = grammars[i].call
ast.initRegex() ast.initRegex()
for n in ast.name.split("|"): for n in ast.name.split("|"):
if n notin gStateRT.ast: if n notin result:
gStateRT.ast[n] = @[ast] result[n] = @[ast]
else: else:
gStateRT.ast[n].add(ast) result[n].add(ast)
proc printGrammar*() = proc printGrammar*(astTable: AstTable) =
for name in gStateRT.ast.keys(): for name in astTable.keys():
for ast in gStateRT.ast[name]: for ast in astTable[name]:
echo ast.printAst() echo ast.printAst()

View file

@ -53,7 +53,7 @@ proc printLisp(root: TSNode) =
if node == root: if node == root:
break break
proc process(path: string) = proc process(path: string, astTable: AstTable) =
if not existsFile(path): if not existsFile(path):
echo "Invalid path " & path echo "Invalid path " & path
return return
@ -97,7 +97,7 @@ proc process(path: string) =
if gStateRT.past: if gStateRT.past:
printLisp(root) printLisp(root)
elif gStateRT.pnim: elif gStateRT.pnim:
printNim(path, root) printNim(path, root, astTable)
elif gStateRT.preprocess: elif gStateRT.preprocess:
echo gStateRT.code echo gStateRT.code
@ -136,11 +136,12 @@ proc main(
if pluginSourcePath.nBl: if pluginSourcePath.nBl:
loadPlugin(pluginSourcePath) loadPlugin(pluginSourcePath)
let
astTable = parseGrammar()
if pgrammar: if pgrammar:
parseGrammar() astTable.printGrammar()
printGrammar()
elif source.len != 0: elif source.len != 0:
process(source[0]) process(source[0], astTable)
when isMainModule: when isMainModule:
import cligen import cligen