1

给定输入<outer> Content <inner> Inner <single/> </inner> </outer>

我将如何编写语法来解析<single>节点以及具有匹配关闭节点的节点?

这是我目前的语法,取自这里

Content =
  (Element / Text)*

Element =
  startTag:StartTag content:Content endTag:EndTag {
    if (startTag != endTag) {
      throw new Error(
        "Expected </" + startTag + "> but </" + endTag + "> found."
      );
    }

    return {
      name:    startTag,
      content: content
    };
  }

StartTag =
  "<" name:TagName ">" { return name; }

EndTag =
  "</" name:TagName ">" { return name; }

TagName = chars:[a-z]+ { return chars.join(""); }
Text    = chars:[^<]+  { return chars.join(""); }

这仅适用于具有关闭节点的节点。

我认为问题在于文本规则。所以我一直在尝试改变它以包含一个负面的前瞻,比如:

Text    = chars:(!EndTag .)* EndTag { return chars.join(""); }

但这还没有取得任何成功。

有任何想法吗?

4

1 回答 1

1

我这样做的方法是让 Element 匹配“sTag”或“selfTag”;如果它匹配“selfTag”,则没有“Content”或“endTag”:

Content =
  (Element / Text)*

Element =
  startTag:sTag content:Content endTag:eTag {
    if (startTag != endTag) {
      throw new Error(
        "Expected </" + startTag + "> but </" + endTag + "> found."
      );
    }

    return {
      name:    startTag,
      content: content
    };
  }
  / startTag:selfTag {
        return startTag;
    }

sTag =
  "<" name:TagName ">" { return name; }

selfTag =
  "<" name:TagName "/>" { return name; }

eTag =
  "</" name:TagName ">" { return name; }

TagName = chars:[a-z-]+ { return chars.join(""); }
Text    = chars:[^<]+  { return chars.join(""); }

请注意,此答案要求您使用<single/>而不是<single>(即 / 是必需的);这是向 PEG 解析器发出悬空开始标记和“自闭合标记”之间区别的最简单方法。

于 2014-09-28T21:57:47.447 回答