PLY与正确的端子不匹配

时间:2018-11-13 14:10:16

标签: python parsing yacc lex ply

我在PLY中创建了一个简单的解析器,该解析器有两个规则:

  • 首先出现:时会出现一个名字
  • 首先出现=时出现数字

对应的代码:

from ply import lex, yacc

tokens = ['Name', 'Number']

def t_Number(t):
    r'[0-9]'
    return t

def t_Name(t):
    r'[a-zA-Z0-9]'
    return t

literals = [':', '=']

def t_error(t):
    print("lex error: " + str(t.value[0]))
    t.lexer.skip(1)

lex.lex()

def p_name(p):
    '''
    expression : ':' Name
    '''
    print("name: " + str(list(p)))

def p_number(p):
    '''
    expression : '=' Number
    '''
    print("number: " + str(list(p)))

def p_error(p):
    print("yacc error: " + str(p.value))

yacc.yacc()
yacc.parse("=3")
yacc.parse(":a")
yacc.parse(":3")

我的期望是,如果看到:=,它将输入相应的规则并尝试匹配相应的终端。但是在第三个示例中,它与应为名称的Number匹配,然后失败。 Afaik的语法应该没有上下文限制(需要解析),是这种情况吗?另外,当一个令牌是另一令牌的超集时,我该如何处理?

1 个答案:

答案 0 :(得分:1)

在查询语法之前先进行层标记化,因此上下文不会影响标记化。(更准确地说,解析器接收由词法分析器生成的标记流。这两个过程在实践中是交织的,但它们会保留独立。)

您可以将上下文构建到词法分析器中,但这确实很难实现。 (尽管如此,这是一种常见的策略。)

您最好的选择是编写您的词法规则以产生尽可能细的结果,然后编写语法以接受所有替代方法:

def p_name(p):
    '''
    expression : ':' Name
    expression : ':' Number
    '''
    print("name: " + str(list(p)))

def p_number(p):
    '''
    expression : '=' Number
    '''
    print("number: " + str(list(p)))

假定您更改词法规则以将最具体的模式放在首位。