parser.java

来自「linux下建立JAVA虚拟机的源码KAFFE」· Java 代码 · 共 1,004 行 · 第 1/2 页

JAVA
1,004
字号
		&& source[index+3]=='t'		&& source[index+4]=='i'		&& source[index+5]=='c') {	       for (index+=6; index<source.length && Parser.WHITESPACE.indexOf(source[index])>=0; ++index)		  ;	       if (index<source.length && source[index]=='{')		  return index+1;	       else		  return -1;	    }	 }	 return -1;      }   }   class ClassComponent extends SourceComponent {      int match(char[] source, int index) {	 boolean isClass=false;	 for (; index<source.length && !isClass; ++index) {	    switch (source[index]) {            case '/':  // possible comment               if (index<source.length-1) {                  char c = source[index+1];                  if ('/' == c) {                     index += 2;                     while (index<source.length && source[index]!=10) {                        ++ index;                     }                  }                  else if ('*' == c) {                     index += 3;                     while (index<source.length && (source[index-1] != '*' || source[index]!='/')) {                        ++ index;                     }                  }               }               break;	    case '=':  // field	    case ';':  // field	    case '(':  // function	       return -1;	    case '{':	       isClass=true;	       break;	    }	    if (isClass) break;	 }	 if (!isClass || index>=source.length)	    return -1;	 return index+1;      }      int process(Parser parser, char[] source, int startIndex, int endIndex) throws ParseException, IOException {	 parser.classOpened(source, startIndex, endIndex);	 if (parser.getAddComments())	    parser.ctx.classDoc.setRawCommentText(parser.getLastComment());	 parser.setLastComment(null);	 int rc=parser.parse(source, endIndex, parser.getClassLevelComponents());	 return rc;      }   }public class Parser {   static int skipExpression(char[] source, int endIndex, int level, char delimiter) throws ParseException {      int orgEndIndex=endIndex;      final int STATE_NORMAL=1;      final int STATE_STARC=2;      final int STATE_SLASHC=3;      final int STATE_CHAR=4;      final int STATE_STRING=5;      int state=STATE_NORMAL;      int prev=0;      for (; !((level==0 && state==STATE_NORMAL && (delimiter=='\0' || source[endIndex]==delimiter))) && endIndex<source.length; ++endIndex) {	 int c=source[endIndex];	 if (state==STATE_NORMAL) {	    if (c=='}') --level;	    else if (c=='{') ++level;	    else if (c=='/' && prev=='/') { state=STATE_SLASHC; c=0; }	    else if (c=='*' && prev=='/') { state=STATE_STARC; c=0; }	    else if (c=='\'' && prev!='\\') { state=STATE_CHAR; c=0; }	    else if (c=='\"' && prev!='\\') { state=STATE_STRING; c=0; }	 }	 else if (state==STATE_SLASHC) {	    if (c=='\n') state=STATE_NORMAL;	 }	 else if (state==STATE_CHAR) {	    if (c=='\'' && prev!='\\') state=STATE_NORMAL;	    else if (c=='\\' && prev=='\\') c=0;	 }	 else if (state==STATE_STRING) {	    if (c=='\"' && prev!='\\') state=STATE_NORMAL;	    else if (c=='\\' && prev=='\\') c=0;	 }	 else {	    if (c=='/' && prev=='*') { state=STATE_NORMAL; c=0; }	 }	 prev=c;      }      if (level>0)	 throw new ParseException("Unexpected end of source.");      else {	 String rc=new String(source, orgEndIndex, endIndex-orgEndIndex);	 return endIndex;      }   }   private boolean addComments = false;   public boolean getAddComments()   {      return this.addComments;   }   public static final String WHITESPACE=" \t\r\n";   public static final boolean isWhitespace(char c) {      return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '');      //return WHITESPACE.indexOf(c)>=0;    }   private int currentLine;   static char[] loadFile(final File file, String encoding)       throws IOException    {      InputStream in = new FileInputStream(file);      NotifyingInputStreamReader notifyingInput         = new NotifyingInputStreamReader(in, encoding);      notifyingInput.addMalformedInputListener(new MalformedInputListener() {            public void malformedInputEncountered(MalformedInputEvent event) {               Main.getRootDoc().printWarning("Illegal character in file " + file + ", line " + event.getLineNumber() + ", column " + event.getColumnNumber());               try {                  Main.getRootDoc().printWarning(IOToolkit.getLineFromFile(file, event.getLineNumber()));                  Main.getRootDoc().printWarning(IOToolkit.getColumnDisplayLine(event.getColumnNumber()));               }               catch (IOException ignore) {               }            }         });      Reader reader         = new BufferedReader(notifyingInput);      char[] result = IOToolkit.readFully(reader);      reader.close();      return result;   }   private SourceComponent[] sourceLevelComponents;   private SourceComponent[] classLevelComponents;   public SourceComponent[] getClassLevelComponents()   {      return this.classLevelComponents;   }   public Parser() {      try {	 sourceLevelComponents=new SourceComponent[] {	    new Whitespace(),	    new CommentComponent(),	    new SlashSlashCommentComponent(),	    new PackageComponent(),	    new EmptyStatementComponent(),	    new ImportComponent(),	    new ClassComponent(),	 };	 classLevelComponents=new SourceComponent[] {	    new Whitespace(),	    new BracketClose(),	    new CommentComponent(),	    new SlashSlashCommentComponent(),	    new FunctionComponent(),	    new StaticBlockComponent(),	    new ImportComponent(),	    new ClassComponent(),	    new FieldComponent(),	 };      }      catch (Exception e) {	 e.printStackTrace();      }   }   public int getNumberOfProcessedFiles() {      return processedFiles.size();   }   static Set processedFiles = new HashSet();   ClassDocImpl processSourceFile(File file, boolean addComments,                                   String encoding, String expectedPackageName)       throws IOException, ParseException   {      this.currentFile = file;      this.currentPackage = null;      this.currentPackageName = null;      this.expectedPackageName = expectedPackageName;      this.outerClass = null;      this.boilerplateComment = null;      this.addComments=addComments;      if (processedFiles.contains(file)) {         return null;      }      processedFiles.add(file);               Debug.log(1,"Processing file "+file);            contextStack.clear();      ctx=null;      importedClassesList.clear();      importedStringList.clear();      importedPackagesList.clear();      importedStatementList.clear();            currentLine = 1;      char[] source = loadFile(file, encoding);      try {         parse(source, 0, sourceLevelComponents);         ClassDoc[] importedClasses=(ClassDoc[])importedClassesList.toArray(new ClassDoc[0]);         PackageDoc[] importedPackages=(PackageDoc[])importedPackagesList.toArray(new PackageDoc[0]);                  if (Main.DESCEND_IMPORTED) {            for (int i=0; i<importedClasses.length; ++i) {               Main.getRootDoc().scheduleClass(currentClass, importedClasses[i].qualifiedName());            }         }                /*           if (contextStack.size()>0) {           Debug.log(1,"-->contextStack not empty! size is "+contextStack.size());           }         */           return outerClass;      }      catch (IgnoredFileParseException ignore) {         return null;      }   }         int parse(char[] source, int index, SourceComponent[] componentTypes) throws ParseException, IOException {      while (index<source.length) {	 int match=-1;	 int i=0;	 for (; i<componentTypes.length; ++i) {	    if ((match=componentTypes[i].match(source, index))>=0) {	       //Debug.log(9,componentTypes[i].getClass().getName()+" ("+match+"/"+source.length+")");	       break;	    }	 }	 if (i<componentTypes.length) {	    int endIndex=componentTypes[i].getEndIndex(source, match);	    	    index=componentTypes[i].process(this, source, index, endIndex);	    if (index<0) {	       //Debug.log(9,"exiting parse because of "+componentTypes[i].getClass().getName()+" (\""+new String(source, index, endIndex-index)+"\")");	       return endIndex;	    }	 }	 else {	    //Debug.log(9,"index="+index+", source.length()="+source.length);	    throw new ParseException("unmatched input in line "+currentLine+": "+new String(source, index, Math.min(50,source.length-index)));	 }      }      //Debug.log(9,"exiting parse normally, index="+index+" source.length="+source.length);      return index;   }   private static int countNewLines(String source) {      int i=0;      int rc=0;      while ((i=source.indexOf('\n',i)+1)>0) 	 ++rc;      return rc;   }   public void processSourceDir(File dir, String encoding, String expectedPackageName)       throws IOException, ParseException    {      Debug.log(9,"Processing "+dir.getParentFile().getName()+"."+dir.getName());      File[] files=dir.listFiles();      if (null!=files) {	 for (int i=0; i<files.length; ++i) {	    if (files[i].getName().toLowerCase().endsWith(".java")) {	       processSourceFile(files[i], true, encoding, expectedPackageName);	    }	 }      }   }   void classOpened(char[] source, int startIndex, int endIndex) throws ParseException, IOException {      referencedClassesList.clear();      if (null == currentPackage) {         if (expectedPackageName != null) {            if (null == currentPackageName ||                !currentPackageName.equals(expectedPackageName)) {               Main.getRootDoc().printWarning("Ignoring file " + currentFile + ": (wrong package, " + currentPackageName + "!=" + expectedPackageName + ")");               throw new IgnoredFileParseException();            }         }         if (null != currentPackageName) {            currentPackage = Main.getRootDoc().findOrCreatePackageDoc(currentPackageName);         }         else {            currentPackage = Main.getRootDoc().findOrCreatePackageDoc("");         }      }      if (currentPackageName != null)	 importedStatementList.add(currentPackageName + ".*");      importedStatementList.add("java.lang.*");      ClassDocImpl classDoc	 = ClassDocImpl.createInstance((ctx!=null)?(ctx.classDoc):null, currentPackage, 				       null,				       (PackageDoc[])importedPackagesList.toArray(new PackageDoc[0]),				       source, startIndex, endIndex,                                       importedStatementList);      if (ctx != null) {         ctx.innerClassesList.add(classDoc);         if (classDoc.isIncluded()) {            ctx.filteredInnerClassesList.add(classDoc);         }      }      if (importedClassesList.isEmpty()) {	 for (Iterator it=importedStringList.iterator(); it.hasNext(); ) {	    importedClassesList.add(new ClassDocProxy((String)it.next(), classDoc));	 }      }      classDoc.setImportedClasses((ClassDoc[])importedClassesList.toArray(new ClassDoc[0]));      currentPackage.addClass(classDoc);      currentClass = classDoc;      if (null == outerClass) {         outerClass = classDoc;      }      if (classDoc.superclass()!=null)	 referencedClassesList.add(classDoc.superclass());      //Debug.log(9,"classOpened "+classDoc+", adding superclass "+classDoc.superclass());      contextStack.push(ctx);      ctx=new Context(classDoc);      //Debug.log(9,"ctx="+ctx);   }   private Doc[] toArray(List list, Doc[] template)   {      Doc[] result = (Doc[])list.toArray(template);      return result;   }   void classClosed() throws ParseException, IOException {      ctx.classDoc.setFields((FieldDoc[])toArray(ctx.fieldList,                                                              new FieldDoc[0]));      ctx.classDoc.setFilteredFields((FieldDoc[])toArray(ctx.filteredFieldList,                                                                      new FieldDoc[0]));      ctx.classDoc.setSerializableFields((FieldDoc[])toArray(ctx.sfieldList, new FieldDoc[0]));      ctx.classDoc.setMethods((MethodDoc[])toArray(ctx.methodList, new MethodDoc[0]));      ctx.classDoc.setFilteredMethods((MethodDoc[])toArray(ctx.filteredMethodList, new MethodDoc[0]));      ctx.classDoc.setMaybeSerMethodList(ctx.maybeSerMethodList);      ctx.classDoc.setConstructors((ConstructorDoc[])toArray(ctx.constructorList, new ConstructorDoc[0]));      ctx.classDoc.setFilteredConstructors((ConstructorDoc[])toArray(ctx.filteredConstructorList, new ConstructorDoc[0]));      ctx.classDoc.setInnerClasses((ClassDocImpl[])toArray(ctx.innerClassesList, new ClassDocImpl[0]));      ctx.classDoc.setFilteredInnerClasses((ClassDocImpl[])toArray(ctx.filteredInnerClassesList, new ClassDocImpl[0]));      ctx.classDoc.setBoilerplateComment(boilerplateComment);      Main.getRootDoc().addClassDoc(ctx.classDoc);            if (Main.DESCEND_INTERFACES) {	 for (int i=0; i<ctx.classDoc.interfaces().length; ++i) {	    Main.getRootDoc().scheduleClass(ctx.classDoc, ctx.classDoc.interfaces()[i].qualifiedName());	 }      }      //Debug.log(9,"classClosed: "+ctx.classDoc);      ctx=(Context)contextStack.pop();      ClassDoc[] referencedClasses=(ClassDoc[])referencedClassesList.toArray(new ClassDoc[0]);      if (Main.DESCEND_SUPERCLASS) {	 for (int i=0; i<referencedClasses.length; ++i) {	    Main.getRootDoc().scheduleClass(currentClass, referencedClasses[i].qualifiedName());	 }      }   }      Context      ctx             = null;   Stack        contextStack    = new Stack();   class Context {      Context(ClassDocImpl classDoc) { this.classDoc=classDoc; }      ClassDocImpl      classDoc                 = null;      List	        fieldList                = new LinkedList();      List	        filteredFieldList        = new LinkedList();      List	        sfieldList               = new LinkedList();      List	        methodList               = new LinkedList();      List	        filteredMethodList       = new LinkedList();      List              maybeSerMethodList       = new LinkedList();      List	        constructorList          = new LinkedList();      List	        filteredConstructorList  = new LinkedList();      List              innerClassesList         = new LinkedList();      List              filteredInnerClassesList = new LinkedList();   }      File currentFile = null;   String lastComment = null;   String expectedPackageName = null;   String currentPackageName = null;   PackageDocImpl currentPackage = null;   ClassDocImpl currentClass = null;   ClassDocImpl outerClass   = null;   List ordinaryClassesList  = new LinkedList();   List allClassesList       = new LinkedList();   List interfacesList       = new LinkedList();   List importedClassesList  = new LinkedList();   List importedStringList   = new LinkedList();   List importedPackagesList = new LinkedList();   List importedStatementList = new LinkedList();   List referencedClassesList = new LinkedList();   String boilerplateComment = null;   void packageOpened(String packageName) {      currentPackageName = packageName;   }      void importEncountered(String importString) throws ParseException, IOException {      //Debug.log(9,"importing '"+importString+"'");      importedStatementList.add(importString);      if (importString.endsWith(".*")) {	 importedPackagesList.add(Main.getRootDoc().findOrCreatePackageDoc(importString.substring(0,importString.length()-2)));      }      else {	 importedStringList.add(importString);      }   }   void setLastComment(String lastComment) {      this.lastComment=lastComment;   }   String getLastComment() {      return this.lastComment;   }   void setBoilerplateComment(String boilerplateComment)   {      this.boilerplateComment = boilerplateComment;   }   String getBoilerplateComment()   {      return boilerplateComment;   }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?