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

问题描述 投票:0回答:1

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

python
1个回答
0
投票

我不确定这是否是您的主要问题,但是您两次定义了一些标记。

第一次:

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

如果删除第一个定义,则可以正常运行。


EDIT:当我尝试使用它时,它可以添加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)

EDIT:此版本仅使用一个函数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])

并且使用带有功能的字典

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


    func = {'sin': sin, 'cos': cos, 'tan': tan}

    if p[1] in func:
        p[0] = func[p[1]](p[3])
© www.soinside.com 2019 - 2024. All rights reserved.