4

添加skip到规则并没有达到我的预期。这是一对用逗号和空格分隔的标记的语法。我制作了一个带有逗号标记的版本skip,以及一个没有逗号的版本:

grammar Commas;

COMMA:          ', ';
COMMASKIP:      ', ' -> skip;
DATA:           ~[, \n]+;

withoutSkip:    data COMMA data '\n';
withSkip:       data COMMASKIP data '\n';
data:           DATA;

skip在没有按预期工作的情况下测试规则:

$ echo 'a, b' | grun Commas withoutSkip -tree
(withoutSkip (data a) ,  (data b) \n)

Withskip给了我一个错误:

$ echo 'a, b' | grun Commas withSkip -tree
line 1:1 mismatched input ', ' expecting COMMASKIP
(withSkip (data a) ,  b \n)

如果我注释掉COMMAandwithoutSkip规则,我会得到:

$ echo 'a, b' | grun Commas withSkip -tree
line 1:3 missing ', ' at 'b'
(withSkip (data a) <missing ', '> (data b) \n)

我正在尝试获取仅包含不带逗号的数据标记的输出,如下所示:

(withSkip (data a) (data b) \n)

我究竟做错了什么?

4

1 回答 1

8

skip导致词法分析器丢弃令牌。因此,skip不能在解析器规则中使用 ped 词法分析器规则。

另一件事,如果两个或多个规则匹配相同的输入,则首先定义的规则将“赢得”语法后面定义的规则,无论解析器是否尝试匹配语法后面定义的规则,第一条规则将永远“获胜”。在您的情况下,COMMASKIP将永远不会创建规则,因为COMMA匹配相同的输入。

尝试这样的事情:

语法逗号;

COMMA : ',' -> skip;
SPACE : (' '|'\n') -> skip;
DATA  : ~[, \n]+;

data  : DATA+;

编辑

那么如何在不将逗号包含在解析树中的情况下指定逗号的位置?您的代码将匹配 a, , b。

你没有,所以如果逗号很重要(即。a,,b)是无效的,它不能从词法分析器中跳过。

我认为在 antlr3 中你应该使用感叹号。

在 ANTLR 4 中,您无法从解析中创建 AST。在新版本中,所有终端/规则都在一个解析树中。您可以使用自定义访问者和/或侦听器迭代此树。可以在此问答中找到如何执行此操作的演示:一旦语法完成,遍历 ANTLR v4 树的最佳方法是什么?

在您的情况下,语法如下所示:

grammar X;

COMMA : ',';
SPACE : (' '|'\n') -> skip;
DATA  : ~[, \n]+;

data  : DATA (COMMA DATA)*;

然后像这样创建一个监听器:

public class MyListener extends XBaseListener {

    @Override
    public void enterData(XParser.DataContext ctx) {

        List dataList = ctx.DATA(); // not sure what type of list it returns...
        // do something with `dataList`
    }
}

如您所见,COMMA没有删除,但在enterData(...)您内部只使用DATA令牌。

于 2013-02-28T08:00:37.627 回答