问题描述
我是新来的,有一个一般问题。我正在尝试创建一个递归下降解析器来评估数学表达式,而我迄今为止制作的解析器也非常适用于整数和浮点数。但现在我试图通过对函数的评估来扩展它,比如“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 (将#修改为@)