我正在尝试使用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
匹配,即使它不应该这样做,因为正则表达式在字母之前需要*
。
在此之后,解析器无法识别表达式,因为词法分析器不会返回正确的标记。
有什么问题?用于令牌IDENTIFIER的正则表达式在Python中完美运行。
答案 0 :(得分:1)
我想我发现了问题和解决方案。
' *'
中的问题是'\* '
,因为它将'\* *'
视为一个字符串 - 所以'\* '
表示'abc*'
多次或无(例如'abc'
表示'\*[ ]*'
多次或没有)。
您需要'\*\s*'
或xhr
答案 1 :(得分:1)
根据PLY manual :(强调添加)
在内部,
lex.py
使用re
模块进行模式匹配。 使用re.VERBOSE
标志编译模式,可用于帮助提高可读性。但是,请注意忽略未转义的空格并在此模式下允许注释。如果您的模式涉及空格,请确保使用\s
。如果您需要匹配#
字符,请使用[#]
。
因此,正则表达式\* *[a-zA-Z_]+
中的空格字符将被忽略,从而有效地生成正则表达式\**[a-zA-Z_]+
;即零个或多个星星。如果你真的希望它是一个明星,后跟一个或多个空格,你会想要像:\*\ [a-zA-Z_]+
。