给出输入<outer> Content <inner> Inner <single/> </inner> </outer>
。
我如何编写解析<single>
节点的语法以及具有匹配结束节点的节点?
这是我目前的语法,取自here:
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规则。因此,我一直在尝试改变它,以包括一个负面的前瞻,如:
Text = chars:(!EndTag .)* EndTag { return chars.join(""); }
但那还没有取得任何成功。
有什么想法吗?
答案 0 :(得分: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解析器发出悬挂起始标签和“自闭标签”之间差异的最简单方法。