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

标签 python regex lexical-analysis ply

我正在做一个词法分析器作为大学类(class)的一部分。我们教授给我们的脑筋急转弯之一(对评分没有贡献的额外作业)是我们如何在字符串文字中实现注释。
我们的字符串文字以感叹号开始和结束。例如!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'\.\.\.[^\r\n]*\.\.\.', "", t.value)
    return t

最佳答案

也许这可能是另一种选择。
使用第一个否定字符类匹配 0+ 次除反斜杠、点或感叹号之外的任何字符。
然后,当您匹配第一个字符类不匹配的字符时,请使用替换来匹配:

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

  • 为了防止灾难性的回溯,您可以在 Python 中使用正向前瞻和内部捕获组来模拟原子组。如果断言为真,则使用对 \1 的反向引用匹配。
    例如
    (?<!\\)![^!\\.]*(?:(?:\.(?!\.\.)|(?=(\.{3}.*?\.{3}))\1|\\.)[^!\\.]*)*!
    
    说明
  • (?<!\\)!比赛 !前面没有直接\
  • [^!\\.]*匹配除 ! 以外的任何字符 1+ 次\.
  • (?:非捕获组
  • (?:\.(?!\.\.)匹配一个不直接跟在 2 个点后面的点
  • |
  • (?=(\.{3}.*?\.{3}))\1来自 ... 的组 1 中的断言和捕获到最近的 ...
  • |
  • \\.匹配转义字符

  • )关闭群
  • [^!\\.]*匹配除 ! 之外的任何字符 1+ 次\.
  • )*!关闭非捕获组并重复 0+ 次,然后匹配 !

  • Regex demo

    关于python - 如何忽略字符串文字中的注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64210788/

    相关文章:

    python - 为什么单击一次 ToolButton 上的 pygtk 回调会执行两次

    php - 从格式为 "DD MMM YYYY"的字符串中提取日期

    ruby - 在 Ruby 中解析结构化文本

    java - 伪编程语言的正则表达式

    python - 如何针对大型规则集(5000 多个且不断增长)构建高效的电子邮件过滤器

    lexical-analysis - 在 Gold Parser Builder 中定义字符串/输入的长度

    python - 使用python psycopg2保存二进制数据时如何修复 "can' t adapt error

    python - 使用 PIL 优化 .png 图像

    python - 将多个文件中的数据检索到多个数据帧中

    rewrite.xml 中的正则表达式