-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathparser.py
72 lines (60 loc) · 1.95 KB
/
parser.py
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
import ast
import os
import sys
from lib2to3 import pygram
from lib2to3 import pytree
from lib2to3.pgen2 import driver
from lib2to3.pgen2 import parse
from lib2to3.pgen2 import token
_GRAMMAR_FOR_PY3 = pygram.python_grammar_no_print_statement.copy()
del _GRAMMAR_FOR_PY3.keywords['exec']
_GRAMMAR_FOR_PY2 = pygram.python_grammar.copy()
del _GRAMMAR_FOR_PY2.keywords['nonlocal']
def parse_string(code):
"""Parse the given code to a lib2to3 pytree.
Arguments:
code: a string with the code to parse.
Raises:
SyntaxError if the code is invalid syntax.
parse.ParseError if some other parsing failure.
Returns:
The root node of the parsed tree.
"""
try:
parser_driver = driver.Driver(_GRAMMAR_FOR_PY3, convert=pytree.convert)
tree = parser_driver.parse_string(code, debug=False)
except parse.ParseError:
try:
parser_driver = driver.Driver(_GRAMMAR_FOR_PY2,
convert=pytree.convert)
tree = parser_driver.parse_string(code, debug=False)
except parse.ParseError:
try:
ast.parse(code)
except SyntaxError as e:
raise e
else:
raise
return tree
def parse_file(filename):
code = open(filename).read()
if not code.endswith("\n"):
code += "\n"
return parse_string(code)
def parse_dir(dir):
for dirpath, _, filenames in os.walk(dir):
for filename in filenames:
if filename.endswith(".py"):
path = os.path.join(dirpath, filename)
yield (filename, path, parse_file(path))
def parse_any(arg):
if os.path.isfile(arg):
yield (arg, arg, parse_file(arg))
elif os.path.isdir(arg):
yield from parse_dir(arg)
else:
print("Ignoring", arg)
if __name__ == "__main__":
for arg in sys.argv[1:]:
for filename, tree in parse_any(arg):
print(filename, tree is not None)