antlr-代码分析(7)-listner编写

提取类的方法
g4文件相关部分,类定义和方法定义

classDeclaration
    :   'class' Identifier typeParameters? ('extends' type)?
        ('implements' typeList)?
        classBody
    ;
methodDeclaration
    :   type Identifier formalParameters ('[' ']')* methodDeclarationRest
    |   'void' Identifier formalParameters methodDeclarationRest
    ;

生成如下文件
JavaListener接口、JavaBaseListener类
JavaParser、JavaLexer

JavaParser继承自Parser定义语法规则
JavaLexer继承自Lexer定义词法规则

JavaListener

JavaListener定义了,各个语法的enter和exit方法

void enterClassDeclaration(JavaParser.ClassDeclarationContext ctx);
void exitClassDeclaration(JavaParser.ClassDeclarationContext ctx);

传入参数的各个context,比如ClassDeclarationContext是从JavaParser中定义的;
比如这里的类声明上下文

	public static class ClassDeclarationContext extends ParserRuleContext {
		public TerminalNode Identifier() { return getToken(JavaParser.Identifier, 0); }
		public ClassBodyContext classBody() {
			return getRuleContext(ClassBodyContext.class,0);
		}
		public TypeParametersContext typeParameters() {
			return getRuleContext(TypeParametersContext.class,0);
		}
		public TypeContext type() {
			return getRuleContext(TypeContext.class,0);
		}
		public TypeListContext typeList() {
			return getRuleContext(TypeListContext.class,0);
		}
		public ClassDeclarationContext(ParserRuleContext parent, int invokingState) {
			super(parent, invokingState);
		}
		@Override public int getRuleIndex() { return RULE_classDeclaration; }
		@Override
		public void enterRule(ParseTreeListener listener) {
			if ( listener instanceof JavaListener ) ((JavaListener)listener).enterClassDeclaration(this);
		}
		@Override
		public void exitRule(ParseTreeListener listener) {
			if ( listener instanceof JavaListener ) ((JavaListener)listener).exitClassDeclaration(this);
		}
	}

这里定义了getRuleIndex、enterRule、exitRule三个基本的方法,以及定义数目性的获取方法,比如:Identifier、typeParameters、type、typeList;这里可以参考classDeclaration的定义;
JavaBaseListener是JavaListener接口的实现类,内容都是空,需要用户去覆盖方法;

继承JavaBaseListener

ExtractInterfaceListener保存一个JavaParser,所有的语法解析上下文都从JavaParser中获取;

public class ExtractInterfaceListener extends JavaBaseListener {
    JavaParser parser;
    public ExtractInterfaceListener(JavaParser parser) {this.parser = parser;}
    /** Listen to matches of classDeclaration */
    @Override
    public void enterClassDeclaration(JavaParser.ClassDeclarationContext ctx){
        System.out.println("interface I"+ctx.Identifier()+" {");
    }
    @Override
    public void exitClassDeclaration(JavaParser.ClassDeclarationContext ctx) {
        System.out.println("}");
    }

    /** Listen to matches of methodDeclaration */
    @Override
    public void enterMethodDeclaration(
        JavaParser.MethodDeclarationContext ctx
    )
    {
        // need parser to get tokens
        TokenStream tokens = parser.getTokenStream();
        String type = "void";
        if ( ctx.type()!=null ) {
            type = tokens.getText(ctx.type());
        }
        String args = tokens.getText(ctx.formalParameters());
        System.out.println("\t"+type+" "+ctx.Identifier()+args+";");
    }
}

首先知道这些方法的调用顺序是enterClassDeclaration->enterMethodDeclaration->exitClassDeclaration
enterClassDeclaration方法,获取JavaParser.ClassDeclarationContext,从ClassDeclarationContext中可以提取任何需要的内容

   public void enterClassDeclaration(JavaParser.ClassDeclarationContext ctx){
        System.out.println("interface I"+ctx.Identifier()+" {");
    }

而enterMethodDeclaration中打印内容如下

   public void enterMethodDeclaration(
        JavaParser.MethodDeclarationContext ctx
    )
    {
        // need parser to get tokens
        TokenStream tokens = parser.getTokenStream();
        String type = "void";
        if ( ctx.type()!=null ) {
            type = tokens.getText(ctx.type());
        }
        String args = tokens.getText(ctx.formalParameters());
        System.out.println("\t"+type+" "+ctx.Identifier()+args+";");
    }

获取context的内容通过从tokens中获取,tokens.getText(ctx.type())读取的是节点信息;
如果获取ClassDeclarationContext的节点text就是所有的类定义;

main

完整的listner如下

   public static void main(String[] args) throws Exception {
        String inputFile = "D:\\code\\zsh_demo\\zsh-demo-data\\ANTLR\\src\\main\\java\\jparse\\Demo.java";
        InputStream is = System.in;
        if ( inputFile!=null ) {
            is = new FileInputStream(inputFile);
        }
		//获取lexer、tokens、parser
        ANTLRInputStream input = new ANTLRInputStream(is);
        JavaLexer lexer = new JavaLexer(input);	
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        JavaParser parser = new JavaParser(tokens);
		//通过parser获取tree
        ParseTree tree = parser.compilationUnit(); // parse
		//创建系统walker
        ParseTreeWalker walker = new ParseTreeWalker(); // create standard walker
		//创建listner
        ExtractInterfaceListener extractor = new ExtractInterfaceListener(parser);
		//工作
        walker.walk(extractor, tree); // initiate walk of tree with listener
    }
posted @ 2016-12-26 12:06  zhangshihai1232  阅读(511)  评论(0)    收藏  举报