代码之家  ›  专栏  ›  技术社区  ›  Sarah Vessels

树梢语法中的匹配标记对

  •  2
  • Sarah Vessels  · 技术社区  · 14 年前

    我不想重复 the Cthulhu answer ,但我想使用treetop匹配成对的打开和关闭HTML标记。使用 this grammar ,我可以匹配开始标记和结束标记,但现在我需要一个规则将它们捆绑在一起。我尝试过以下方法,但是使用它可以让我的解析器永远运行下去(无限循环):

    rule html_tag_pair
      html_open_tag (!html_close_tag (html_tag_pair / '' / text / newline /
        whitespace))+ html_close_tag <HTMLTagPair>
    end
    

    我试图基于递归圆括号示例和负的前瞻性示例 on the Treetop Github page . 我引用的其他规则如下:

    rule newline
      [\n\r] {
        def content
          :newline
        end
      }
    end
    
    rule tab
      "\t" {
        def content
          :tab
        end
      }
    end
    
    rule whitespace
      (newline / tab / [\s]) {
        def content
          :whitespace
        end
      }
    end
    
    rule text
      [^<]+ {
        def content
          [:text, text_value]
        end
      }
    end
    
    rule html_open_tag
      "<" html_tag_name attribute_list ">" <HTMLOpenTag>
    end
    
    rule html_empty_tag
      "<" html_tag_name attribute_list whitespace* "/>" <HTMLEmptyTag>
    end
    
    rule html_close_tag
      "</" html_tag_name ">" <HTMLCloseTag>
    end
    
    rule html_tag_name
      [A-Za-z0-9]+ {
        def content
          text_value
        end
      }
    end
    
    rule attribute_list
      attribute* {
        def content
          elements.inject({}){ |hash, e| hash.merge(e.content) }
        end
      }
    end
    
    rule attribute
      whitespace+ html_tag_name "=" quoted_value {
        def content
          {elements[1].content => elements[3].content}
        end
      }
    end
    
    rule quoted_value
      ('"' [^"]* '"' / "'" [^']* "'") {
        def content
          elements[1].text_value
        end
      }
    end
    

    我知道我需要允许匹配单独的开始或结束标记,但是如果有一对HTML标记存在,我想把它们成对地放在一起。通过将它们与我的语法相匹配来做到这一点似乎是最干净的,但也许有更好的方法?

    2 回复  |  直到 12 年前
        1
  •  1
  •   Clifford Heath    12 年前

    您只能使用每个HTML标记对的单独规则或使用语义谓词来完成此操作。也就是说,通过保存开始标签(在sempre中),然后接受(在另一个sempre中)结束标签(仅当它是相同的标签时)。在树端,这比它应该做的要困难得多,因为没有方便的地方来保存上下文,并且您无法查看解析器堆栈,但这是可能的。

    顺便说一句,在分析mime边界(以及标记)时也会出现同样的问题。我还没有检查过Mikel在ActionMailer中的实现(可能他使用了嵌套的mime解析器),但在Treetop中是可能的。

    http://github.com/cjheath/activefacts/blob/master/lib/activefacts/cql/parser.rb 我将上下文保存在一个假输入流中—您可以看到它必须支持哪些方法—因为“input”在所有syntaxnode上都可用。我有不同的理由使用sempres,但有些技术是适用的。

        2
  •  5
  •   munchbit    12 年前

    下面是一个非常简单的语法,它使用语义谓词将结束标记与开始标记匹配。

    grammar SimpleXML
      rule document
        (text / tag)*
      end
    
      rule text
        [^<]+
      end
    
      rule tag
        "<" [^>]+ ">" (text / tag)* "</" [^>]+ &{|seq| seq[1].text_value == seq[5].text_value } ">"
      end
    end