├── .gitignore
├── .idea
├── .gitignore
├── codeStyles
│ └── codeStyleConfig.xml
├── compiler.xml
├── encodings.xml
├── jarRepositories.xml
├── libraries
│ └── tools.xml
├── misc.xml
├── runConfigurations.xml
└── uiDesigner.xml
├── README.md
├── pom.xml
├── src
└── main
│ └── java
│ └── work
│ └── liziyun
│ ├── Demo03.java
│ ├── LzyJavaCompiler.java
│ ├── ast
│ ├── Express.java
│ ├── LexerBuffer.java
│ ├── LzyExpressParser.java
│ ├── LzyJavacParser.java
│ ├── LzyStatementParser.java
│ ├── Parser.java
│ └── Statement.java
│ ├── code
│ ├── LzyClassFile.java
│ ├── LzyClassReader.java
│ ├── LzyClassWriter.java
│ ├── LzyCode.java
│ ├── LzyPool.java
│ ├── LzyScope.java
│ ├── LzySymtab.java
│ ├── symbol
│ │ ├── LzyClassSymbol.java
│ │ ├── LzyMethodSymbol.java
│ │ ├── LzyPackageSymbol.java
│ │ ├── LzySymbol.java
│ │ ├── LzyTypeSymbol.java
│ │ └── LzyVarSymbol.java
│ └── type
│ │ ├── LzyArrayType.java
│ │ ├── LzyClassType.java
│ │ ├── LzyErrorType.java
│ │ ├── LzyMethodType.java
│ │ ├── LzyPackageType.java
│ │ ├── LzyType.java
│ │ ├── LzyTypeParameter.java
│ │ └── LzyTypeTags.java
│ ├── comp
│ ├── LzyAbsGen.java
│ ├── LzyAttr.java
│ ├── LzyAttrContext.java
│ ├── LzyCheck.java
│ ├── LzyConstFold.java
│ ├── LzyEnter.java
│ ├── LzyEnv.java
│ ├── LzyGen.java
│ ├── LzyInfer.java
│ ├── LzyItems.java
│ ├── LzyMemberEnter.java
│ ├── LzyResolve.java
│ └── LzyTodo.java
│ ├── io
│ └── LzyJavaFile.java
│ ├── jvm
│ └── LzyTarget.java
│ ├── tag
│ ├── LzyByteCodes.java
│ ├── LzyFlags.java
│ └── LzyKinds.java
│ ├── tree
│ ├── LzyJCCompilationUnit.java
│ ├── LzyJCImport.java
│ ├── LzyJCIndexed.java
│ ├── LzyJCMethodDef.java
│ ├── LzyJCModifiers.java
│ ├── LzyJCTree.java
│ ├── LzyJCTypeParameter.java
│ ├── LzyTreeInfo.java
│ ├── LzyTreeMaker.java
│ ├── LzyVisitor.java
│ ├── express
│ │ ├── LzyJCApply.java
│ │ ├── LzyJCAssign.java
│ │ ├── LzyJCAssignop.java
│ │ ├── LzyJCBinary.java
│ │ ├── LzyJCConditional.java
│ │ ├── LzyJCErroneous.java
│ │ ├── LzyJCIdent.java
│ │ ├── LzyJCLiteral.java
│ │ ├── LzyJCNewArray.java
│ │ ├── LzyJCNewClass.java
│ │ ├── LzyJCParens.java
│ │ ├── LzyJCSelect.java
│ │ ├── LzyJCTypeArray.java
│ │ ├── LzyJCTypeCast.java
│ │ ├── LzyJCTypeIdent.java
│ │ ├── LzyJCTypeTest.java
│ │ └── LzyJCUnary.java
│ └── state
│ │ ├── LzyJCBlock.java
│ │ ├── LzyJCBreak.java
│ │ ├── LzyJCCase.java
│ │ ├── LzyJCCatch.java
│ │ ├── LzyJCClassDef.java
│ │ ├── LzyJCContinue.java
│ │ ├── LzyJCDoloop.java
│ │ ├── LzyJCExec.java
│ │ ├── LzyJCExpressionStatement.java
│ │ ├── LzyJCForLoop.java
│ │ ├── LzyJCIf.java
│ │ ├── LzyJCReturn.java
│ │ ├── LzyJCSkip.java
│ │ ├── LzyJCSwitch.java
│ │ ├── LzyJCThrow.java
│ │ ├── LzyJCTry.java
│ │ ├── LzyJCVarDef.java
│ │ └── LzyJCWhileLoop.java
│ ├── util
│ ├── LzyAssert.java
│ ├── LzyByteBuffer.java
│ ├── LzyContext.java
│ ├── LzyConvert.java
│ ├── LzyHashtable.java
│ ├── LzyList.java
│ ├── LzyListBuffer.java
│ └── LzyPosition.java
│ └── world
│ ├── LzyKeywords.java
│ ├── LzyName.java
│ ├── LzyScanner.java
│ ├── LzyTable.java
│ └── LzyToken.java
└── test_javac
├── Anlimal.class
├── Anlimal.java
├── Demo03.class
├── Demo03.java
└── rt.jar
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project exclude paths
2 | /target/
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/libraries/tools.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LzyJavac
2 | JavaCompile 仿制的Java前端编译器 基础正版javac的精简版本,添加大量注释说明
3 |
4 | # LzyJavac和正版Javac有什么区别?
5 | LzyJavac是从正版Javac大量抄袭修改而来的,为了帮助大家方便学习理解。
6 | 删减大量复杂非必要的过程,语法检查 和 插件化注解 和 解语法糖并没有实现!
7 | 但是这不影响,我们对Java前端编译器的学习和理解!
8 | 这份源码中,写了大量注释。参考多个jdk版本,选择的算法是简单为主!而不是最好的,因为更容易帮助大家理解!
9 |
10 | # 两个路径
11 | jdk类库路径:存放jdk自带的类
12 | String List 等等
13 | 编译路径:存放Java源代码
14 | 将对这个位置的源代码进行编译处理
15 | # 不支持的功能
16 | 1. 内部类
17 | 2. 枚举
18 | 3. 注解
19 | 4. 泛型
20 | 5. Lambda
21 | 6. switch
22 | 为什么不支持1-5?
23 | 因为要实现他们,过于繁琐难度很大,也不利于大家初步的学习
24 | 为什么不支持6?
25 | 因为懒,大家可以参考我关于switch字节码的分析去实现!
26 | # switch字节码的原理分析
27 | https://www.bilibili.com/video/BV1qv411g7tj/
28 |
29 | # 作者信息
30 | 李滋芸 鄂州职业大学
31 |
32 | 微信:liziyun_2000
33 |
34 | 公众号:小豆的奇思妙想
35 |
36 | B站up讲课:李滋芸
37 | # 使用教程
38 | https://www.bilibili.com/video/BV1La411C7Xe
39 |
40 |
41 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.example
8 | LzyJavaCompile1.5
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | org.springframework.boot
14 | spring-boot-maven-plugin
15 | 2.3.1.RELEASE
16 |
17 |
18 | work.liziyun.LzyJavaCompiler
19 |
20 |
21 |
22 |
23 |
24 | repackage
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | jdk-1.8
36 |
37 | 1.8
38 | true
39 |
40 |
41 | UTF-8
42 | UTF-8
43 | UTF-8
44 | 1.8
45 | 1.8
46 | 1.8
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/main/java/work/liziyun/Demo03.java:
--------------------------------------------------------------------------------
1 | package work.liziyun;
2 |
3 |
4 |
5 | class Anlimal{
6 | public String name = "23";
7 | }
8 |
9 | public class Demo03 extends Anlimal {
10 |
11 | public Anlimal anlimal = new Anlimal();
12 |
13 | public static String getName(){
14 | return "23";
15 | }
16 |
17 |
18 | public static void main(String []args){
19 | Demo03 demo03 = new Demo03();
20 | System.out.println( demo03.anlimal.name );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/work/liziyun/LzyJavaCompiler.java:
--------------------------------------------------------------------------------
1 | package work.liziyun;
2 |
3 |
4 |
5 | import work.liziyun.ast.LexerBuffer;
6 | import work.liziyun.ast.LzyJavacParser;
7 | import work.liziyun.code.LzyClassWriter;
8 | import work.liziyun.code.symbol.LzyClassSymbol;
9 | import work.liziyun.comp.*;
10 | import work.liziyun.code.LzyClassReader;
11 | import work.liziyun.tree.LzyJCCompilationUnit;
12 |
13 | import work.liziyun.tree.LzyTreeMaker;
14 | import work.liziyun.tree.state.LzyJCClassDef;
15 | import work.liziyun.util.LzyContext;
16 | import work.liziyun.util.LzyList;
17 | import work.liziyun.util.LzyListBuffer;
18 | import work.liziyun.world.LzyTable;
19 | import java.io.*;
20 | import java.util.Scanner;
21 |
22 | public class LzyJavaCompiler implements LzyClassReader.SourceCompleter {
23 |
24 |
25 | private work.liziyun.util.LzyContext LzyContext;
26 |
27 | private LzyTreeMaker treeMaker;
28 |
29 | private LzyTable names;
30 |
31 | private LzyEnter enter;
32 |
33 | private LzyClassReader classReader;
34 |
35 | private LzyAttr attr;
36 |
37 | private LzyTodo todo;
38 |
39 | private LzyGen gen;
40 |
41 | private LzyClassWriter classWriter;
42 |
43 | public LzyJavaCompiler(LzyContext LzyContext){
44 | this.LzyContext = LzyContext;
45 | this.treeMaker = LzyTreeMaker.instance(LzyContext);
46 | this.names = LzyTable.instance(LzyContext);
47 | this.enter = LzyEnter.instance(LzyContext);
48 | this.classReader = LzyClassReader.instance(LzyContext);
49 | // 设置路径: 注意结束符号 classReader.bootclassPath
50 | // 源码路径: 注意结束符号 classReader.sourceClassPath
51 | // 设置填充器
52 | classReader.sourceCompleter = this;
53 | // 引用消除
54 | this.attr = LzyAttr.instance(LzyContext);
55 | // 承上启下的组件
56 | this.todo = LzyTodo.instance(LzyContext);
57 | //
58 | this.gen = LzyGen.instance(LzyContext);
59 |
60 | this.classWriter = LzyClassWriter.instance(LzyContext);
61 | }
62 |
63 | public LzyList compile(LzyList LzyList) throws Exception {
64 | // 抽象语法树建立
65 | LzyList allPath = LzyList;
66 | LzyListBuffer compilationUnitListBuffer = new LzyListBuffer();
67 | while ( allPath.nonEmpty() ){
68 | try {
69 | compilationUnitListBuffer.append( this.parse(allPath.head) );
70 | } catch (IOException e) {
71 | e.printStackTrace();
72 | }
73 | // 下一个
74 | allPath = allPath.tail;
75 | }
76 | // 符号填充
77 | enter.complete(compilationUnitListBuffer.toList(),null);
78 | // 引用消除
79 | while (todo.nonEmpty()){
80 | LzyEnv env = (LzyEnv)todo.remove();
81 | attr.attribClass(env.tree.pos,env.enclClass.sym);
82 | // Gen生成可寻址实体 + 写入字节码IO流
83 | LzyJCClassDef classDef = (LzyJCClassDef) env.tree;
84 | genCode(env,classDef);
85 | }
86 | return null ;
87 | }
88 |
89 | void genCode(LzyEnv env, LzyJCClassDef classDef) throws Exception {
90 | try{
91 | // 可寻址指令处理
92 | if (this.gen.genClass(env,classDef)){
93 | // 建立IO流生成字节码
94 | this.classWriter.writeClass( classDef.sym );
95 | }
96 | }catch (Exception e){
97 | throw e;
98 | }
99 | }
100 |
101 |
102 |
103 | public static String read(InputStream inputStream) throws IOException {
104 | BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
105 | String temp;
106 | StringBuilder sb = new StringBuilder();
107 | while ( (temp = in.readLine()) != null ){
108 | sb.append(temp);
109 | }
110 | in.close();
111 | return sb.toString();
112 | }
113 |
114 |
115 | public LzyJCCompilationUnit parse(String path) throws IOException {
116 | return parse(path,new FileInputStream(new File(path)));
117 | }
118 |
119 |
120 | public LzyJCCompilationUnit parse(String path,InputStream inputStream) {
121 | // 默认: 空语法树
122 | LzyJCCompilationUnit compilationUnit = this.treeMaker.CompilationUnit(null, LzyList.nil());
123 | if ( inputStream != null ){
124 | // 词法解析器
125 | LexerBuffer lexerBuffer = null;
126 | try {
127 | lexerBuffer = new LexerBuffer(LzyContext, read(inputStream).toCharArray(),path);
128 | } catch (IOException e) {
129 | e.printStackTrace();
130 | }
131 | // 关闭流
132 | try {
133 | inputStream.close();
134 | } catch (IOException e) {
135 | e.printStackTrace();
136 | }
137 | // 移动到第一个词
138 | lexerBuffer.nextToken();
139 | // 解析抽象语法树
140 | LzyJavacParser lzyJavacParser = new LzyJavacParser(lexerBuffer, LzyTreeMaker.instance(LzyContext), LzyTable.instance(LzyContext));
141 | compilationUnit = lzyJavacParser.parseCompilationUnit();
142 | }
143 | // 设置文件路径
144 | compilationUnit.sourcefile = this.names.fromString(path);
145 | return compilationUnit;
146 | }
147 |
148 |
149 | /**
150 | * 被动触发的Java源文件: 1. 抽象语法树的建立 2. 符号的填充
151 | * @param classSymbol
152 | * @param sourcePath
153 | * @param inputStream
154 | *
155 | * am
156 | */
157 | @Override
158 | public void complete(LzyClassSymbol classSymbol , String sourcePath, InputStream inputStream){
159 | // 抽象语法树的建立
160 | System.out.println("LzyJavaCompiler.complete(): 成功触发其他源文件的编译!");
161 | LzyJCCompilationUnit compilationUnit = this.parse(sourcePath, inputStream);
162 | // 符号的填充
163 | this.enter.complete(LzyList.of(compilationUnit),classSymbol);
164 | // 填充失败
165 | if ( this.enter.getEnv(classSymbol) == null){
166 | throw new LzyClassReader.BadClassFile(classSymbol,"file.doesnt.contain.class "+classSymbol.fullName());
167 | }
168 | }
169 | // 系统下级符号
170 | private static String separator = File.separator;
171 | // 系统分割符号
172 | private static String pathSeparator = File.pathSeparator;
173 |
174 | public static void main(String[] args) throws Exception {
175 |
176 | Scanner sc = new Scanner(System.in);
177 | // 设置编译器路径
178 | System.setProperty("env.class.path",System.getProperty("user.dir")+separator+"test_javac"+separator+pathSeparator );
179 | // 系统类路径
180 | System.setProperty("sun.boot.class.path",System.getProperty("env.class.path").substring(0,System.getProperty("env.class.path").length()-1)+"rt.jar"+pathSeparator);
181 | System.out.println( "请检查jdk类库路径:" + System.getProperty("env.class.path") );
182 | System.out.println( "请检查项目路径: " + System.getProperty("sun.boot.class.path") );
183 | LzyJavaCompiler lzyJavaCompiler = new LzyJavaCompiler(new LzyContext());
184 | System.out.println("========================================================");
185 | System.out.println("位置:./LzyJavaCompile1.5/test_javac");
186 | System.out.println("有包格式:pojo.Student.java");
187 | System.out.println("无包格式:Student.java");
188 | System.out.println("========================================================");
189 | LzyList list = LzyList.nil();
190 | while (true){
191 | System.out.println("请输入编译的文件:");
192 | String javaFileName = sc.next();
193 | javaFileName = javaFileName.substring(0,javaFileName.lastIndexOf('.')).replace('.',File.separatorChar)+".java";
194 | list = list.append(System.getProperty("user.dir")+separator+"test_javac"+separator+javaFileName);
195 | System.out.println("是否,继续?(y/n)");
196 | String yes = sc.next();
197 | if (!yes.equals("y")){
198 | break;
199 | }
200 | }
201 | System.out.println("=======================开始编译===========================");
202 | lzyJavaCompiler.compile( list );
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/src/main/java/work/liziyun/ast/Express.java:
--------------------------------------------------------------------------------
1 | package work.liziyun.ast;
2 |
3 |
4 | import work.liziyun.tree.LzyJCTree;
5 | import work.liziyun.tree.LzyTreeInfo;
6 | import work.liziyun.world.LzyToken;
7 |
8 | public interface Express {
9 | /**
10 | * 赋值表达式
11 | * @return
12 | */
13 | public LzyJCTree.JCExpression term();
14 | public LzyJCTree.JCExpression term(int mode);
15 | public LzyJCTree.JCExpression termRest(LzyJCTree.JCExpression var1);
16 |
17 |
18 | /**
19 | * 三元
20 | * @return
21 | */
22 | public LzyJCTree.JCExpression term1();
23 | public LzyJCTree.JCExpression term1Rest(LzyJCTree.JCExpression tree);
24 |
25 |
26 | /**
27 | * 二元
28 | * @return
29 | */
30 | public LzyJCTree.JCExpression term2();
31 | public LzyJCTree.JCExpression term2Rest(LzyJCTree.JCExpression tree,int op);
32 |
33 |
34 | /**
35 | * 一元 与 基本表达式
36 | * @return
37 | */
38 | public LzyJCTree.JCExpression term3();
39 |
40 | static int prec(LzyToken var0) {
41 | int var1 = optag(var0);
42 | return var1 >= 0 ? LzyTreeInfo.opPrec(var1) : -1;
43 | }
44 |
45 | /**
46 | * 基本数据类型的映射值
47 | * @param var0
48 | * @return
49 | */
50 | static int typetag(LzyToken var0) {
51 | switch(var0) {
52 | case BYTE:
53 | return 1;
54 | case SHORT:
55 | return 3;
56 | case CHAR:
57 | return 2;
58 | case INT:
59 | return 4;
60 | case LONG:
61 | return 5;
62 | case FLOAT:
63 | return 6;
64 | case DOUBLE:
65 | return 7;
66 | case BOOLEAN:
67 | return 8;
68 | default:
69 | return -1;
70 | }
71 | }
72 |
73 |
74 |
75 | /**
76 | * 辅助TreeMark的创建: 一元运算符 映射值
77 | * @param var0
78 | * @return
79 | */
80 | static int unoptag(LzyToken var0) {
81 | switch(var0) {
82 | case BANG:
83 | return 50;
84 | case TILDE:
85 | return 51;
86 | case LPAREN:
87 | case THIS:
88 | case SUPER:
89 | case NEW:
90 | case LBRACKET:
91 | case DOT:
92 | case QUES:
93 | default:
94 | return -1;
95 | case PLUSPLUS:
96 | return 52;
97 | case SUBSUB:
98 | return 53;
99 | case PLUS:
100 | return 48;
101 | case SUB:
102 | return 49;
103 | }
104 | }
105 |
106 | static int optag(LzyToken var0) {
107 | switch(var0) {
108 | case LT:
109 | return 64;
110 | case BYTE:
111 | case SHORT:
112 | case CHAR:
113 | case INT:
114 | case LONG:
115 | case FLOAT:
116 | case DOUBLE:
117 | case BOOLEAN:
118 | case VOID:
119 | case IDENTIFIER:
120 | case CASE:
121 | case DEFAULT:
122 | case IF:
123 | case FOR:
124 | case WHILE:
125 | case DO:
126 | case TRY:
127 | case SWITCH:
128 | case RETURN:
129 | case THROW:
130 | case BREAK:
131 | case CONTINUE:
132 | case ELSE:
133 | case FINALLY:
134 | case CATCH:
135 | case INTLITERAL:
136 | case LONGLITERAL:
137 | case FLOATLITERAL:
138 | case DOUBLELITERAL:
139 | case CHARLITERAL:
140 | case STRINGLITERAL:
141 | case TRUE:
142 | case FALSE:
143 | case NULL:
144 | case EQ:
145 | case BANG:
146 | case TILDE:
147 | case LPAREN:
148 | case THIS:
149 | case SUPER:
150 | case NEW:
151 | case LBRACKET:
152 | case DOT:
153 | case QUES:
154 | case PLUSPLUS:
155 | case SUBSUB:
156 | case ERROR:
157 | default:
158 | return -1;
159 | case PLUSEQ:
160 | return 88;
161 | case SUBEQ:
162 | return 89;
163 | case STAREQ:
164 | return 90;
165 | case SLASHEQ:
166 | return 91;
167 | case PERCENTEQ:
168 | return 92;
169 | case AMPEQ:
170 | return 78;
171 | case BAREQ:
172 | return 76;
173 | case CARETEQ:
174 | return 77;
175 | case LTLTEQ:
176 | return 85;
177 | case GTGTEQ:
178 | return 86;
179 | case GTGTGTEQ:
180 | return 87;
181 | case PLUS:
182 | return 71;
183 | case SUB:
184 | return 72;
185 | case GTEQ:
186 | return 67;
187 | case GTGTGT:
188 | return 70;
189 | case GTGT:
190 | return 69;
191 | case GT:
192 | return 65;
193 | case BARBAR:
194 | return 57;
195 | case AMPAMP:
196 | return 58;
197 | case BAR:
198 | return 59;
199 | case CARET:
200 | return 60;
201 | case AMP:
202 | return 61;
203 | case EQEQ:
204 | return 62;
205 | case BANGEQ:
206 | return 63;
207 | case LTEQ:
208 | return 66;
209 | case LTLT:
210 | return 68;
211 | case STAR:
212 | return 73;
213 | case SLASH:
214 | return 74;
215 | case PERCENT:
216 | return 75;
217 | case INSTANCEOF:
218 | return 32;
219 | }
220 | }
221 |
222 | }
223 |
--------------------------------------------------------------------------------
/src/main/java/work/liziyun/ast/LexerBuffer.java:
--------------------------------------------------------------------------------
1 | package work.liziyun.ast;
2 |
3 |
4 | import work.liziyun.util.LzyContext;
5 | import work.liziyun.world.LzyName;
6 | import work.liziyun.world.LzyScanner;
7 | import work.liziyun.world.LzyTable;
8 | import work.liziyun.world.LzyToken;
9 |
10 |
11 | public class LexerBuffer extends LzyScanner {
12 |
13 | private int errorEndPos;
14 | private LzyTable names;
15 |
16 | public LexerBuffer(LzyContext LzyContext, char[] chars,String fileName) {
17 | super( LzyContext,chars,fileName);
18 |
19 | }
20 |
21 |
22 |
23 | /**
24 | * 返回当前词Token的Name
25 | * 注意:
26 | * 1. 不处理assert断言关键字
27 | * 2. 不处理枚举
28 | * 3. 不处理this
29 | * 4. 不处理UNDERSCORE下划线
30 | * @return
31 | */
32 | public LzyName ident(){
33 | LzyName name;
34 | // 当前Token是标识符
35 | if (this.token() == LzyToken.IDENTIFIER){
36 | name = this.name();
37 | // 移词
38 | this.nextToken();
39 | return name;
40 | }else{
41 | // 记录错误: 我们一直期望得到一个标识符的词
42 | this.accept(LzyToken.IDENTIFIER);
43 | return this.names.error;
44 | }
45 | }
46 |
47 | public void accept(LzyToken expectToken){
48 | if (this.token() == expectToken ){
49 | this.nextToken();
50 |
51 | } else {
52 | // 设置错误位置
53 | setErrorEndPos(this.pos());
54 | // 记录报错信息
55 | System.out.println(this.prevEndPos()+" expected: " + expectToken.toString() );
56 | }
57 | }
58 |
59 | public void tryEndOf(){
60 | if (this.bp == this.buf.length-1){
61 | this.token = LzyToken.EOF;
62 | System.out.println("词法分析结束:"+fileName);
63 | }
64 | }
65 |
66 | public void setErrorEndPos(int errPos) {
67 | if (errPos > errorEndPos)
68 | errorEndPos = errPos;
69 | }
70 |
71 | public int getErrorEndPos(){
72 | return errorEndPos;
73 | }
74 |
75 | /** Skip forward until a suitable stop token is found.
76 | */
77 | public void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
78 | while (true) {
79 | switch (token()) {
80 | case SEMI:
81 | nextToken();
82 | return;
83 | case PUBLIC:
84 | case FINAL:
85 | case ABSTRACT:
86 | case EOF:
87 | case CLASS:
88 | case INTERFACE:
89 | return;
90 | case IMPORT:
91 | if (stopAtImport)
92 | return;
93 | break;
94 | case LBRACE:
95 | case RBRACE:
96 | case PRIVATE:
97 | case PROTECTED:
98 | case STATIC:
99 |
100 | case LT:
101 | case BYTE:
102 | case SHORT:
103 | case CHAR:
104 | case INT:
105 | case LONG:
106 | case FLOAT:
107 | case DOUBLE:
108 | case BOOLEAN:
109 | case VOID:
110 | if (stopAtMemberDecl)
111 | return;
112 | break;
113 | case IDENTIFIER:
114 | if (stopAtIdentifier)
115 | return;
116 | break;
117 | case CASE:
118 | case DEFAULT:
119 | case IF:
120 | case FOR:
121 | case WHILE:
122 | case DO:
123 | case TRY:
124 | case SWITCH:
125 | case RETURN:
126 | case THROW:
127 | case BREAK:
128 | case CONTINUE:
129 | case ELSE:
130 | case FINALLY:
131 | case CATCH:
132 | if (stopAtStatement)
133 | return;
134 | break;
135 | }
136 | nextToken();
137 | }
138 | }
139 |
140 |
141 |
142 |
143 |
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/src/main/java/work/liziyun/ast/Parser.java:
--------------------------------------------------------------------------------
1 | package work.liziyun.ast;
2 |
3 |
4 | import work.liziyun.tree.LzyJCCompilationUnit;
5 | import work.liziyun.tree.LzyJCTree;
6 |
7 | public interface Parser {
8 | LzyJCCompilationUnit parseCompilationUnit();
9 |
10 | LzyJCTree.JCExpression parseExpression();
11 |
12 | LzyJCTree.JCStatement parseStatement();
13 |
14 | LzyJCTree.JCExpression parseType();
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/work/liziyun/ast/Statement.java:
--------------------------------------------------------------------------------
1 | package work.liziyun.ast;
2 |
3 | import work.liziyun.tree.LzyJCTree;
4 | import work.liziyun.util.LzyList;
5 |
6 | public interface Statement {
7 | LzyList blockStatements();
8 | LzyJCTree.JCStatement statement();
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/work/liziyun/code/LzyClassFile.java:
--------------------------------------------------------------------------------
1 | package work.liziyun.code;
2 |
3 |
4 | import work.liziyun.code.type.LzyType;
5 | import work.liziyun.world.LzyName;
6 | import java.io.File;
7 |
8 | public class LzyClassFile {
9 | public static final int JAVA_MAGIC = -889275714;
10 | public static final int CONSTANT_Utf8 = 1;
11 | public static final int CONSTANT_Unicode = 2;
12 | public static final int CONSTANT_Integer = 3;
13 | public static final int CONSTANT_Float = 4;
14 | public static final int CONSTANT_Long = 5;
15 | public static final int CONSTANT_Double = 6;
16 | public static final int CONSTANT_Class = 7;
17 | public static final int CONSTANT_String = 8;
18 | public static final int CONSTANT_Fieldref = 9;
19 | public static final int CONSTANT_Methodref = 10;
20 | public static final int CONSTANT_InterfaceMethodref = 11;
21 | public static final int CONSTANT_NameandType = 12;
22 | public static final int CONSTANT_MethodHandle = 15;
23 | public static final int CONSTANT_MethodType = 16;
24 | public static final int CONSTANT_InvokeDynamic = 18;
25 | public static final int MAX_PARAMETERS = 255;
26 | public static final int MAX_DIMENSIONS = 255;
27 | public static final int MAX_CODE = 65535;
28 | public static final int MAX_LOCALS = 65535;
29 | public static final int MAX_STACK = 65535;
30 |
31 | public LzyClassFile() {
32 | }
33 |
34 | public static byte[] internalize(byte[] var0, int var1, int var2) {
35 | byte[] var3 = new byte[var2];
36 |
37 | for(int var4 = 0; var4 < var2; ++var4) {
38 | byte var5 = var0[var1 + var4];
39 | if (var5 == 47) {
40 | var3[var4] = 46;
41 | } else {
42 | var3[var4] = var5;
43 | }
44 | }
45 |
46 | return var3;
47 | }
48 |
49 | public static byte[] internalize(LzyName var0) {
50 | return internalize(var0.getByteArray(), var0.getIndex(), var0.getByteLength());
51 | }
52 |
53 | public static byte[] externalize(byte[] var0, int var1, int var2) {
54 | byte[] var3 = new byte[var2];
55 |
56 | for(int var4 = 0; var4 < var2; ++var4) {
57 | byte var5 = var0[var1 + var4];
58 | if (var5 == 46) {
59 | var3[var4] = 47;
60 | } else {
61 | var3[var4] = var5;
62 | }
63 | }
64 |
65 | return var3;
66 | }
67 |
68 | public static byte[] externalize(LzyName var0) {
69 | return externalize(var0.getByteArray(), var0.getIndex(), var0.getByteLength());
70 | }
71 |
72 | public static String externalizeFileName(LzyName var0) {
73 | return var0.toString().replace('.', File.separatorChar);
74 | }
75 | public static class NameAndType {
76 | public LzyName name;
77 | public LzyType type;
78 |
79 | public NameAndType(LzyName var1, LzyType var2) {
80 | this.name = var1;
81 | this.type = var2;
82 | }
83 |
84 | public boolean equals(Object var1) {
85 | return var1 instanceof LzyClassFile.NameAndType && this.name == ((LzyClassFile.NameAndType)var1).name && this.type.equals(((LzyClassFile.NameAndType)var1).type);
86 | }
87 |
88 | public int hashCode() {
89 | return this.name.hashCode() * this.type.hashCode();
90 | }
91 | }
92 |
93 | public static enum Version {
94 | V45_3(45, 3),
95 | V49(49, 0),
96 | V50(50, 0),
97 | V51(51, 0);
98 |
99 | public final int major;
100 | public final int minor;
101 |
102 | private Version(int var3, int var4) {
103 | this.major = var3;
104 | this.minor = var4;
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/work/liziyun/code/LzyPool.java:
--------------------------------------------------------------------------------
1 | package work.liziyun.code;
2 |
3 |
4 | import work.liziyun.code.symbol.LzyMethodSymbol;
5 | import work.liziyun.code.symbol.LzyVarSymbol;
6 | import java.util.HashMap;
7 |
8 | /**
9 | * 作者: 李滋芸
10 | * 常量池
11 | */
12 |
13 | interface LzyPoolType{
14 | int CONSTANT_Utf8_info = 1;
15 | int CONSTANT_Integer_info = 3;
16 | int CONSTANT_Float_info = 4;
17 | int CONSTANT_Long_info = 5;
18 | int CONSTANT_Double_info = 6;
19 | int CONSTANT_Class_info = 7;
20 | int CONSTANT_String_info = 8;
21 | int CONSTANT_Filedref_info = 9;
22 | int CONSTANT_Methodref_info = 10;
23 | int CONSTANT_InterfaceMethodref_info = 11;
24 | int CONSTANT_NameAndType_info =12;
25 | int CONSTANT_MethodHandle_info =15;
26 | int CONSTANT_MethodType_info =16;
27 | int CONSTANT_InvokeDynamic_info =18;
28 | }
29 |
30 |
31 | public class LzyPool {
32 | public static final int MAX_ENTRIES = 65535;
33 | public static final int MAX_STRING_LENGTH= 65535;
34 | int pp;
35 | Object[] pool;
36 | HashMap