我有一个基于 ANTLR 4 并使用侦听器而不是访问者的解析器。它已经识别并存储了函数、变量等的声明。
我正在尝试使用语义谓词解决一些语法歧义,例如在解析 VHDL 源代码时将函数调用与数组/向量访问分开。这对于避免完整语法的进一步复杂化很重要。
在以下示例中:
3 + j * f(i)
f(i)
可以是f
带参数的函数,也可以是由 index 访问i
的数组。下面的简化示例显示了谓词如何帮助解决这种歧义:f
i
expression:
expression OPERATOR expression | simple_expression;
simple_expression:
function_expression | array_expression | ID | NUMBER;
function_expression:
{is_function()}? ID '(' expression_list ')';
array_expression:
{is_array()}? ID '(' expression ')';
expression_list:
expression ( ',' expression )*;
侦听器解析声明并将函数和数组标识符存储在数据库中,这允许知道标识符ID
是函数、数组还是未声明的(为了简单起见,我没有在此处显示这些声明的任何语法示例)。
谓词的一个例子是,在语法文件的顶部:
@parser::members {
Definitions defs;
boolean is_function() {
return defs.isFunction(getCurrentToken().getText());
}
boolean is_array() {
return defs.isArray(getCurrentToken().getText());
}
}
但是,我不能在谓词中使用该信息,因为在调用声明的侦听器来构建 ID 数据库之前,它们被调用得太早。如果我System.out.print
在这些函数中以及在侦听器中添加 a,我会看到
- 表达式谓词首先在被解析的整个文件上调用,
- 然后才调用所有声明侦听器,即使声明在文件中的这些表达式之前也是如此。
我知道解析器正在向前看,但是有没有办法尽快加快声明侦听器的速度,以便为与文件其余部分中的表达式相关的谓词准备好它们的信息?
或者这是使用谓词的错误方式?我想尽可能避免语法中的源代码,例如在解析声明期间存储初步信息的解决方法,其中嵌入了语法文件中的代码。2-pass 解析器似乎有点尴尬。