访问ANTLR 4中的信道并分别对其进行解析
本文关键字:ANTLR 信道 访问 | 更新日期: 2023-09-27 18:30:03
我在ANTLR 4中的一个单独通道中包含了我的评论。就我而言,是第二频道。
这是我的lexer语法。
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中的所有标记,并使用注释语法对其进行解析,以将所有注释添加到列表(IReadOnly<CommentContext>
)中,这样我就可以迭代其中的每一个,并访问诸如开始行、开始列、结束行-结束列和标记文本等信息。
CommonTokenStream tokens = new CommonTokenStream(lexer,2);
这不会给我通道2中的令牌。我发现的另一件事是,直到这些令牌作为参数传递给解析器结构XParser parser = new XParser(tokens);
然后只有我可以通过调用GetTokens()
来访问令牌。在令牌中,我可以看到有被标识为令牌的注释,并且在通道2中。即使CommentTokenStrem
物种的通道数量如上所述。它包含所有的令牌。
在使用令牌创建解析器对象之前无法访问令牌的原因是什么?
我想在通道2中获得一个
CommentTokenStrem
,并将传递给XParser对象创建,以使用我的comment
语法解析这些令牌。在ANTLR 4 API中,最好的方法是什么?
CommonTokenStream
内部跟踪任何通道的所有令牌。调用getTokens()
时,唯一看不到的是执行-> skip
操作的lexer规则(甚至没有为这些规则创建令牌)。
您可以使用TokenStream.LT
和IntStream.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();
}
这个怎么样:
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();
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
);
}
或者,您可以将所有其他令牌放在另一个通道中,并使用解析器的默认通道。
当然,如果您有两个解析器在不同的通道中期望令牌,那么这将不起作用。