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 + -
显示快捷键?