Я пишу компилятор на Python, и я написал рукописный лексер, потому что я не могу понять, как разобрать отступ в PLY.Кроме того, мой лексер использует некоторые операторы yield
, например, так:
def scan():
...
for i in tokens:
if i[0]: yield Token(self.line, i[0] if i[0] in keywords else "ident", i[0])
elif i[1]:
if "e" in i[1]:
base, exp = i[1].split("e")
val = float(base) * 10 ** int(exp)
else: val = float(i[1])
yield Token(self.line, "float", val)
... other cases ...
Однако я понял, что для синтаксического анализатора PLY требуется метод token
, поэтому я создал такой, который выглядит следующим образом:
def token(self):
return next(self.scan())
Фактическое сканирование с использованием scan()
занимает в среднем 124 мс, согласно моим тестам, но когда я использую анализатор PLY, анализ не начинается через несколько минут.Похоже, у моего метода token()
есть проблема.
Также я попытался переименовать метод scan()
, чтобы it мог стать интерфейсом.Python возвращает что-то вроде
AttributeError: 'generator' object has no attribute 'type'
Так что, похоже, PLY нужен метод, который будет возвращать один токен за раз.
Есть ли способ переписать метод token()
, чтобыон вернет следующую итерацию scan()
и не будет такой медленной?