我一直在为自己要尝试实现的自定义编程语言编写解释器,现在看来它可以很好地与数字,字符串和基本打印功能配合使用,我正着手开发“内置的ins的一部分。现在,为了简化操作并考虑将来的扩展性,我创建了一个基础Type
类,类似于Python自己的type
。
在这里,我添加了一些用于初始化的常规方法,引发了解析错误以及一些内部方法,例如__add__
。我的Number
内置类型类需要继承算术,比较和一元相关的方法。但是我的String
需要继承先验的一种变体,其中一元方法,大多数比较方法和大多数算术方法都会产生错误。在下面的示例中,我有一个带有“支持二进制操作”的子类的基类:
class Type:
def __init__(self, token, *, error_msg='{}', expected_type=None):
self.token = token
self.value = token.value
if '{}' not in error_msg:
raise TypeError()
if expected_type:
if not isinstance(self.value, expected_type):
raise TypeError(error_msg.format(self.value.__class__.__name__))
def __repr__(self):
return 'Number({})'.format(repr(self.token))
def __str__(self):
return str(self.value)
def unsupported_binary_op(self, op, obj1, obj2):
raise TypeError('Invalid operation: {} {} {}'
.format(obj1.__class__.__name__,
op,
obj2.__class__.__name__))
def supports_binary_operations(self):
def __add__(self, other):
if isinstance(other, self.__class__):
num1 = self.value
num2 = other.value
return self.__class__(Token(self.token.type, num1 + num2))
else:
self.unsupported_binary_op('+', self, other)
# more of these special methods here....
names = {
'__add__': __add__,
# more method mappings here...
}
for name, func in names.items():
setattr(self, name, func)
# And the subclass 'Number'...
class Number(Type):
def __init__(self, token):
msg = 'expected python <decimal.Decimal> type, got <{}>'
super(Number, self).__init__(token,
error_msg=msg,
expected_type=decimal.Decimal)
self.supports_binary_operations()
如果您注意到了,我将decimal.Decimal
用于我的数字,以避免浮点错误,并且为了简单起见,我使用了“通用”数字类型。
(以及有助于重新创建的令牌类):
class Token:
def __init__(self, token_type, value):
self.type = token_type
self.value = value
要创建Number
对象,请执行以下操作:
import decimal
n = Number(Token('NUM',decimal.Decimal(1)))
然后,如果我这样做:
>>> n + n
TypeError: unsupported operand type(s) for +: 'Number' and 'Number'
>>> n.__add__(n)
TypeError: __add__() missing 1 required positional argument: 'other'
>>> n.__add__ # not calling it
<function Type.supports_binary_operations.<locals>.__add__ at 0x...>
当我将方法直接放入__add__
类的主体中时,我不知道为什么Number
函数在这里不起作用,它的工作原理与我移动方法之前一样进入基类。