有没有办法用 ANTLR 按顺序提取令牌?

Is there a way to extract tokens in order with ANTLR?

你好,我目前正尝试在 C# 中从 ANTLR 中提取所有标记,我正在使用 Antlr4.CodeGenerator 和 Antlr4.Runtime 包。

我希望它们以一种我可以操纵它们、更改它们的内容等的方式构建。我尝试过使用听众和访问者,但没有成功,所以我的目的是用包含内容、规则和令牌来源的对象在列表中构建令牌。我的解析器正在正确验证输入。

我试过使用 MyLanguageLexer.GetAllTokens() 但它 return 是空的。还尝试在执行 .Fill() 后使用 CommonTokenStream.GetTokens(),它只找到 return 找到的最后一个标记是一个 EOF,我不明白为什么。

我可以在 ParseTree 中递归地迭代它们,但这是解决问题的不安全方法,它困扰着我,之前的方法不起作用。

这是我的自定义解析 class,目前 return 是已解析的树,我的 objective 是 return 作为我正在尝试构建的结构代币。

public static class Parser
{
    public static RootContext TryParse(string query)
    {
        var inputStream = new AntlrInputStream(query);
        var lexer = new StatsQueryLexer(inputStream);
        lexer.RemoveErrorListeners();
        lexer.AddErrorListener(new LexerErrorListener());

        var tokenStream = new CommonTokenStream(lexer);
        var parser = new StatsQueryParser(tokenStream);
        parser.RemoveErrorListeners();
        parser.AddErrorListener(new ParserErrorListener());
        parser.BuildParseTree = true;

        var tree = parser.root();

        var tokens = lexer.GetAllTokens();
        return tree;
    }
}

这是我的词法分析器:

lexer grammar StatsQueryLexer;

SPACE: [ \t\r\n]+ -> skip;
NULL_: 'NULL';

L_BRACKET: '(';
R_BRACKET: ')';
NUMBER: [-]? [0-9]+ ('.' [0-9]+)?;
OPERATOR: ('+' | '-' | '*' | '/');
COMPARATOR: ('=' | '!=' | '>' | '<' | '>=' | '<=');

SUM_FN: 'SOMA';
AVG_FN: 'MEDIA';
MAX_FN: 'MAX';
MIN_FN: 'MIN';
COUNT_FN: 'CONTA';
SQL_FN: 'SQL';

IF: 'SE';
THEN: 'RETORNA';
ELSE: 'SENAO';

QUOTE: '`' ([\u0000-\uFFFF])+ '`';
COMMA: ',';
COLUMN: '{' ([a-z] | [A-Z] | [0-9] | ' ')+ '}';

这是我的解析器:

parser grammar StatsQueryParser;

options {
    tokenVocab = StatsQueryLexer;
}

root: el += expression (OPERATOR el += expression)* EOF;

expression:
    NUMBER
    | NULL_
    | aggregateFunction
    | nativeSqlFunction
    | caseElse
    | expression OPERATOR expression
    | L_BRACKET expression R_BRACKET;

aggregateFunction:
    aggregateFunctionPrefix L_BRACKET aggregateFunctionArgs R_BRACKET;

aggregateFunctionArgs:
    NUMBER
    | COLUMN
    | nativeSqlFunction
    | caseElse
    | L_BRACKET aggregateFunctionArgs R_BRACKET;

aggregateFunctionPrefix:
    SUM_FN
    | AVG_FN
    | MAX_FN
    | MIN_FN
    | COUNT_FN;

nativeSqlFunction: SQL_FN L_BRACKET QUOTE R_BRACKET;

caseElse: IF (comparison THEN expression)+ ( ELSE expression)?;

comparison:
    expression COMPARATOR expression
    | L_BRACKET comparison R_BRACKET;

这在我的机器上运行良好(使用 ANTLR 4.9.3 C# 运行时):

const string query = "1 + 2";

var inputStream = new AntlrInputStream(query);
var lexer = new StatsQueryLexer(inputStream);
var tokenStream = new CommonTokenStream(lexer);
tokenStream.Fill();

var parser = new StatsQueryParser(tokenStream)
{
  BuildParseTree = true
};

Console.WriteLine($"Parse tree: {parser.root().ToStringTree(parser)}");
Console.WriteLine("\nTokens:");

foreach (var token in tokenStream.GetTokens())
{
  Console.WriteLine($"  {StatsQueryLexer.DefaultVocabulary.GetSymbolicName(token.Type), -15} '{token.Text}'");
}

打印:

Parse tree: (root (expression (expression 1) + (expression 2)) <EOF>)

Tokens:
  NUMBER          '1'
  OPERATOR        '+'
  NUMBER          '2'
  EOF             '<EOF>'