首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Grappa匹配OR表达式(Java PEG解析器)

使用Grappa匹配OR表达式(Java PEG解析器)
EN

Stack Overflow用户
提问于 2015-10-09 11:30:02
回答 1查看 388关注 0票数 2

我刚接触聚乙二醇解析,正在尝试编写一个简单的解析器来解析出一个表达式,比如:“anotherterm”,理想的情况是解析成一个类似如下的term1:

代码语言:javascript
运行
复制
          OR
-----------|---------
|                    |
"term1"            "term2 anotherterm"

我目前使用的是Grappa (https://github.com/fge/grappa),但它甚至不能匹配更基本的表达式"term1 OR term2“。这就是我所拥有的:

代码语言:javascript
运行
复制
package grappa;

import com.github.fge.grappa.annotations.Label;
import com.github.fge.grappa.parsers.BaseParser;
import com.github.fge.grappa.rules.Rule;

public class ExprParser extends BaseParser<Object> {

  @Label("expr")
  Rule expr() {
    return sequence(terms(), wsp(), string("OR"), wsp(), terms(), push(match()));
  }

  @Label("terms")
  Rule terms() {
    return sequence(whiteSpaces(),
        join(term()).using(wsp()).min(0),
        whiteSpaces());
  }

  @Label("term")
  Rule term() {
    return sequence(oneOrMore(character()), push(match()));
  }

  Rule character() {
    return anyOf(
        "0123456789" +
        "abcdefghijklmnopqrstuvwxyz" +
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
        "-_");
  }

  @Label("whiteSpaces")
  Rule whiteSpaces() {
    return join(zeroOrMore(wsp())).using(sequence(optional(cr()), lf())).min(0);
  }

}

有谁能给我指个方向吗?

EN

回答 1

Stack Overflow用户

发布于 2016-03-22 00:19:40

( grappa的作者在这里...)

好的,那么,您似乎想要的实际上是一个解析树。

最近,grappa开发了一个扩展(2.0.x+),它可以满足您的需求:https://github.com/ChrisBrenton/grappa-parsetree

默认情况下,Grappa只“盲目地”匹配文本,并且有一个堆栈可供使用,因此,例如,您可以:

代码语言:javascript
运行
复制
public Rule oneOrOneOrEtc()
{
    return join(one(), push(match())).using(or()).min(1));
}

但你所有的匹配都会在堆栈上...不是很实用,但在某些情况下仍然有用(例如,请参阅sonar-sslr-grappa)。

在您的情况下,您需要这个包。您可以使用它来执行以下操作:

代码语言:javascript
运行
复制
// define your root node
public final class Root
    extends ParseNode
{
    public Root(final String match, final List<ParseNode> children)
    {
        super(match, children);
    }
}

// define your parse node
public final class Alternative
    extends ParseNode
{
    public Alternative(final String match, final List<ParseNode> children)
    {
        super(match, children);
    }
}

这是最小的实现。然后你的解析器看起来就像这样:

代码语言:javascript
运行
复制
@GenerateNode(Alternative.class)
public Rule alternative() // or whatever
{
    return // whatever an alternative is
}

@GenerateNode(Root.class)
public Rule root
{
    return join(alternative())
        .using(or())
        .min(1);
}

这里发生的事情是,如果你有一个字符串,那么根节点是在备选节点之前匹配的:

代码语言:javascript
运行
复制
a or b or c or d

然后,根节点将匹配“整个序列”,并且它将有四个备选方案分别匹配a、b、c和d。

这里的全部功劳都归功于Christopher Brenton,因为它首先提出了这个想法!

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33029437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档