java - 使用 Antlr 获取标识符和函数名

标签 java c antlr

我正在尝试使用和理解 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没写好,或者identifierList不是我要听的……真的不知道。抱歉,我什至没有理解我的输出,为什么会出现词法错误?:

line 3:4 mismatched input '(' expecting {<EOF>, ','}
main
(
)
{
int
i
=
0
;
}

如您所见,我对此很困惑。有人可以帮我吗?请...

最佳答案

用这一行:

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]

关于java - 使用 Antlr 获取标识符和函数名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23305232/

相关文章:

java - 是否有可能使 Eclipse 生成 hashCode 和等于 HashCodeBuilder 和 EqualsBuilder

java - 保护 Restful api 调用

java - PlayN声音: Requested buffer too large

c - 在循环中,读取的不同字符串最终会被重复为同一字符串

tree - ANTLR 复制一棵树

c - if 语句不适用于我的语法

c# - ANTLR:如何避免在用户修改文本时重新解析整个文件

Java将一个数组放入另一个数组中

c - 在 C 中,如果我的函数出现 longjmp "passes through",有什么方法可以清理吗?

c - 向用户读入字符串,直到使用 "."