0

我有一个 ply 问题,我必须接收一个带有标记列表和语法 (bnf) 的文件,我编写了一个语法来识别输入,它几乎可以工作(只是小问题,我们正在解决它们),因为例如这是一个有效的输入文件

#tokens = NUM PLUS TIMES
exp : exp PLUS exp | exp TIMES exp
exp : NUM

(在这种情况下,我们不关心模棱两可的语法或其他什么,这是一个输入示例)

分别解析每一行工作正常,但我想用这些规则解析整个文件:

  • #tokens 必须只在第一行,所以如果我们在语法之后有 #tokens 声明,则它是无效的
  • 每行“代码”之后可以有 0 个或多个空行
  • 你可以有尽可能多的语法规则

我尝试使用循环分别扫描和解析每一行,但我无法控制第一个(也是非常重要的)规则,所以我在我的 .py 文件中尝试了这个:

我定义了 t_NLINEA (新行)我也有使用 \n 字符作为文字的问题,并且使用 rU 模式打开文件以避免有关 \r\n 或 \n 字符的冲突,所以我添加了这些规则:

def p_S(p):
'''S : T N U'''
print("OK")

def p_N(p): '''N : NLINEA N''' pass

def p_N2(p): '''N : ''' 通过

def p_U(p): '''U : RN U''' pass

def p_U2(p): '''U : ''' 传球

(正如我在上面告诉你的,我让你使用 N 规则,因为 ply 在我的语法中不接受 \n 文字,我将 \n 添加到“literals”变量中)

T 是解析#tokens 声明的规则,R 用于解析语法规则,如果我在单行字符串中使用它们,T 和 R 可以正常工作,但是当我添加上面写的产品时,我在解析时遇到语法错误第一个语法规则,例如A : B C我得到语法错误:

有什么建议吗?谢谢

4

1 回答 1

0

Ply 试图根据您的规则找出“起始规则”。使用您编写的内容,它将使“exp”成为开始规则,即每个字符串或文件只有一个表达式。如果你想要多个表达式,你可能想要一个表达式列表:

def p_exp_list(p):
    """exp_list :
                | exp_list exp
    """
    if len(p) == 1:
       p[0] = []
    else:
       p[0] = p[1] + [p[2]]

那么你的起始规则将是“exp_list”。这将允许在每一行上使用多个表达式。如果您想限制每行一个表达式,那么如何:

def p_line_list(p):
    """line_list :
                 | line_list line
    """
    if len(p) == 1:
       p[0] == []
    else:
       p[0] = p[1] + [p[2]]

def p_line(p):
    """line : exp NL"""
    p[0] = p[1]

我认为您不能将换行符用作文字(因为它可能会弄乱正则表达式)。您可能需要更具体的令牌规则:

t_NL = r'[\r*\n]'

很确定这会起作用,但没有尝试过,因为没有足够的继续。

至于“#token”行,你可以跳过它,如果它没有出现在其他任何地方:

def t_COMMENT(t):
    r'#.*$'
    pass # ignore this token
于 2013-11-06T19:59:35.800 回答