首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否有方法按照ANTLR的顺序提取令牌?

是否有方法按照ANTLR的顺序提取令牌?
EN

Stack Overflow用户
提问于 2022-01-13 18:48:52
回答 1查看 332关注 0票数 2

嗨,我目前正试图从C#中的ANTLR中提取所有令牌,我使用的是Antlr4.CodeGenerator和Antlr4.Runtime包。

我想要他们的结构,我可以操纵他们,改变他们的内容,等等。我尝试过使用侦听器和访问者,但没有得到任何结果,所以我的意图是在列表中构造包含其内容、规则和令牌来源的对象。我的解析器正在正确地验证输入。

我试过使用MyLanguageLexer.GetAllTokens(),但它返回为空。在执行CommonTokenStream.GetTokens()之后,它也尝试使用.Fill(),它只返回最后找到的令牌,即EOF,但我无法找出原因。

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

这是我的自定义解析类,它当前返回解析树,我的目标是作为构建令牌的结构返回。

代码语言:javascript
复制
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;
    }
}

这是我的雷克萨斯:

代码语言:javascript
复制
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] | ' ')+ '}';

这是我的解析器:

代码语言:javascript
复制
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;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-13 19:50:47

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

代码语言:javascript
复制
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}'");
}

其中的指纹:

代码语言:javascript
复制
Parse tree: (root (expression (expression 1) + (expression 2)) <EOF>)

Tokens:
  NUMBER          '1'
  OPERATOR        '+'
  NUMBER          '2'
  EOF             '<EOF>'
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70701595

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档