如何忽略字符串文字中的注释



我正在做一个lexer,作为大学课程的一部分。教授给我们的一个脑筋急转弯(对评分没有帮助的额外作业(是,我们如何在字符串文字中实现注释。

我们的字符串文字以感叹号开头和结尾。例如!this is a string literal!

我们的评论以三个句号开始和结束。例如...This is a comment...

从字符串文字中删除注释相对简单。只需通过/!.*!/匹配字符串文字,然后通过正则表达式删除注释。如果有三个以上的连续逗号,但没有结束逗号,则抛出一个错误。

然而,我想更进一步。我想实现字符串文本中感叹号的转义。不幸的是,我似乎无法同时使用评论和感叹号转义符。

我想要创建的是可以同时包含注释和感叹号转义的字符串文字。这是怎么做到的?

示例:

!Normal string!
!String with escaped ! exclamation mark!
!String with a comment ... comment ...!
!String ! with both ... comments can have unescaped exclamation marks!!!... !

这是我目前的代码,不能忽略评论中的感叹号:

def t_STRING_LITERAL(t):
r'![^!\]*(?:\.[^!\]*)*!'
# remove the escape characters from the string
t.value = re.sub(r'\!', "!", t.value)
# remove single line comments
t.value = re.sub(r'...[^rn]*...', "", t.value)
return t

也许这可能是另一种选择。

使用第一个否定字符类将除反斜杠、点或感叹号之外的任何字符匹配0+倍。

然后,当你匹配第一个字符类不匹配的字符时,使用一个替换来匹配其中一个:

  • 重复0+次匹配一个不直接跟2个点的点
  • 或从3个点匹配到3个点的下一个第一匹配
  • 或只匹配转义字符

为了防止灾难性的回溯,可以在Python中使用带有捕获组的正向前瞻来模拟原子组。如果断言为true,则使用对1的反向引用进行匹配。

例如

(?<!\)![^!\.]*(?:(?:.(?!..)|(?=(.{3}.*?.{3}))1|\.)[^!\.]*)*!

解释

  • (?<!\)!比赛!不直接以开头
  • [^!\.]*匹配1+乘以除!.之外的任何字符
  • (?:非捕获组
    • (?:.(?!..)匹配一个不直接跟2个点的点
    • |
    • (?=(.{3}.*?.{3}))1在组1中从...断言并捕获到最近的...
    • |
    • \.匹配转义字符
  • )关闭组
  • [^!\.]*匹配1+乘以除!.之外的任何字符
  • )*!关闭非捕获组并重复0+次,然后匹配!

Regex演示

查看此正则表达式以匹配字符串文字:https://regex101.com/r/v2bjWi/2.CCD_ 26。

  • 它被两个CCD_ 27包围
  • 它由交替转义的惊叹号\!、注释(?:...(?P<comment>.*?)...)和非感叹号[^!]组成。请注意,这大约是使用正则表达式所能实现的。任何额外的请求,都将不再足够

最新更新