有没有办法用 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>'
你好,我目前正尝试在 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>'