我试图使用和理解AntLR,这对我来说是新的。我的目的是读取用C编写的源代码文件,并从中提取标识符(变量和函数名称)。
在我的C语法(文件 C.g4 )中考虑:
identifierList
: Identifier
| identifierList Comma Identifier
;
Identifier
: IdentifierNondigit
( IdentifierNondigit
| Digit
)*
;
生成解析器和监听器后,我创建了自己的标识符监听器。
请注意,MyCListener类扩展了CBaseListener:
public class MyCListener extends CBaseListener {
@Override
public void enterIdentifierList(CParser.IdentifierListContext ctx) {
List<ParseTree> children = ctx.children;
for (ParseTree parseTree : children) {
System.out.println(parseTree.getText());
}
}
然后我在主要课程中有这个:
String fileurl = "C:/example.c";
CLexer lexer;
try {
lexer = new CLexer(new ANTLRFileStream(fileurl));
CommonTokenStream tokens = new CommonTokenStream(lexer);
CParser parser = new CParser(tokens);
CParser.IdentifierListContext identifierContext = parser.identifierList();
ParseTreeWalker walker = new ParseTreeWalker();
MyCListener listener = new MyCListener();
walker.walk(listener, identifierContext);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
其中example.c是:
int main() {
// this is C
int i=0; // i is int
/* double j=0.0;
C
*/
}
我做错了什么? 也许我没有正确地编写MyCListener,或者标识符列表不是我需要听的...真的不知道。对不起,但我甚至不理解我的输出,为什么会出现词汇错误?:
line 3:4 mismatched input '(' expecting {<EOF>, ','}
main
(
)
{
int
i
=
0
;
}
如您所见,我对此非常困惑。有人能帮助我吗?请...
答案 0 :(得分:3)
这一行:
CParser.IdentifierListContext identifierContext = parser.identifierList();
您尝试将整个输入解析为identifierList
。但你的意见并非如此。
假设您正在使用C.g4
from the ANTLR4 Github repository,请尝试让解析器从语法的入口点开始(这是规则compilationUnit
):
MyCListener listener = new MyCListener();
ParseTreeWalker.DEFAULT.walk(listener, parser.compilationUnit());
这是一个快速演示:
public class Main {
public static void main(String[] args) throws Exception {
final List<String> identifiers = new ArrayList<String>();
String source = "int main() {\n" +
"\n" +
"// this is C\n" +
"\n" +
" int i=0; // i is int\n" +
" /* double j=0.0;\n" +
" C\n" +
" */\n" +
"}";
CLexer lexer = new CLexer(new ANTLRInputStream(source));
CParser parser = new CParser(new CommonTokenStream(lexer));
ParseTreeWalker.DEFAULT.walk(new CBaseListener(){
@Override
public void enterDirectDeclarator(@NotNull CParser.DirectDeclaratorContext ctx) {
if (ctx.Identifier() != null) {
identifiers.add(ctx.Identifier().getText());
}
}
// Perhaps override other rules that use `Identifier`
}, parser.compilationUnit());
System.out.println("identifiers -> " + identifiers);
}
}
会打印:
identifiers -> [main, i]