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
|
from fontTools.feaLib.lexer import IncludingLexer, Lexer
from fontTools.feaLib.error import FeatureLibError
import re, io
VARIABLE = "VARIABLE"
class feax_Lexer(Lexer):
def __init__(self, *a):
Lexer.__init__(self, *a)
self.tokens_ = None
self.stack_ = []
self.empty_ = False
def next_(self, recurse=False):
while (not self.empty_):
if self.tokens_ is not None:
res = self.tokens_.pop(0)
if not len(self.tokens_):
self.popstack()
if res[0] != VARIABLE:
return (res[0], res[1], self.location_())
return self.parse_variable(res[1])
try:
res = Lexer.next_(self)
except IndexError as e:
self.popstack()
continue
except StopIteration as e:
self.popstack()
continue
except FeatureLibError as e:
if u"Unexpected character" not in str(e):
raise e
# only executes if exception occurred
location = self.location_()
text = self.text_
start = self.pos_
cur_char = text[start]
if cur_char == '$':
self.pos_ += 1
self.scan_over_(Lexer.CHAR_NAME_CONTINUATION_)
varname = text[start+1:self.pos_]
if len(varname) < 1 or len(varname) > 63:
raise FeatureLibError("Bad variable name length for: %s" % varname, location)
res = (VARIABLE, varname, location)
else:
raise FeatureLibError("Unexpected character: %r" % cur_char, location)
return res
raise StopIteration
def __repr__(self):
if self.tokens_ is not None:
return str(self.tokens_)
else:
return str((self.text_[self.pos_:self.pos_+20], self.pos_, self.text_length_))
def popstack(self):
if len(self.stack_) == 0:
self.empty_ = True
return
t = self.stack_.pop()
if t[0] == 'tokens':
self.tokens_ = t[1]
else:
self.text_, self.pos_, self.text_length_ = t[1]
self.tokens_ = None
def pushstack(self, v):
if self.tokens_ is None:
self.stack_.append(('text', (self.text_, self.pos_, self.text_length_)))
else:
self.stack_.append(('tokens', self.tokens_))
self.stack_.append(v)
self.popstack()
def pushback(self, token_type, token):
if self.tokens_ is not None:
self.tokens_.append((token_type, token))
else:
self.pushstack(('tokens', [(token_type, token)]))
def parse_variable(self, vname):
t = str(self.scope.get(vname, ''))
if t != '':
self.pushstack(['text', (t + " ", 0, len(t)+1)])
return self.next_()
class feax_IncludingLexer(IncludingLexer):
@staticmethod
def make_lexer_(file_or_path):
if hasattr(file_or_path, "read"):
fileobj, closing = file_or_path, False
else:
filename, closing = file_or_path, True
fileobj = io.open(filename, mode="r", encoding="utf-8")
data = fileobj.read()
filename = getattr(fileobj, "name", None)
if closing:
fileobj.close()
return feax_Lexer(data, filename)
|