From da875fcb62c801b8d19b3d4d984ad963574fb356 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 2 Mar 2023 21:01:10 +0100 Subject: Adding upstream version 1.6.0. Signed-off-by: Daniel Baumann --- lib/silfont/feax_lexer.py | 105 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 lib/silfont/feax_lexer.py (limited to 'lib/silfont/feax_lexer.py') diff --git a/lib/silfont/feax_lexer.py b/lib/silfont/feax_lexer.py new file mode 100644 index 0000000..58ea72d --- /dev/null +++ b/lib/silfont/feax_lexer.py @@ -0,0 +1,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", 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) + -- cgit v1.2.3