ply - PLY - 在 C 样式注释中转义新行
问题描述
我正在使用 PLY 编写一个简单的解析器。我的评论可能看起来像这样
# this is a single line comment \
with an escaped new line
我的尝试是在这里使用状态。我有
states = (
('COMMENT', 'exclusive'),
)
tokens = ('COMMENT')
def t_begin_COMMENT(t):
r'\#'
t.lexer.begin('COMMENT')
def t_COMMENT_contents(t):
r'.|\\\n'
t_COMMENT_ignore = r' '
def t_COMMENT_error(t):
pass
def t_COMMENT_end(t):
r'\n'
t.lexer.begin('INITIAL')
当我做
lexer = lex.lex()
string = "# test \\\ns \n4"
lexer.input(string)
for tok in lexer:
print(tok)
它应该打印 4 (我有另一个令牌,但现在无关紧要)但我明白了s
,4
哪里s
还有评论。如何为内容编写正则表达式?这是因为COMMENT
以 结尾\n
吗?
解决方案
Python 正则表达式不会产生最长的匹配。Python 正则表达式中的Alternation( |
) 是有序的;如果您使用模式.|\\\n
,.
则将始终匹配(除非字符串为空),因此\\\n
永远不会尝试。如果没有转义符号,这更容易看到:
>>> import re
>>> re.match(r'.|ab', 'ab')
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.match(r'ab|.', 'ab')
<_sre.SRE_Match object; span=(0, 2), match='ab'>
我完全不清楚为什么要进行所有这些工作,而不是使用单个正则表达式而不必求助于词法分析器状态。
def t_comment(t):
r'\#(\\\n|.)*\n'
pass
(注意:我更喜欢正则表达式r'\#(\\[\s\S]|.)*'
,它允许 a\
转义任何内容,包括它自己。您使用的正则表达式不允许您在注释行的末尾放置反斜杠:
# This will continue, perhaps unexpectedly: \\
still a comment
此外,无论如何都将忽略尾随\n
,因此没有明显的理由将其包含在模式中,如果注释位于输入的末尾并且输入没有以换行符终止,则它可能无法匹配。
推荐阅读
- python - 经过卷积步骤后,全连接层中张量的形状应该是什么?
- c# - 错误 ajax 错误数据表警告:表 id -example
- hadoop - 在 Amazon EMR 上处理 15GB 的日志文件数据需要多长时间?
- apache-kafka - Kafka 流丰富 - 采购查找表
- c# - 无法通过c#中的gridview更新数据库
- azure - 在统一上使用 zumo 在 Azure 上发布到 Web api 时出错
- sql-server - 在 django 数据库中插入多个值 - 原始 sqlite 语句
- python - 使用 Python 从 CSV 文件中的文本文件填充数据
- c# - Gridview没有在C#中添加新行
- php - 我的外部 php 不理解在 ReactJS 的 render() 中声明的输入的 name 属性值