2012-08-26 30 views
-3

我想在python中实现一个简单的表达式求值器,但是我陷入了解析器method.Below是我的代码片段。Python表达式求值器和解释器模式

class Number: 
    def __init__(self,value): 
     self.value=value 
    def execute(self): 
     return self.value 

class Plus: 
    def __init__(self,left,right): 
     self.left=left 
     self.right=right 
    def execute(self): 
     return self.left+self.right 

class Minus: 
    def __init__(self,left,right): 
     self.left=left 
     self.right=right 
    def execute(self): 
     return self.left-self.right 

class Multiply: 
    def __init__(self,left,right): 
     self.left=left 
     self.right=right 
    def execute(self): 
     return self.left*self.right 
import re 
def parser(input): 
    stack=[] 
    token_pat = re.compile("\s*(?:(\d+)|(.))") 
    for number, operator in token_pat.findall(input): 


     if number: 
      stack.append(Number(int(number))) 

     else: 
      first,second=stack.pop(),stack.pop() 

      if operator=="+": 
       stack.append(Plus(first,second)) 
      elif operator=="-": 
       stack.append(Minus(first,second)) 
      elif operator=="*": 
       stack.append(Multiply(first,second)) 
      else: 
       raise SyntaxError("unknown operator") 
    print stack[0].execute() 


if __name__=="__main__": 
    parser('1 2 +') 

当我运行上面的代码,我得到以下error.Can任何人都可以检查我的代码。

Traceback (most recent call last): 
    File "Interpreter.py", line 52, in <module> 
    parser('1 2 +') 
    File "Interpreter.py", line 48, in parser 
    print stack[0].execute() 
    File "Interpreter.py", line 12, in execute 
    return self.left+self.right 
TypeError: unsupported operand type(s) for +: 'instance' and 'in 
+1

这里的问题是什么?错误消息清楚地表明你的错误是什么。要么?你需要哪些帮助? –

+1

...你的问题是...? –

+2

你错过了递归。只要使用'self.left.execute()'和'self.right.execute()'这样的东西,你应该没问题。 – filmor

回答

5

错误消息是令人困惑,因为您正在使用classic classes。随着新式的类(即从object继承),你会得到一个更加合理:

TypeError: unsupported operand type(s) for +: 'Number' and 'Number' 

要么使用int s,而不是数量的对象,或者实现通过实施__add__ and friends添加逻辑,或添加Plus.execute逻辑判断。

另请注意,您正在重新实现Python的内置插件。此外,使用execute方法几乎是一种反模式。一个更短的实现将是

import functools,operator,re 

def parser(inp): 
    stack=[] 
    token_pat = re.compile("\s*(?:(\d+)|(.))") 
    for number, op in token_pat.findall(inp): 
     if number: 
      stack.append(functools.partial(lambda i:i, int(number))) 
     else: 
      first,second=stack.pop(),stack.pop() 
      try: 
       op = { 
        '+': operator.add, 
        '-': operator.sub, 
        '*': operator.mul 
       }[op] 
      except KeyError: 
       raise SyntaxError("unknown operator") 

      stack.append(functools.partial(lambda op,first,second: 
         op(first(), second()), op, first, second)) 
    print(stack[0]()) 

if __name__=="__main__": 
    parser('1 2 + 3 *') 
+0

非常感谢您为我查看我的代码+1。我正按照您的指示更改我的代码。 –

1

既然你有没有兴趣做基本的调试自己:

sucmac: $ python out.py 
> /Users/xxxx/out.py(13)execute() 
-> return self.left+self.right 
(Pdb) self.left 
<__main__.Number instance at 0x10043f3f8> 
(Pdb) self.right 
<__main__.Number instance at 0x10042f248> 
(Pdb) right 
*** NameError: name 'right' is not defined 
(Pdb) self.right.__dict__ 
{'value': 1} 

你显然希望

return self.right.value + self.left.value 
+0

你显然是错的,他想对表达式进行递归评估。 – Begemoth

+0

@esael ..:感谢您的发现+1 –

+0

在您的机器上,'python'似乎被别名为除了通用cpython之外的东西。你能包括你如何设置? – phihag