antlr4:令牌未被识别为预期的

antlr4:令牌未被识别为预期的,antlr4,Antlr4,我正在尝试使用antlr4构建一个语法,它应该能够将中间解析结果存储为变量,以便以后使用。我考虑使用一个关键字,比如as(或者德语als),它将触发此存储功能。除此之外,我还有一个通用令牌ID,它将匹配任何可能的标识符。 存储能力应该是用户的选择。因此,我使用的是?在我的语法定义中 我的语法如下: grammar TokenTest; @header { package some.package.declaration; } AS : 'als' ; VALUE_ASSIGNMENT : A

我正在尝试使用antlr4构建一个语法,它应该能够将中间解析结果存储为变量,以便以后使用。我考虑使用一个关键字,比如as(或者德语als),它将触发此存储功能。除此之外,我还有一个通用令牌ID,它将匹配任何可能的标识符。 存储能力应该是用户的选择。因此,我使用的是?在我的语法定义中

我的语法如下:

grammar TokenTest;

@header {
package some.package.declaration;
}

AS : 'als' ;
VALUE_ASSIGNMENT : AS ID ;

ID : [a-zA-Z_][a-zA-Z0-9_]+ ;

WS : [ \t\n\r]+ -> skip ;

ANY : . ;

formula  :  identifier=ID (variable=VALUE_ASSIGNMENT)?  #ExpressionIdentifier
;
fragment AS : 'als' ;
编译此语法时没有失败。但是,当我尝试应用以下TestNG测试时,我无法解释其行为:

package some.package.declaration;

import java.util.List;

import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Token;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import some.package.declaration.TokenTestLexer;

public class TokenTest {

    private static List<Token> getTokens(final String input) {
        final TokenTestLexer lexer = new TokenTestLexer(CharStreams.fromString(input));
        final CommonTokenStream tokens = new CommonTokenStream(lexer);
        tokens.fill();
        return tokens.getTokens();
    }

    @DataProvider (name = "tokenData")
    public Object[][] tokenData() {
        return new Object [][] {
            {"result", new String[] {"result"}, new int[] {TokenTestLexer.ID}},
            {"als", new String[] {"als"}, new int[] {TokenTestLexer.AS}},
            {"result als x", new String[] {"result", "als", "x"}, new int[] {TokenTestLexer.ID, TokenTestLexer.AS, TokenTestLexer.ID}},
        };
    }

    @Test (dataProvider = "tokenData")
    public void testTokenGeneration(final String input, final String[] expectedTokens, final int[] expectedTypes) {
//      System.out.println("test token generation for <" + input + ">");
        Assert.assertEquals(expectedTokens.length, expectedTypes.length);
        final List<Token> parsedTokens = getTokens(input);
        Assert.assertEquals(parsedTokens.size()-1/*EOF is a token*/, expectedTokens.length);
        for (int index = 0; index < expectedTokens.length; index++) {
            final Token currentToken = parsedTokens.get(index);
            Assert.assertEquals(currentToken.getText(), expectedTokens[index]);
            Assert.assertEquals(currentToken.getType(), expectedTypes[index]);
        }
    }

}
还有一种奇怪的行为。当然,第二个测试用例不再工作,因为不再有AS-标记。这并不奇怪。相反,第三个测试用例中的x将被识别为任何标记。但是,我假设整个“als x”序列是一个赋值-标记。我做错了什么?任何帮助都会很好

亲切的问候

但是,第三个测试没有按预期进行。我假设它是一个ID令牌,后跟一个AS令牌,最后后跟一个ID令牌。但是,最后一个令牌将被识别为任意令牌

这是因为您定义了:

ID : [a-zA-Z_][a-zA-Z0-9_]+ ;
其中,
+
表示“一个或多个”。您可能想要的是“零或更多”:

但是,我假设整个“ALSx”-序列是一个赋值标记。我做错了什么

请注意,在解析器规则中跳过空格,而不是lexer规则。这意味着
VALUE\u赋值
将只匹配
alsFOO
,而不匹配
alsFOO
。此规则可能应该是解析器规则:

value_assignment : AS ID ;
但是,第三个测试没有按预期进行。我假设它是一个ID令牌,后跟一个AS令牌,最后后跟一个ID令牌。但是,最后一个令牌将被识别为任意令牌

这是因为您定义了:

ID : [a-zA-Z_][a-zA-Z0-9_]+ ;
其中,
+
表示“一个或多个”。您可能想要的是“零或更多”:

但是,我假设整个“ALSx”-序列是一个赋值标记。我做错了什么

请注意,在解析器规则中跳过空格,而不是lexer规则。这意味着
VALUE\u赋值
将只匹配
alsFOO
,而不匹配
alsFOO
。此规则可能应该是解析器规则:

value_assignment : AS ID ;

好的第一个问题:清晰的问题描述,观察到的和预期的行为。和一个小语法来复制它。希望所有的问题都比你的好一半:拇指支持:好的第一个问题:清晰的问题描述,观察到的和预期的行为。和一个小语法来复制它。希望所有的问题都能比你的一半好:拇指支持:谢谢你,解析程序和词法程序之间的空白跳跃差异对我来说是全新的。现在,我可以更好地理解细节了。谢谢,解析器和词法分析器之间的这种空白跳跃的差异对我来说是全新的。现在,我可以更好地理解细节了。