-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsrcml.py
More file actions
103 lines (79 loc) · 2.69 KB
/
srcml.py
File metadata and controls
103 lines (79 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""
Modifying AST with `srcml`. Parses very OK! Can we modify??
"""
from lxml import etree
from lxml.builder import ElementMaker
import subprocess
from pathlib import Path
import re
import os
import copy
import logging
logger = logging.getLogger(__name__)
srcml_install = Path(__file__).parent / 'srcml'
srcml_exe = srcml_install / 'bin/srcml'
assert srcml_exe.exists()
srcml_env = copy.deepcopy(os.environ)
if "LD_LIBRARY_PATH" in srcml_env:
srcml_env["LD_LIBRARY_PATH"] = str(srcml_install / 'lib') + ':' + srcml_env["LD_LIBRARY_PATH"]
else:
srcml_env["LD_LIBRARY_PATH"] = str(srcml_install / 'lib')
namespaces = {'src': 'http://www.srcML.org/srcML/src'}
E = ElementMaker(namespace=namespaces["src"], nsmap=namespaces)
# Print XML from root
def prettyprint(node, return_string=False):
s = etree.tostring(node, encoding="unicode", pretty_print=True)
if return_string:
return s
else:
print(s)
# prettyprint(xmldata)
def tagname(node):
return etree.QName(node).localname
def start_pos(node):
# prettyprint(node)
return node.get('{http://www.srcML.org/srcML/position}start')
def get_space(node, front_back):
if front_back == 'front':
regex = rf'^<{etree.QName(node).localname}[^>]+>(\s+)'
elif front_back == 'back':
regex = r'(\s+)$'
else:
raise
m = re.search(regex, etree.tostring(node, encoding='unicode'))
if m:
return m.group(1)
else:
return ''
class SrcMLInfo:
def __init__(self, c_code=None):
self.c_code = c_code
self.xml = None
self.xml_root = None
self.load_xml()
def load_xml(self):
proc = subprocess.Popen([str(srcml_exe), '-lC'],
stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
self.xml = proc.communicate(input=self.c_code.encode('utf-8'))[0]
self.xml_root = etree.fromstring(self.xml)
return self.xml
def load_c_code(self):
proc = subprocess.Popen([str(srcml_exe)], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
self.c_code = proc.communicate(input=self.xml)[0].decode('utf-8')
logger.debug('new C code:\n%s', self.c_code)
return self.c_code
def revert_changes(self):
self.xml_root = etree.fromstring(self.xml)
def apply_changes(self):
self.xml = etree.tostring(self.xml_root)
def xp(self, *args):
if len(args) == 1:
node = self.xml_root
query = args[0]
else:
node = args[0]
query = args[1]
return node.xpath(query, namespaces=namespaces)
@classmethod
def tag(cls, node):
return etree.QName(node).localname