用于计算数学表达式的递归下降解析器抛出错误,我不知道如何修复它

问题描述

我是新来的,有一个一般问题。我正在尝试创建一个递归下降解析器来评估数学表达式,而我迄今为止制作的解析器也非常适用于整数和浮点数。但现在我试图通过对函数的评估来扩展它,比如“log”、“ln”或“cbrt”。 我的解析器由八个函数组成,不包括用于评估的函数。我还制作了一个用于扫描输入字符串的函数。如果字符串是 '5+....',这个函数将返回一个表达式列表,语法为 [5.0,'+',....]。此功能运行良好,这不是我遇到的问题。我的问题是,解析器引发了“列表索引超出范围”错误,我不明白为什么。 当我插入一个没有任何要评估的函数的表达式时,解析器会提供正确的抽象语法树,我的评估函数会计算出正确的值。我现在找到了一种评估形状为 'function( expr )' 的表达式的方法(解析器不会抛出错误),但是当尝试类似 'function1( expr1 ) + function2( expr2 )' 或 'value + function( expr )',总是抛出'列表索引超出范围错误'。

def expect_token( a,i ):
    if a[i] is None:
        raise SyntaxError( 'Unexpected end of input' )
    else:
        return a[i]

def atom( a,i,functions,dispatch ):
    t = expect_token( a,i )
    if isinstance( t,float ):
        return i+1,a[i]
    elif t == '(':
        i,x = expression( a,i+1,dispatch )
        if expect_token( a,i ) != ')':
            raise SyntaxError( '")" was expected,but it came "{}"'.format( a[i] ) )
        return i+1,x
    elif t in dispatch.keys():
        i,dispatch )
        return i+1,a[i]
    else:
        raise SyntaxError( 'Unexpected symbol: "{}"'.format( t ) )

def power( a,dispatch ):
    i,x = atom( a,dispatch )
    if a[i] == '^':
        i,y = negation( a,dispatch )
        return i,['^',x,y]
    else:
        return i,x

def negation( a,dispatch ):
    if a[i] == '-':
        i,x = power( a,['~',x]
    else:
        return power( a,dispatch )

def multiplication( a,x = negation( a,dispatch )
    op = a[i]
    while op == '*' or op == '/':
        i,dispatch )
        x = [op,y]
        op = a[i]
    return i,x

def addition( a,x = multiplication( a,dispatch )
    op = a[i]
    while op == '+' or op == '-':
        i,y = multiplication( a,x

def expression( a,dispatch ):
    if a[i] in functions:
        i_,y = expression( a,dispatch )
        x = [a[i],y]
        return i_,x
    return addition( a,dispatch )

def ast( a,t = expression( a,dispatch )
    if a[i] is None:
        return t
    else:
        raise SyntaxError( 'End of input expected,but there came "{}"'.format( a[i] ) )

dispatch_ = {'+': lambda x,y: x+y,'-': lambda x,y: x-y,'*': lambda x,y: x*y,'/': lambda x,y: x/y,'^': lambda x,y: x**y,'~': lambda x: -x,'log': lambda x: log( x,10 ),'ln': lambda x: log( x ),'sqrt': lambda x: sqrt( x ),'cbrt': lambda x: pow( x,1/3 )
            }

functions_ = [ 'log','ln','sqrt','cbrt' ]
´´´
I don't know if it important,but I import log and sqrt from the 'math' libary.
I debugged the program very often and found that the error is caused by the 'atom function',but I do not know how to fix it.

-> cbrt( 8 )+ log( 10 )

> Traceback (most recent call last):   File
> "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line
> 150,in <module>
>     run()   File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line
> 140,in run
>     t = ast( a,functions_,dispatch_ )   File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line
> 100,in ast
>     i,dispatch )   File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line
> 94,in expression
>     i_,line
> 97,in expression
>     return addition( a,line
> 87,in addition
>     i,line
> 75,in multiplication
>     i,line
> 72,in negation
>     return power( a,line
> 61,in power
>     if a[i] == '^': IndexError: list index out of range

''' 尝试计算 '5+sqrt( 4 )' 时,会抛出相同的错误。

我的问题是,程序中的错误究竟在哪里,我该如何修复它。 如果您愿意,我还将向您展示我的扫描和评估程序。 感谢您未来的帮助。

编辑:

这是我的扫描程序:

def is_sign( sign ):
    if sign in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ':
        return True
    return False

def scan( s ):
    a = []
    i = 0
    n = len( s )
    while i < n:
        if s[i] in '+-*/^()':
            a.append( s[i] )
            i += 1
        elif s[i].isdigit():
            j = i
            while i < n and ( s[i].isdigit() or s[i] == '.' ):
                i += 1
            a.append( float( s[j:i] ) )
        elif s[i].isspace():
            i += 1
        elif is_sign( s[i] ):
            j = i
            while i < n and is_sign( s[i] ):
                i += 1
            a.append( s[j:i] )
        else:
            raise SyntaxError( 'Unexpected character: "{}"'.format( s[i] ) )
    a.append( None )
    return a

# And for evaluation I use this function:

def evaluate( t ):
    if isinstance( t,float ):
        return t
    else:
        return dispatch_[t[0]]( *map( evaluate,t[1:] ) )
´´´

Examples:

expr = '3+5*( 5+3-6 )-9'
-> tree = ['-',[ '+',3.0,['*',5.0,['-',['+',3.0],6.0]]],9.0]
-> sol = 4.0

expr = 'cbrt( 4*3-4 )'
-> tree = ['cbrt',4.0,4.0]]
-> sol = 2.0

expr = '3*log( 4-9 )'
-> error:
 Traceback (most recent call last):
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line 150,in <module>
    run()
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line 140,in run
    t = ast( a,dispatch_ )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line 100,in ast
    i,dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line 97,in expression
    return addition( a,line 84,in addition
    i,line 78,in multiplication
    i,line 72,in negation
    return power( a,line 61,in power
    if a[i] == '^':
IndexError: list index out of range

expr = 'sqrt( 4 ) - ln( 2.7 )'
-> error:
Traceback (most recent call last):
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py",line 94,in expression
    i_,line 87,line 75,in power
    if a[i] == '^':
IndexError: list index out of range

´´´
I hope this additional information will help you to support me.

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)