我对ANTLR很陌生,我试图了解ATNLR4中Token
到底是什么。考虑以下非常荒谬的语法:
grammar Tst;
init: A token=('+'|'-') B;
A: .+?;
B: .+?;
ADD: '+';
SUB: '-';
ANTLR4 为其生成以下TstParser.InitContext
:
public static class InitContext extends ParserRuleContext {
public Token token; //<---------------------------- HERE
public TerminalNode A() { return getToken(TstParser.A, 0); }
public TerminalNode B() { return getToken(TstParser.B, 0); }
public InitContext(ParserRuleContext parent, int invokingState) {
super(parent, invokingState);
}
@Override public int getRuleIndex() { return RULE_init; }
@Override
public void enterRule(ParseTreeListener listener) {
if ( listener instanceof TstListener ) ((TstListener)listener).enterInit(this);
}
@Override
public void exitRule(ParseTreeListener listener) {
if ( listener instanceof TstListener ) ((TstListener)listener).exitInit(this);
}
}
现在,所有词法分析器规则都可以作为解析器类中的静态常量使用:
public static final int A=1, B=2, ADD=3, SUB=4;
我们如何使用它们来识别词法分析器规则?所有A
、B
和ADD
规则都可能与'+'
匹配。那么在测试它时我应该使用什么类型。
我的意思是:
TstParser.InitContext ctx;
//...
ctx.token.getType() == //What type?
//TstParse.A
//TstParse.B
//or
//TstParse.ADD?
一般来说,我想了解ANTLR4
如何知道Token
的类型?
我将尝试向您介绍解析过程。该过程分为两个阶段。词法分析器部分(创建令牌的位置)和解析器部分。 (这就是解析表达式的来源 - 如果我们谈论的是一般的解析,则不是很精确)。您在此过程中要做的只是理解输入,同时可能创建输入的模型。为了缓解这种情况,作业通常分为较小的步骤。主要表示为"单词"的标记(输入元素比字符大一些)更容易理解。(准确地说是关键字,变量,文字)。
因此,您要执行的第一步是以字符流的形式将输入预处理为 TOKENS。关于令牌,您只能说与它相关的价值以及它是哪种令牌。例如,在非常简单的计算器中,输入"2+3*9"2"表示值 2 的数字标记,"+"表示值"+"的运算符 toke,依此类推......词法分析器部分的结果是令牌流。可以想象,词法分析器和解析器规则非常相似。第一步处理字符,第二步处理令牌。
关于ANTLR(许多其他生成器的工作方式相同),关于词法分析器有一个重要的规则。不能对不同的令牌使用相同的规则。因此,您插入的语法不起作用,因为词法分析器部分在 A 和 B 之间不能有所不同。您可以只对双方使用相同的令牌名称。你以后会照顾它。
为什么词法分析器规则不能相同?当词法分析器处理输入时,它会遍历流。它会尝试找到的第一个词法分析器规则,如果没问题,它将应用它。因此,如果有另一条规则也适用,嗯,真是可怜。它不会有机会。解析器在ANTLR中比词法分析器慷慨得多。
总结一下。令牌是词法分析器的产品,它们是一个或多个字符的组,应作为单个单元呈现到下一步。我们正在研究变量名称、运算符、函数名称等。