aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGanesh Viswanathan <dev@genotrance.com>2019-01-18 21:52:29 -0600
committerGanesh Viswanathan <dev@genotrance.com>2019-01-18 21:52:29 -0600
commitcd8a263f85a4ade35ec59bbe8360ece880f681ce (patch)
treed72f103b0edae320c7782d0491078339771abee2
parent287980c9edbb1f037b1827b62ca8cc3453b2203a (diff)
downloadnimterop-recurexpr.tar.gz
nimterop-recurexpr.zip
Recursive node support, enum expressions, or/and/notrecurexpr
-rw-r--r--nimterop/ast.nim29
-rw-r--r--nimterop/getters.nim15
-rw-r--r--nimterop/globals.nim26
-rw-r--r--nimterop/grammar.nim25
-rw-r--r--nimterop/lisp.nim8
-rw-r--r--tests/include/test.h6
-rw-r--r--tests/tnimterop_c.nim4
7 files changed, 75 insertions, 38 deletions
diff --git a/nimterop/ast.nim b/nimterop/ast.nim
index 6981deb..6498c93 100644
--- a/nimterop/ast.nim
+++ b/nimterop/ast.nim
@@ -4,18 +4,6 @@ import regex
import "."/[getters, globals, grammar, treesitter/runtime]
-const gAtoms = @[
- "field_identifier",
- "identifier",
- "shift_expression",
- "math_expression",
- "number_literal",
- "preproc_arg",
- "primitive_type",
- "sized_type_specifier",
- "type_identifier"
-].toSet()
-
proc saveNodeData(node: TSNode): bool =
let name = $node.tsNodeType()
if name in gAtoms:
@@ -25,10 +13,10 @@ proc saveNodeData(node: TSNode): bool =
if name == "primitive_type" and node.tsNodeParent.tsNodeType() == "sized_type_specifier":
return true
- if name == "number_literal" and $node.tsNodeParent.tsNodeType() in ["shift_expression", "math_expression"]:
+ if name == "number_literal" and $node.tsNodeParent.tsNodeType() in gExpressions:
return true
- if name in ["math_expression", "primitive_type", "sized_type_specifier"]:
+ if name in ["primitive_type", "sized_type_specifier"]:
val = val.getType()
let
@@ -52,6 +40,10 @@ proc saveNodeData(node: TSNode): bool =
ppname == "function_declarator":
gStateRT.data.add(("function_declarator", ""))
+ elif name in gExpressions:
+ if $node.tsNodeParent.tsNodeType() notin gExpressions:
+ gStateRT.data.add((name, node.getNodeVal()))
+
elif name in ["abstract_pointer_declarator", "enumerator", "field_declaration", "function_declarator"]:
gStateRT.data.add((name.replace("abstract_", ""), ""))
@@ -65,14 +57,19 @@ proc searchAstForNode(ast: ref Ast, node: TSNode): bool =
return
if ast.children.len != 0:
- if childNames.contains(ast.regex):
+ if childNames.contains(ast.regex) or
+ (childNames.len == 0 and ast.recursive):
if node.getTSNodeNamedChildCountSansComments() != 0:
var flag = true
for i in 0 .. node.tsNodeNamedChildCount()-1:
if $node.tsNodeNamedChild(i).tsNodeType() != "comment":
let
nodeChild = node.tsNodeNamedChild(i)
- astChild = ast.getAstChildByName($nodeChild.tsNodeType())
+ astChild =
+ if not ast.recursive:
+ ast.getAstChildByName($nodeChild.tsNodeType())
+ else:
+ ast
if not searchAstForNode(astChild, nodeChild):
flag = false
break
diff --git a/nimterop/getters.nim b/nimterop/getters.nim
index 59dbb15..1b39247 100644
--- a/nimterop/getters.nim
+++ b/nimterop/getters.nim
@@ -236,12 +236,16 @@ converter toKind*(kind: string): Kind =
else:
exactlyOne
-proc getNameKind*(name: string): tuple[name: string, kind: Kind] =
- result.name = name
+proc getNameKind*(name: string): tuple[name: string, kind: Kind, recursive: bool] =
+ if name[0] == '^':
+ result.recursive = true
+ result.name = name[1 .. ^1]
+ else:
+ result.name = name
result.kind = $name[^1]
if result.kind != exactlyOne:
- result.name = name[0 .. ^2]
+ result.name = result.name[0 .. ^2]
proc getTSNodeNamedChildCountSansComments*(node: TSNode): int =
if node.tsNodeNamedChildCount() != 0:
@@ -261,8 +265,9 @@ proc getTSNodeNamedChildNames*(node: TSNode): seq[string] =
proc getRegexForAstChildren*(ast: ref Ast): string =
result = "^"
for i in 0 .. ast.children.len-1:
- let kind: string = ast.children[i].kind
- let begin = if result[^1] == '|': "" else: "(?:"
+ let
+ kind: string = ast.children[i].kind
+ begin = if result[^1] == '|': "" else: "(?:"
case kind:
of "!":
result &= &"{begin}{ast.children[i].name}|"
diff --git a/nimterop/globals.nim b/nimterop/globals.nim
index ed69ff5..0c81e27 100644
--- a/nimterop/globals.nim
+++ b/nimterop/globals.nim
@@ -1,10 +1,33 @@
-import sets, tables
+import sequtils, sets, tables
import regex
when not declared(CIMPORT):
import "."/treesitter/runtime
+const
+ gAtoms* = @[
+ "field_identifier",
+ "identifier",
+ "number_literal",
+ "preproc_arg",
+ "primitive_type",
+ "sized_type_specifier",
+ "type_identifier"
+ ].toSet()
+
+ gExpressions* = @[
+ "parenthesized_expression",
+ "bitwise_expression",
+ "shift_expression",
+ "math_expression"
+ ].toSet()
+
+ gEnumVals* = @[
+ "identifier",
+ "number_literal"
+ ].concat(toSeq(gExpressions.items))
+
type
Kind* = enum
exactlyOne
@@ -16,6 +39,7 @@ type
Ast* = object
name*: string
kind*: Kind
+ recursive*: bool
children*: seq[ref Ast]
when not declared(CIMPORT):
tonim*: proc (ast: ref Ast, node: TSNode)
diff --git a/nimterop/grammar.nim b/nimterop/grammar.nim
index ae46404..ee42825 100644
--- a/nimterop/grammar.nim
+++ b/nimterop/grammar.nim
@@ -325,14 +325,15 @@ proc initGrammar() =
if gStateRT.consts.addNewIdentifer(fname):
if i+1 < gStateRT.data.len-fend and
- gStateRT.data[i+1].name in ["identifier", "shift_expression", "math_expression", "number_literal"]:
- if " " in gStateRT.data[i+1].val:
- gStateRT.data[i+1].val = "(" & gStateRT.data[i+1].val.replace(" ", "") & ")"
+ gStateRT.data[i+1].name in gEnumVals:
gStateRT.data[i+1].val = gStateRT.data[i+1].val.multiReplace([
- ("<<", " shl "), (">>", " shr ")
+ (" ", ""),
+ ("<<", " shl "), (">>", " shr "),
+ ("^", " xor "), ("&", " and "), ("|", " or "),
+ ("~", " not ")
])
- gStateRT.constStr &= &" {fname}* = {gStateRT.data[i+1].val}.{nname}\n"
+ gStateRT.constStr &= &" {fname}* = ({gStateRT.data[i+1].val}).{nname}\n"
try:
count = gStateRT.data[i+1].val.parseInt() + 1
except:
@@ -349,15 +350,12 @@ proc initGrammar() =
(type_identifier?)
(enumerator_list
(enumerator+
- (identifier+)
- (number_literal?)
- (shift_expression|math_expression?
- (number_literal+)
- )
+ (identifier?)
+ (^$1+)
)
)
)
- """,
+ """ % gEnumVals.join("|"),
proc (ast: ref Ast, node: TSNode) =
var
name = ""
@@ -439,8 +437,9 @@ proc initGrammar() =
proc initRegex(ast: ref Ast) =
if ast.children.len != 0:
- for child in ast.children:
- child.initRegex()
+ if not ast.recursive:
+ for child in ast.children:
+ child.initRegex()
var
reg: string
diff --git a/nimterop/lisp.nim b/nimterop/lisp.nim
index 3d3c34e..c21c3be 100644
--- a/nimterop/lisp.nim
+++ b/nimterop/lisp.nim
@@ -34,8 +34,10 @@ proc readFromTokens(): ref Ast =
quit(1)
if gTokens[idx+1] != "comment":
result = new(Ast)
- (result.name, result.kind) = gTokens[idx+1].getNameKind()
+ (result.name, result.kind, result.recursive) = gTokens[idx+1].getNameKind()
result.children = @[]
+ if result.recursive:
+ result.children.add(result)
idx += 2
while gTokens[idx] != ")":
var res = readFromTokens()
@@ -48,9 +50,9 @@ proc readFromTokens(): ref Ast =
idx += 1
proc printAst*(node: ref Ast, offset=""): string =
- result = offset & "(" & node.name & node.kind.toString()
+ result = offset & "(" & (if node.recursive: "^" else: "") & node.name & node.kind.toString()
- if node.children.len != 0:
+ if node.children.len != 0 and not node.recursive:
result &= "\n"
for child in node.children:
result &= printAst(child, offset & " ")
diff --git a/tests/include/test.h b/tests/include/test.h
index 8a8c579..64bdbb2 100644
--- a/tests/include/test.h
+++ b/tests/include/test.h
@@ -60,6 +60,12 @@ typedef enum ENUM4 {
enum12
} ENUM4;
+enum ENUM5 {
+ enum13 = (1 << 2),
+ enum14 = ((1 << 3) | 1),
+ enum15 = (1 << (1 & 1))
+};
+
typedef void * VOIDPTR;
typedef int * INTPTR;
diff --git a/tests/tnimterop_c.nim b/tests/tnimterop_c.nim
index 0f53556..86526c1 100644
--- a/tests/tnimterop_c.nim
+++ b/tests/tnimterop_c.nim
@@ -97,6 +97,10 @@ else:
check e3 == enum7
check e4 == enum11
+check enum13 == 4
+check enum14 == 9
+check enum15 == 2
+
cAddStdDir()
## failing tests