【发布时间】:2021-02-02 20:15:16
【问题描述】:
在SLY中有一个写计算器的例子(转载自calc.pyhere):
from sly import Lexer
class CalcLexer(Lexer):
tokens = { NAME, NUMBER }
ignore = ' \t'
literals = { '=', '+', '-', '*', '/', '(', ')' }
# Tokens
NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
@_(r'\d+')
def NUMBER(self, t):
t.value = int(t.value)
return t
@_(r'\n+')
def newline(self, t):
self.lineno += t.value.count('\n')
def error(self, t):
print("Illegal character '%s'" % t.value[0])
self.index += 1
看起来它有问题,因为 NAME 和 NUMBER 在定义之前就被使用了。但实际上,没有NameError,这段代码执行得很好。这是如何运作的?什么时候可以在名称被定义之前引用它?
【问题讨论】:
-
Lexer使用处理缺失变量的自定义元类。 -
这里有一些 deep 魔法——
Lexer有一个元类,它重新定义了它的子类的定义方式。具体来说,子类不再使用标准的 Python 字典作为其命名空间,而是使用字典子类在查找时自动定义名称(作为与名称相等的字符串)。