我目前正在使用PLY (Python Lex-Yacc)为我的不和谐机器人编写一个计算器。 问题在于代码无法编译。
它引发语法错误:
Traceback (most recent call last): File "main.py", line 6, in <module>
import calculator
File "/home/runner/calculator.py", line 72, in <module> lexer=lex()
File "/home/runner/.local/share/virtualenvs/python3/lib/python3.7/site-packages/ply/lex.py"
, line 909, in lex raise SyntaxError("Can't build lexer")
SyntaxError: Can't build lexer
这是我的代码:
from ply.lex import lex
from ply.yacc import yacc
from decimal import *
setcontext(Context(prec=2000,rounding=ROUND_HALF_DOWN))
factorial=[1]
fac=Decimal('1')
for i in range(2,1000):
fac*=Decimal(i)
factorial.append(fac)
def sin(s):
sin=Decimal(s)
s=Decimal(s)
for i in range(5,1000,4):
sin+=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
for i in range(3,1000,4):
sin-=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
return sin
def cos(s):
cos=Decimal('1')
s=Decimal(s)
for i in range(4,1000,4):
cos+=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
for i in range(2,1000,4):
cos-=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
return cos
def tan(s):
return sin(s)/cos(s)
tokens=['NUM','PLUS','MINUS','TIMES','DIVIDE','LPAREN','RPAREN','SIN','COS','TAN']
#tokens=['NUM','PLUS','MINUS','TIMES','DIVIDE','LPAREN','RPAREN', 'SIN']
t_ignore=' \t\n'
t_PLUS=r'\+'
t_MINUS=r'\-'
t_TIMES=r'\*'
t_DIVIDE=r'/'
t_LPAREN=r'\('
t_RPAREN=r'\)'
t_SIN=r'sin'
t_COS=r'cos'
t_TAN=r'tan'
def t_NUM(t):
r'\d+(\.\d+)?'
t.value=Decimal(t.value)
return t
def t_SIN(t):
r'sin\((\d+(\.\d+)?)\)'
t.value=sin(Decimal(t))
return t
def t_COS(t):
r'cos\((\d+(\.\d+)?)\)'
t.value=cos(Decimal(t))
return t
def t_TAN(t):
r'tan\((\d+(\.\d+)?)\)'
t.value=tan(Decimal(t))
return t
def t_error(t):
print('Bad Character: {!r}'.format(t.value[0]))
t.lexer.skip(1)
lexer=lex()
def p_expr(p):
'''
expr : expr PLUS term
| expr MINUS term
'''
if p[2]=='+':
p[0]=p[1]+p[3]
elif p[2]=='-':
p[0]=p[1]-p[3]
def p_expr_term(p):
'''
expr : term
'''
p[0]=p[1]
def p_term(p):
'''
term : term TIMES factor
| term DIVIDE factor
'''
if p[2]=='*':
p[0]=p[1]*p[3]
elif p[2]=='/':
p[0]=p[1]/p[3]
def p_term_factor(p):
'''
term : factor
'''
p[0]=p[1]
def p_factor(p):
'''
factor : NUM
'''
p[0]=p[1]
'''
def p_factor(p):
factor : SIN
| COS
| TAN
if p[0]=='sin':
p[0]=Decimal(sin(Decimal(p[1])))
elif p[0]=='cos':
p[0]=Decimal(cos(Decimal(p[1])))
elif p[0]=='tan':
p[0]=Decimal(sin(Decimal(p[1]))/cos(Decimal(p[1])))
p[0]=p[1]
'''
def p_factor_group(p):
'''
factor : LPAREN expr RPAREN
'''
p[0]=p[2]
def p_error(p):
if p:
print("Syntax error at '%s'" % p.value)
else:
print("Syntax error at EOF")
#if __name__ == '__main__':
parser=yacc()
我猜测问题出在sin/cos/tan
部分,但我没有解决。
谁能帮我吗?
答案 0 :(得分:0)
我不确定这是否是您的主要问题,但是您两次定义了一些令牌。
第一次:
--no-bash
第二次:
t_SIN=r'sin'
t_COS=r'cos'
t_TAN=r'tan'
如果删除第一个定义,那么我可以正常运行。
编辑:当我尝试使用它时,它可以添加诸如def t_SIN(t):
r'sin\((\d+(\.\d+)?)\)'
t.value=sin(Decimal(t))
return t
def t_COS(t):
r'cos\((\d+(\.\d+)?)\)'
t.value=cos(Decimal(t))
return t
def t_TAN(t):
r'tan\((\d+(\.\d+)?)\)'
t.value=tan(Decimal(t))
return t
之类的值,但对1+2
有问题。对于我来说sin(9)
应该只能识别文本t_SIN
,但无法计算。解析器应该计算值。
必须是
sin(...)
完整代码
t_SIN=r'sin'
def p_sin(p):
'''
term : SIN LPAREN expr RPAREN
'''
#print('p:', p[0], p[1], p[2], p[3], p[4])
p[0] = sin(p[3])
编辑:此版本仅使用一个函数from ply.lex import lex
from ply.yacc import yacc
from decimal import *
setcontext(Context(prec=2000,rounding=ROUND_HALF_DOWN))
factorial=[1]
fac=Decimal('1')
for i in range(2,1000):
fac*=Decimal(i)
factorial.append(fac)
def sin(s):
sin=Decimal(s)
s=Decimal(s)
for i in range(5,1000,4):
sin+=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
for i in range(3,1000,4):
sin-=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
return sin
def cos(s):
cos=Decimal('1')
s=Decimal(s)
for i in range(4,1000,4):
cos+=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
for i in range(2,1000,4):
cos-=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
return cos
def tan(s):
return sin_(s)/cos_(s)
tokens=['NUM','PLUS','MINUS','TIMES','DIVIDE','LPAREN','RPAREN','SIN','COS','TAN']
#tokens=['NUM','PLUS','MINUS','TIMES','DIVIDE','LPAREN','RPAREN', 'SIN']
t_ignore=' \t\n'
t_PLUS=r'\+'
t_MINUS=r'\-'
t_TIMES=r'\*'
t_DIVIDE=r'/'
t_LPAREN=r'\('
t_RPAREN=r'\)'
t_SIN=r'sin'
t_COS=r'cos'
t_TAN=r'tan'
def t_NUM(t):
r'\d+(\.\d+)?'
t.value=Decimal(t.value)
return t
def t_error(t):
print('Bad Character: {!r}'.format(t.value[0]))
t.lexer.skip(1)
lexer=lex()
def p_expr(p):
'''
expr : expr PLUS term
| expr MINUS term
'''
if p[2]=='+':
p[0]=p[1]+p[3]
elif p[2]=='-':
p[0]=p[1]-p[3]
def p_expr_term(p):
'''
expr : term
'''
p[0]=p[1]
def p_term(p):
'''
term : term TIMES factor
| term DIVIDE factor
'''
if p[2]=='*':
p[0]=p[1]*p[3]
elif p[2]=='/':
p[0]=p[1]/p[3]
def p_sin(p):
'''
term : SIN LPAREN expr RPAREN
'''
#print('p:', p[0], p[1], p[2], p[3], p[4])
p[0] = sin(p[3])
def p_cos(p):
'''
term : COS LPAREN expr RPAREN
'''
#print('p:', p[0], p[1], p[2], p[3], p[4])
p[0] = cos(p[3])
def p_tan(p):
'''
term : TAN LPAREN expr RPAREN
'''
#print('p:', p[0], p[1], p[2], p[3], p[4])
p[0] = tan(p[3])
def p_term_factor(p):
'''
term : factor
'''
p[0]=p[1]
def p_factor(p):
'''
factor : NUM
'''
p[0]=p[1]
'''
def p_factor(p):
factor : SIN
| COS
| TAN
if p[0]=='sin':
p[0]=Decimal(sin(Decimal(p[1])))
elif p[0]=='cos':
p[0]=Decimal(cos(Decimal(p[1])))
elif p[0]=='tan':
p[0]=Decimal(sin(Decimal(p[1]))/cos(Decimal(p[1])))
p[0]=p[1]
'''
def p_factor_group(p):
'''
factor : LPAREN expr RPAREN
'''
p[0]=p[2]
def p_error(p):
if p:
print("Syntax error at '%s'" % p.value)
else:
print("Syntax error at EOF")
#if __name__ == '__main__':
parser=yacc()
while True:
try:
s = input('calc > ')
except EOFError:
break
if not s: continue
result = parser.parse(s)
print(result)
来计算p_func
。它使用sin/cos/tan
来识别计算p[1]
sin/cos/tan
def p_func(p):
'''
term : SIN LPAREN expr RPAREN
| COS LPAREN expr RPAREN
| TAN LPAREN expr RPAREN
'''
print('[DEBUG] p:', p[0], p[1], p[2], p[3], p[4])
if p[1] == 'sin':
p[0] = sin(p[3])
elif p[1] == 'cos':
p[0] = cos(p[3])
elif p[1] == 'tan':
p[0] = tan(p[3])
类似
from ply.lex import lex
from ply.yacc import yacc
from decimal import *
setcontext(Context(prec=2000,rounding=ROUND_HALF_DOWN))
factorial=[1]
fac=Decimal('1')
for i in range(2,1000):
fac*=Decimal(i)
factorial.append(fac)
def sin(s):
sin=Decimal(s)
s=Decimal(s)
for i in range(5,1000,4):
sin+=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
for i in range(3,1000,4):
sin-=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
return sin
def cos(s):
cos=Decimal('1')
s=Decimal(s)
for i in range(4,1000,4):
cos+=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
for i in range(2,1000,4):
cos-=(Decimal((s**Decimal(i)))/Decimal(factorial[i-1]))
return cos
def tan(s):
return sin_(s)/cos_(s)
tokens=['NUM','PLUS','MINUS','TIMES','DIVIDE','LPAREN','RPAREN','SIN','COS','TAN']
#tokens=['NUM','PLUS','MINUS','TIMES','DIVIDE','LPAREN','RPAREN', 'SIN']
t_ignore=' \t\n'
t_PLUS=r'\+'
t_MINUS=r'\-'
t_TIMES=r'\*'
t_DIVIDE=r'/'
t_LPAREN=r'\('
t_RPAREN=r'\)'
t_SIN=r'sin'
t_COS=r'cos'
t_TAN=r'tan'
def t_NUM(t):
r'\d+(\.\d+)?'
t.value=Decimal(t.value)
return t
def t_error(t):
print('Bad Character: {!r}'.format(t.value[0]))
t.lexer.skip(1)
lexer=lex()
def p_expr(p):
'''
expr : expr PLUS term
| expr MINUS term
'''
if p[2]=='+':
p[0]=p[1]+p[3]
elif p[2]=='-':
p[0]=p[1]-p[3]
def p_expr_term(p):
'''
expr : term
'''
p[0]=p[1]
def p_term(p):
'''
term : term TIMES factor
| term DIVIDE factor
'''
if p[2]=='*':
p[0]=p[1]*p[3]
elif p[2]=='/':
p[0]=p[1]/p[3]
def p_func(p):
'''
term : SIN LPAREN expr RPAREN
| COS LPAREN expr RPAREN
| TAN LPAREN expr RPAREN
'''
print('p:', p[0], p[1], p[2], p[3], p[4])
if p[1] == 'sin':
p[0] = sin(p[3])
elif p[1] == 'cos':
p[0] = cos(p[3])
elif p[1] == 'tan':
p[0] = tan(p[3])
def p_term_factor(p):
'''
term : factor
'''
p[0]=p[1]
def p_factor(p):
'''
factor : NUM
'''
p[0]=p[1]
def p_factor_group(p):
'''
factor : LPAREN expr RPAREN
'''
p[0]=p[2]
def p_error(p):
if p:
print("Syntax error at '%s'" % p.value)
else:
print("Syntax error at EOF")
#if __name__ == '__main__':
parser=yacc()
while True:
try:
s = input('calc > ')
except EOFError:
break
if not s: continue
result = parser.parse(s)
print(result)
并使用带有功能的字典
t_FUNC=r'sin|cos|tan'
def p_func(p):
'''
term : FUNC LPAREN expr RPAREN
'''
print('p:', p[0], p[1], p[2], p[3], p[4])
if p[1] == 'sin':
p[0] = sin(p[3])
elif p[1] == 'cos':
p[0] = cos(p[3])
elif p[1] == 'tan':
p[0] = tan(p[3])