在 parboiled 中使用变量
Using variables in parboiled
我正在尝试使用 parboiled Java library.
创建一个简单的 XML 解析器
以下代码尝试使用变量来验证结束标记是否包含与开始标记相同的标识符。
class SimpleXmlParser2 extends BaseParser<Object> {
Rule Expression() {
StringVar id = new StringVar();
return Sequence(OpenElement(id), ElementContent(), CloseElement(id));
}
Rule OpenElement(StringVar id) {
return Sequence('<', Identifier(), ACTION(id.set(match())), '>');
}
Rule CloseElement(StringVar id) {
return Sequence("</", id.get(), '>');
}
Rule ElementContent() {
return ZeroOrMore(NoneOf("<>"));
}
Rule Identifier() {
return OneOrMore(CharRange('A', 'z'));
}
}
但是,当我创建 ParseRunner 时,上述操作失败并显示错误消息 org.parboiled.errors.GrammarException: 'null' cannot be automatically converted to a parser Rule
。
看来我对如何在半熟中使用变量有一个基本的误解。谁能帮我解决这个问题?
想出了一个答案。将它包含在这里,供可能遇到相同问题的任何其他煮熟的新手使用。
问题是对变量内容的任何访问都必须在解析器操作中发生,以确保它发生在解析阶段,而不是在规则构建阶段。
对上述程序进行以下更改,确保在元素标识符不匹配时解析失败。
Rule CloseElement(StringVar id) {
return Sequence("</", Identifier(), matchStringVar(id), '>');
}
Action matchStringVar(final StringVar var) {
return new Action() {
public boolean run(Context ctx) {
String match = ctx.getMatch();
return match.equals(var.get());
}
};
}
我正在尝试使用 parboiled Java library.
创建一个简单的 XML 解析器以下代码尝试使用变量来验证结束标记是否包含与开始标记相同的标识符。
class SimpleXmlParser2 extends BaseParser<Object> {
Rule Expression() {
StringVar id = new StringVar();
return Sequence(OpenElement(id), ElementContent(), CloseElement(id));
}
Rule OpenElement(StringVar id) {
return Sequence('<', Identifier(), ACTION(id.set(match())), '>');
}
Rule CloseElement(StringVar id) {
return Sequence("</", id.get(), '>');
}
Rule ElementContent() {
return ZeroOrMore(NoneOf("<>"));
}
Rule Identifier() {
return OneOrMore(CharRange('A', 'z'));
}
}
但是,当我创建 ParseRunner 时,上述操作失败并显示错误消息 org.parboiled.errors.GrammarException: 'null' cannot be automatically converted to a parser Rule
。
看来我对如何在半熟中使用变量有一个基本的误解。谁能帮我解决这个问题?
想出了一个答案。将它包含在这里,供可能遇到相同问题的任何其他煮熟的新手使用。
问题是对变量内容的任何访问都必须在解析器操作中发生,以确保它发生在解析阶段,而不是在规则构建阶段。
对上述程序进行以下更改,确保在元素标识符不匹配时解析失败。
Rule CloseElement(StringVar id) {
return Sequence("</", Identifier(), matchStringVar(id), '>');
}
Action matchStringVar(final StringVar var) {
return new Action() {
public boolean run(Context ctx) {
String match = ctx.getMatch();
return match.equals(var.get());
}
};
}