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

Math 用于计算数学表达式的递归下降解析器抛出错误,我不知道如何修复它,math,python-3.8,recursive-descent,Math,Python 3.8,Recursive Descent,我是新来的,有一个一般性的问题。我正在尝试创建一个递归下降解析器,用于计算数学表达式,而到目前为止,我制作的解析器也非常适用于整数和浮点数。但现在我尝试用函数的求值来扩展它,比如“log”、“ln”或“cbrt”。 我的解析器由八个函数组成,不包括用于求值的函数。我还设计了一个用于扫描输入字符串的函数。如果字符串为“5+…”,此函数将返回语法为[5.0,“+”,…]的表达式列表。这个函数工作得很好,这不是我的问题。我的问题是,解析器引发了一个“列表索引超出范围”错误,我不明白为什么。 当我插入一

我是新来的,有一个一般性的问题。我正在尝试创建一个递归下降解析器,用于计算数学表达式,而到目前为止,我制作的解析器也非常适用于整数和浮点数。但现在我尝试用函数的求值来扩展它,比如“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, functions, 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, x = expression( a, i+1, functions, dispatch )
        return i+1, a[i]
    else:
        raise SyntaxError( 'Unexpected symbol: "{}"'.format( t ) )

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

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

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

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

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

def ast( a, functions, dispatch ):
    i, t = expression( a, 0, functions, 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)+对数(10)

>回溯(最近一次调用上次):文件
>“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>150,英寸
>运行()文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>140,在逃
>t=ast(a,函数,调度)文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>100,在ast中
>i,t=表达式(a,0,函数,分派)文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>94,在表达上
>i,y=表达式(a,i+1,函数,分派)文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>97,在表达上
>返回添加(a、i、函数、分派)文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>87,另外,
>i,y=乘法(a,i+1,函数,分派)文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>75,乘法运算
>i,x=否定(a,i,函数,分派)文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>72,在否定中
>返回电源(a、i、函数、调度)文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第行
>61岁,掌权
>如果[i]='^':索引器:列表索引超出范围
' 尝试计算“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, ['-', ['+', 5.0, 3.0], 6.0]]], 9.0]
-> sol = 4.0

expr = 'cbrt( 4*3-4 )'
-> tree = ['cbrt', ['-', ['*', 4.0, 3.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, functions_, dispatch_ )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 100, in ast
    i, t = expression( a, 0, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 97, in expression
    return addition( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 84, in addition
    i, x = multiplication( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 78, in multiplication
    i, y = negation( a, i+1, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 72, in negation
    return power( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", 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 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, t = expression( a, 0, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 94, in expression
    i_, y = expression( a, i+1, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 97, in expression
    return addition( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 87, in addition
    i, y = multiplication( a, i+1, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 75, in multiplication
    i, x = negation( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 72, in negation
    return power( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 61, in power
    if a[i] == '^':
IndexError: list index out of range

´´´
I hope this additional information will help you to support me.
def是符号(sign):
如果登录“abcdefghijklmnopqrstuvwxyzabefghijklmnopqrstuvxyz”:
返回真值
返回错误
def扫描:
a=[]
i=0
n=长(s)
而itree=['-'、['+'、3.0、['*'、5.0、['-'、['+'、5.0、3.0]、6.0]]、9.0]
->溶胶=4.0
expr='cbrt(4*3-4)'
->tree=['cbrt',['-',['*',4.0,3.0],4.0]]
->溶胶=2.0
expr='3*log(4-9)'
->错误:
回溯(最近一次呼叫最后一次):
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第150行,在
运行()
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第140行,正在运行
t=ast(a、功能、调度)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第100行,在ast中
i、 t=表达式(a,0,函数,分派)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第97行,在表达式中
返回添加(a、i、功能、分派)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第84行,另外
i、 x=乘法(a、i、函数、分派)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第78行,乘法
i、 y=否定(a,i+1,函数,分派)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第72行,反义
返回功率(a、i、功能、调度)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第61行,在power中
如果a[i]='^':
索引器:列表索引超出范围
expr='sqrt(4)-ln(2.7)'
->错误:
回溯(最近一次呼叫最后一次):
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第150行,在
运行()
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第140行,正在运行
t=ast(a、功能、调度)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第100行,在ast中
i、 t=表达式(a,0,函数,分派)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第94行,在表达式中
i_,y=表达式(a,i+1,函数,分派)
文件“F:\Privat\Programms\Python\Projects\Calculator\calc\u tools.py”,第97行,在表达式中
返回加法(a、i、函数、disp
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, ['-', ['+', 5.0, 3.0], 6.0]]], 9.0]
-> sol = 4.0

expr = 'cbrt( 4*3-4 )'
-> tree = ['cbrt', ['-', ['*', 4.0, 3.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, functions_, dispatch_ )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 100, in ast
    i, t = expression( a, 0, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 97, in expression
    return addition( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 84, in addition
    i, x = multiplication( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 78, in multiplication
    i, y = negation( a, i+1, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 72, in negation
    return power( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", 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 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, t = expression( a, 0, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 94, in expression
    i_, y = expression( a, i+1, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 97, in expression
    return addition( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 87, in addition
    i, y = multiplication( a, i+1, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 75, in multiplication
    i, x = negation( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 72, in negation
    return power( a, i, functions, dispatch )
  File "F:\Privat\Programms\Python\Projects\Calculator\calc_tools.py", line 61, in power
    if a[i] == '^':
IndexError: list index out of range

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