3

我已将我的评论包含在 ANTLR 4 中的一个单独频道中。在我的情况下,它是频道 2。

这是我的词法分析器语法。

COMMENT: '/*' .*? '*/' -> channel(2) 
       ;

我想访问此频道 2 并在此频道上进行解析以积累评论。所以我把它包括在解析语法中,如下所示:

comment
:COMMENT
;

在节目中

        string s = " paring string"
        AntlrInputStream input = new AntlrInputStream(s);
        CSSLexer lexer = new CSSLexer(input); 
       
        CommonTokenStream tokens = new CommonTokenStream(lexer,2);

然后我想对令牌进行解析

var xr = parser.comment().GetRuleContexts<CommentContext>();

因为我想从 CommentContext 对象中获取信息,例如Start.Column等。

编辑:

这是改进的问题

更具体地说,我想获取通道 2 中的所有标记并使用注释语法对其进行解析,以将所有注释获取到一个 list( IReadOnly<CommentContext>) 中,以便我可以遍历其中的每一个并访问诸如起始行之类的信息,开始列、结束行结束列和标记文本。

CommonTokenStream tokens = new CommonTokenStream(lexer,2);

这并没有给我通道 2 中的标记。我发现的另一件事是,直到这些标记作为参数传递给解析器构造XParser parser = new XParser(tokens);

然后只有我可以通过调用访问令牌GetTokens()。在令牌中,我可以看到有被标识为令牌的评论并且在频道 2 中。即使CommentTokenStrem如上所述指定频道号。它包含所有令牌。

  1. 在使用令牌创建解析器对象之前无法访问令牌的原因是什么?

  2. 我想CommentTokenStrem在通道 2 中获取一个并将其传递给 XParser 对象创建,以使用我的comment语法解析这些标记。在 ANTLR 4 API 中执行此操作的最佳方法是什么?

4

4 回答 4

4

CommonTokenStream在内部跟踪来自任何通道的所有令牌。调用时唯一getTokens()不到的是执行操作的词法分析器规则-> skip(甚至没有为这些规则创建标记)。

您可以使用TokenStream.LTandIntStream.consume方法查看通道 2 上的令牌。

Java 示例

CommonTokenStream cts = new CommonTokenStream(tokenSource, 2);
List<Token> tokens = new ArrayList<Token>();
while (cts.LA(1) != EOF) {
    tokens.add(cts.LT(1));
    cts.consume();
}

C# 示例:

CommonTokenStream cts = new CommonTokenStream(tokenSource, 2);
IList<IToken> tokens = new List<IToken>();
while (cts.La(1) != Eof)
{
    tokens.Add(cts.Lt(1));
    cts.Consume();
}
于 2013-09-05T12:26:13.270 回答
2

这个怎么样:

 var allowedChannels = new[] { 2 }; // add more if you need to
 var tokensImInterestedIn = tokens.GetTokens().Where(token => allowedChannels.Contains(token.Channel) && token.Type != CSSLexer.Eof).ToArray();

 // if you're just interested in one particular channel
 var tokensImInterestedIn = tokens.GetTokens().Where(token => token.Channel == 2) && token.Type != CSSLexer.Eof).ToArray();
于 2013-09-05T06:52:18.087 回答
0

或者,您可以将所有其他令牌放在另一个通道中,并为您的解析器使用默认通道。

当然,如果您有两个解析器期望令牌位于不同的通道中,那么这将不起作用。

于 2013-09-05T11:07:55.000 回答
0

ANTLR 4 C#:

       using Antlr4.Runtime;
       ...

       MyLexer lexer = new MyLexer (inputStream);
       var tokenstream = new CommonTokenStream(lexer, TokenConstants.HiddenChannel);
       IList<IToken> tokens = new List<IToken>();

       while (tokenstream.La(1) != TokenConstants.Eof)
       {                    
                            tokens.Add(tokenstream.Lt(1));
                            tokenstream.Consume();
       }
       foreach (IToken iToken in tokens)
       {
              Console.WriteLine(" Line : {0} Text : {1} ",
                                iToken.Line,
                                iToken.Text                  
                                );
       }
于 2017-11-27T11:15:15.690 回答