我在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的语法应该没有上下文限制(需要解析),是这种情况吗?另外,当一个令牌是另一令牌的超集时,我该如何处理?
答案 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)))
假定您更改词法规则以将最具体的模式放在首位。