“ SyntaxError:无法构建词法分析器”是什么意思?

时间:2019-12-15 04:31:30

标签: python

我目前正在使用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部分,但我没有解决。 谁能帮我吗?

1 个答案:

答案 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])