我正在尝试使用 Ply 创建解析器,但我遇到了一个奇怪的错误。 这是发生匹配错误的 MCVE:
词法分析器
import ply.lex as lex
tokens = (
'IDENTIFIER',
'NAME',
'EQUALS'
)
def t_IDENTIFIER(t):
r'\* *[a-zA-Z_]+'
print("identifier")
return t
def t_NAME(t):
r"[a-zA-Z_]+"
print("name")
return t
t_EQUALS = r"="
t_ignore = ' \t'
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)
# Error handling rule
def t_error(t):
print("Illegal character '%s' at line' %s'" % (t.value[0] , t.lexer.lineno ))
t.lexer.skip(1)
# Build the lexer
lexer = lex.lex()
解析器
import ply.yacc as yacc
from l import tokens
def p_main(p):
'''
main : NAME EQUALS NAME
'''
def p_error(p):
if p is not None:
print ("Line %s, illegal token %s" % (p.lineno, p.value))
else:
print("Syntax error in input!")
parser = yacc.yacc()
with open('simple2','r') as f:
result = parser.parse(f.read())
我的输入文件只包含这个:
A = B
发生的是第一个词 A 与标记 IDENTIFIER 匹配,即使它不应该这样做,因为正则表达式需要 * 字母前。 此后,解析器无法识别表达式,因为词法分析器未返回正确的标记。
怎么了?用于 token IDENTIFIER 的正则表达式在 Python 中完美运行。
请您参考如下方法:
根据PLY manual :(强调)
Internally,
lex.pyuses theremodule to do its pattern matching. Patterns are compiled using there.VERBOSEflag which can be used to help readability. However, be aware that unescaped whitespace is ignored and comments are allowed in this mode. If your pattern involves whitespace, make sure you use\s. If you need to match the#character, use[#].
因此正则表达式 \* *[a-zA-Z_]+ 中的空格字符被忽略,使正则表达式有效地成为 \**[a-zA- Z_]+;即,零个或多个星星。如果你真的希望它是一个星号后跟一个或多个空格,你会想要这样的东西:\*\[a-zA-Z_]+。
