diff options
author | alexv-smirnov <alex@ydb.tech> | 2023-03-15 19:59:12 +0300 |
---|---|---|
committer | alexv-smirnov <alex@ydb.tech> | 2023-03-15 19:59:12 +0300 |
commit | 056bb284ccf8dd6793ec3a54ffa36c4fb2b9ad11 (patch) | |
tree | 4740980126f32e3af7937ba0ca5f83e59baa4ab0 /contrib/tools/cython/Cython/Parser/ConcreteSyntaxTree.pyx | |
parent | 269126dcced1cc8b53eb4398b4a33e5142f10290 (diff) | |
download | ydb-056bb284ccf8dd6793ec3a54ffa36c4fb2b9ad11.tar.gz |
add library/cpp/actors, ymake build to ydb oss export
Diffstat (limited to 'contrib/tools/cython/Cython/Parser/ConcreteSyntaxTree.pyx')
-rw-r--r-- | contrib/tools/cython/Cython/Parser/ConcreteSyntaxTree.pyx | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/contrib/tools/cython/Cython/Parser/ConcreteSyntaxTree.pyx b/contrib/tools/cython/Cython/Parser/ConcreteSyntaxTree.pyx new file mode 100644 index 0000000000..f9888c561c --- /dev/null +++ b/contrib/tools/cython/Cython/Parser/ConcreteSyntaxTree.pyx @@ -0,0 +1,88 @@ +cdef extern from "graminit.c": + ctypedef struct grammar: + pass + cdef grammar _PyParser_Grammar + cdef int Py_file_input + +cdef extern from "node.h": + ctypedef struct node + void PyNode_Free(node* n) + int NCH(node* n) + node* CHILD(node* n, int ix) + node* RCHILD(node* n, int ix) + short TYPE(node* n) + char* STR(node* n) + +cdef extern from "parsetok.h": + ctypedef struct perrdetail: + pass + cdef void PyParser_SetError(perrdetail *err) except * + cdef node * PyParser_ParseStringFlagsFilenameEx( + const char * s, + const char * filename, + grammar * g, + int start, + perrdetail * err_ret, + int * flags) + +import distutils.sysconfig +import os +import re + +def extract_names(path): + # All parse tree types are #defined in these files as ints. + type_names = {} + for line in open(path): + if line.startswith('#define'): + try: + _, name, value = line.strip().split() + type_names[int(value)] = name + except: + pass + return type_names + +cdef dict type_names = {} + +cdef print_tree(node* n, indent=""): + if not type_names: + type_names.update(extract_names( + os.path.join(distutils.sysconfig.get_python_inc(), 'token.h'))) + type_names.update(extract_names( + os.path.join(os.path.dirname(__file__), 'graminit.h'))) + + print indent, type_names.get(TYPE(n), 'unknown'), <object>STR(n) if NCH(n) == 0 else NCH(n) + indent += " " + for i in range(NCH(n)): + print_tree(CHILD(n, i), indent) + +def handle_includes(source, path): + # TODO: Use include directory. + def include_here(include_line): + included = os.path.join(os.path.dirname(path), include_line.group(1)[1:-1]) + if not os.path.exists(included): + return include_line.group(0) + ' # no such path: ' + included + return handle_includes(open(included).read(), path) + # TODO: Proper string tokenizing. + return re.sub(r'^include\s+([^\n]+[\'"])\s*(#.*)?$', include_here, source, flags=re.M) + +def p_module(path): + cdef perrdetail err + cdef int flags + cdef node* n + source = open(path).read() + if '\ninclude ' in source: + # TODO: Tokanizer needs to understand includes. + source = handle_includes(source, path) + path = "preparse(%s)" % path + n = PyParser_ParseStringFlagsFilenameEx( + source, + path, + &_PyParser_Grammar, + Py_file_input, + &err, + &flags) + if n: +# print_tree(n) + PyNode_Free(n) + else: + PyParser_SetError(&err) |