-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparsefuture.py
More file actions
112 lines (96 loc) · 3.66 KB
/
Copy pathparsefuture.py
File metadata and controls
112 lines (96 loc) · 3.66 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
104
105
106
107
108
109
110
111
112
import __future__ as future
class FutureFlags(object):
def __init__(self, version):
compiler_flags = 0
self.compiler_features = {}
self.mandatory_flags = 0
for fname in future.all_feature_names:
feature = getattr(future, fname)
if version >= feature.getOptionalRelease():
flag = feature.compiler_flag
compiler_flags |= flag
self.compiler_features[fname] = flag
if version >= feature.getMandatoryRelease():
self.mandatory_flags |= feature.compiler_flag
self.allowed_flags = compiler_flags
def get_flag_names(self, space, flags):
flag_names = []
for name, value in self.compiler_features.items():
if flags & value:
flag_names.append(name)
return flag_names
def get_compiler_feature(self, name):
return self.compiler_features.get(name, 0)
futureFlags_2_4 = FutureFlags((2, 4, 4, 'final', 0))
futureFlags_2_5 = FutureFlags((2, 5, 0, 'final', 0))
futureFlags_2_7 = FutureFlags((2, 7, 0, 'final', 0))
class TokenIterator:
def __init__(self, tokens):
self.tokens = tokens
self.index = 0
self.next()
def next(self):
index = self.index
self.index = index + 1
self.tok = self.tokens[index]
def skip(self, n):
if self.tok.token_type == n:
self.next()
return True
else:
return False
def skip_name(self, name):
from syntaxerrors import pygram
if self.tok.token_type == pygram.tokens.NAME and self.tok.value == name:
self.next()
return True
else:
return False
def next_feature_name(self):
from syntaxerrors import pygram
if self.tok.token_type == pygram.tokens.NAME:
name = self.tok.value
self.next()
if self.skip_name("as"):
self.skip(pygram.tokens.NAME)
return name
else:
return ''
def skip_newlines(self):
from syntaxerrors import pygram
while self.skip(pygram.tokens.NEWLINE):
pass
def add_future_flags(future_flags, tokens):
from syntaxerrors import pygram
it = TokenIterator(tokens)
result = 0
last_position = (0, 0)
#
# The only things that can precede a future statement are another
# future statement and a doc string (only one). This is a very
# permissive parsing of the given list of tokens; it relies on
# the real parsing done afterwards to give errors.
it.skip_newlines()
docstring_possible = True
while True:
it.skip_name("r") or it.skip_name("u") or it.skip_name("ru")
if docstring_possible and it.skip(pygram.tokens.STRING):
it.skip_newlines()
docstring_possible = False
if not (it.skip_name("from") and
it.skip_name("__future__") and
it.skip_name("import")):
break
it.skip(pygram.tokens.LPAR) # optionally
# return in 'last_position' any line-column pair that points
# somewhere inside the last __future__ import statement
# (at the start would be fine too, but it's easier to grab a
# random position inside)
last_position = (it.tok.lineno, it.tok.column)
result |= future_flags.get_compiler_feature(it.next_feature_name())
while it.skip(pygram.tokens.COMMA):
result |= future_flags.get_compiler_feature(it.next_feature_name())
it.skip(pygram.tokens.RPAR) # optionally
it.skip(pygram.tokens.SEMI) # optionally
it.skip_newlines()
return result, last_position