使用openjdk的语法解析器(Parser)解析java源代码

来源:互联网 发布:淘宝网丝巾大全 编辑:程序博客网 时间:2024/05/14 23:44

   jsr269提供annotation processor,允许我们在编译器编译过程中挂钩子。http://projectlombok.org/ 的许多功能正是基于此实现。

    但有时候可能需要解析语法正确,但没有语义的Java文件(比如对工程中的单个java源文件的方法等元素建索引),这个时候jsr269就不能满足需求了。此时,我们只要语法树(ast)就可以了,也就是说不需要编译通过,只需要语法解析,可选的parser我找到了3个:

 

-- antlr parser

-- eclipse jdt parser

-- javac parser

 

下面一个例子使用javac parser来获得ast,并采用visitor模式遍历整颗语法树,提取文件中的所有方法。

注意:

     需要在classpath中引入jdk的tools.jar

     很多类不属于标准api,目前只在openjdk6,7上做过测试

 

Java代码  收藏代码
  1. package org.jilen;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.io.IOException;  
  5. import java.nio.ByteBuffer;  
  6. import java.nio.channels.FileChannel;  
  7. import java.nio.channels.FileChannel.MapMode;  
  8. import java.nio.charset.Charset;  
  9. import java.util.ArrayList;  
  10. import java.util.List;  
  11.   
  12. import com.sun.source.tree.MethodTree;  
  13. import com.sun.source.util.TreeScanner;  
  14. import com.sun.tools.javac.file.JavacFileManager;  
  15. import com.sun.tools.javac.parser.Parser;  
  16. import com.sun.tools.javac.parser.ParserFactory;  
  17. import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;  
  18. import com.sun.tools.javac.util.Context;  
  19.   
  20. public class JDKParser {  
  21.     private ParserFactory factory;  
  22.   
  23.     public JDKParser() {  
  24.         factory = getParserFactory();  
  25.     }  
  26.   
  27.     public List<String> parseMethodDefs(String file) throws IOException {  
  28.         JCCompilationUnit unit = parse(file);  
  29.         MethodScanner scanner = new MethodScanner();  
  30.         return scanner.visitCompilationUnit(unit, new ArrayList<String>());  
  31.   
  32.     }  
  33.   
  34.     JCCompilationUnit parse(String file) throws IOException {  
  35.         Parser parser = factory.newParser(readFile(file), truefalsetrue);  
  36.         return parser.parseCompilationUnit();  
  37.     }  
  38.   
  39.     private ParserFactory getParserFactory() {  
  40.         Context context = new Context();  
  41.         JavacFileManager.preRegister(context);  
  42.         ParserFactory factory = ParserFactory.instance(context);  
  43.         return factory;  
  44.     }  
  45.   
  46.     CharSequence readFile(String file) throws IOException {  
  47.         FileInputStream fin = new FileInputStream(file);  
  48.         FileChannel ch = fin.getChannel();  
  49.         ByteBuffer buffer = ch.map(MapMode.READ_ONLY, 0, ch.size());  
  50.         return Charset.defaultCharset().decode(buffer);  
  51.     }  
  52.       
  53.     //扫描方法时,把方法名加入到一个list中  
  54.     static class MethodScanner extends  
  55.             TreeScanner<List<String>, List<String>> {  
  56.         @Override  
  57.         public List<String> visitMethod(MethodTree node, List<String> p) {  
  58.             p.add(node.getName().toString());  
  59.             return p;  
  60.         }  
  61.     }  
  62.   
  63.     public static void main(String[] args) throws IOException {  
  64.         JDKParser parser = new JDKParser();  
  65.         for (String method : parser.parseMethodDefs("User.java")) {  
  66.             System.out.println(method);  
  67.         }  
  68.     }  
  69. }  

 

1.parser.parseCompilationUnit();获得语法树

2.MethodScanner扫描整颗语法树,整个扫面其实是fold/reduce过程


http://jilen.iteye.com/blog/1479632

原创粉丝点击