Math 用于计算数学表达式的递归下降解析器抛出错误,我不知道如何修复它
我是新来的,有一个一般性的问题。我正在尝试创建一个递归下降解析器,用于计算数学表达式,而到目前为止,我制作的解析器也非常适用于整数和浮点数。但现在我尝试用函数的求值来扩展它,比如“log”、“ln”或“cbrt”。 我的解析器由八个函数组成,不包括用于求值的函数。我还设计了一个用于扫描输入字符串的函数。如果字符串为“5+…”,此函数将返回语法为[5.0,“+”,…]的表达式列表。这个函数工作得很好,这不是我的问题。我的问题是,解析器引发了一个“列表索引超出范围”错误,我不明白为什么。 当我插入一个没有任何要计算的函数的表达式时,解析器会传递正确的抽象语法树,我的计算函数会计算正确的值。我现在找到了一种使用“function(expr)”形状计算表达式的方法(解析器不会抛出错误),但是当尝试类似“function1(expr1)+function2(expr2)”或“value+function(expr)”之类的操作时,总会抛出“列表索引超出范围错误”Math 用于计算数学表达式的递归下降解析器抛出错误,我不知道如何修复它,math,python-3.8,recursive-descent,Math,Python 3.8,Recursive Descent,我是新来的,有一个一般性的问题。我正在尝试创建一个递归下降解析器,用于计算数学表达式,而到目前为止,我制作的解析器也非常适用于整数和浮点数。但现在我尝试用函数的求值来扩展它,比如“log”、“ln”或“cbrt”。 我的解析器由八个函数组成,不包括用于求值的函数。我还设计了一个用于扫描输入字符串的函数。如果字符串为“5+…”,此函数将返回语法为[5.0,“+”,…]的表达式列表。这个函数工作得很好,这不是我的问题。我的问题是,解析器引发了一个“列表索引超出范围”错误,我不明白为什么。 当我插入一
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.