理解 ANTLR4 代币

St.*_*rio 0 java token lexer antlr4

我对 ANTLR 很Token陌生,我试图了解ATNLR4 中到底是什么。考虑以下非常荒谬的语法:

grammar Tst;

init: A token=('+'|'-') B;

A: .+?;
B: .+?;
ADD: '+';
SUB: '-';
Run Code Online (Sandbox Code Playgroud)

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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

现在,所有词法分析器规则都可用作解析器类中的静态常量:

public static final int A=1, B=2, ADD=3, SUB=4;
Run Code Online (Sandbox Code Playgroud)

我们如何使用它们来识别词法分析器规则?所有ABADD规则可能匹配'+'。那么在测试时我应该使用什么类型。

我的意思是:

TstParser.InitContext ctx;
//...
ctx.token.getType() == //What type?
                       //TstParse.A
                       //TstParse.B
                       //or
                       //TstParse.ADD?
Run Code Online (Sandbox Code Playgroud)

一般来说,我想了解如何ANTLR4知道 a 的类型Token

Div*_*ero 5

我将尝试向您介绍解析的过程。该过程有两个阶段。词法分析器部分(创建令牌的地方)和解析器部分。(这就是解析表达式的来源——如果我们谈论的是一般的解析,那就不是很精确了)。您在此过程中要做的就是了解输入,同时可能创建输入模型。为了缓解这种情况,工作通常分为更小的步骤。理解主要表示为“单词”的标记(输入的元素比字符大一些)要容易得多。(准确地说是关键字、变量、文字)。

因此,您要做的第一步是以字符流的形式将输入预处理为 TOKENS。关于代币,您只能说与它相关的价值是什么以及它是什么类型的代币。例如在非常简单的计算器输入“2+3*9” '2' 表示值 2 的数字标记,'+' 表示值 '+' 的运算符标记等等......词法分析器部分的结果是标记流. 可以想象,词法分析器和解析器规则非常相似。第一步处理字符,第二步处理标记。

关于 ANTLR(许多其他生成器的工作方式相同),有一个关于词法分析器的重要规则。您不能对不同的令牌使用相同的规则。因此,您插入的语法将不起作用,因为词法分析器部分在 A 和 B 之间不能不同。您可以对双方使用相同的标记名称。你以后会照顾它。

为什么词法分析器规则不能相同?当词法分析器处理输入时,它会遍历流。它尝试它找到的第一个词法分析器规则,如果没有问题,它将应用它。因此,如果还有另一条规则也适用,嗯,真是太可惜了。它不会有机会。解析器在 ANTLR 中比词法分析器大得多。

把它们加起来。令牌是词法分析器的产物,它们是一个或多个字符的组,应该作为一个单元呈现给下一步。我们正在谈论变量名、运算符、函数名等。