📄 sourcecodeparser.java
字号:
package com.jasml.compiler;
import java.io.File;
import java.util.ArrayList;
import java.util.Hashtable;
import com.jasml.classes.Attribute;
import com.jasml.classes.Attribute_Code;
import com.jasml.classes.Attribute_ConstantValue;
import com.jasml.classes.Attribute_Deprecated;
import com.jasml.classes.Attribute_Exceptions;
import com.jasml.classes.Attribute_InnerClasses;
import com.jasml.classes.Attribute_LocalVariableTable;
import com.jasml.classes.Attribute_SourceFile;
import com.jasml.classes.Attribute_Synthetic;
import com.jasml.classes.Constants;
import com.jasml.classes.Field;
import com.jasml.classes.JavaClass;
import com.jasml.classes.Method;
import com.jasml.helper.IntegerArray;
import com.jasml.helper.OpcodeHelper;
import com.jasml.helper.OpcodeInfo;
import com.jasml.helper.Util;
public class SourceCodeParser implements Scannable {
private Scanner scanner;
JavaClass javaClass;
ConstantPoolGenerator cpl = new ConstantPoolGenerator();
boolean precompile = false;
public SourceCodeParser(File file) throws ParsingException {
scanner = new Scanner(file);
}
public SourceCodeParser(String content) throws ParsingException {
scanner = new Scanner(content);
}
public JavaClass parse() throws ParsingException {
javaClass = new JavaClass();
cpl = new ConstantPoolGenerator();
if (precompile == true) {
preprocessConstantValues();
}
parseClass();
return javaClass;
}
private void preprocessConstantValues() throws ParsingException {
scanner.mark();
String t;
while (scanner.nextToken() != EOF) {
switch (scanner.tokenType()) {
case String:
t = scanner.token();
cpl.addString(Util.parseViewableString(t.substring(1, t.length() - 1)));
break;
case Number_Double:
t = scanner.token();
cpl.addDouble( parseDouble(t ));
case Number_Long:
t = scanner.token();
cpl.addDouble(parseLong(t ));
break;
}
}
scanner.restore();
}
private void parseClass() throws ParsingException, GrammerException {
scanner.nextToken();
if (scanner.tokenType() == Attribute) {
parseMajorOrMinor();
}
parseClassSignature();
parseFields();
parseMethods();
parseClassAttributes();
if (scanner.tokenType() != Bracket_Right) {
exception(scanner, "'}'.expected.here");
}
if (scanner.nextToken() != EOF) {
exception(scanner, "end.of.class.expected.here");
}
javaClass.constantPool = cpl.getConstantPool();
javaClass.constant_pool_count = javaClass.constantPool.getConstantPoolCount();
}
private void parseClassSignature() throws ParsingException {
// access flags
int acc = 0;
while (scanner.tokenType() == AccessFlag) {
acc = acc | Util.getAccessFlag_Class(scanner.token());
scanner.nextToken();
}
if (acc == 0) {
exception(scanner, "\"class\".expected.here");
}
javaClass.access_flags = (short) acc;
// class name
javaClass.this_class = cpl.addClass(scanner.token());
scanner.nextToken();
//interfaces and super classes
while (scanner.tokenType() != Bracket_Left && scanner.tokenType() != EOF) {
if ("extends".equals(scanner.token()) == true) {
scanner.nextToken();
javaClass.super_class = cpl.addClass(scanner.token());
scanner.nextToken();
} else if ("implements".equals(scanner.token()) == true) {
scanner.nextToken();
IntegerArray array = new IntegerArray(5);
while (scanner.tokenType() != Bracket_Left && scanner.tokenType() != EOF) {
array.add(cpl.addClass(scanner.token()));
scanner.nextToken();
if (scanner.tokenType() == Comma) {
scanner.nextToken();
}
}
javaClass.interfaces = array.getAll();
javaClass.interfaces_count = javaClass.interfaces.length;
} else {
exception(scanner, "unexpected.character.here");
}
}
scanner.nextToken();
}
private void parseFields() throws ParsingException, GrammerException {
ArrayList fields = new ArrayList(10);
Object field;
do {
field = parseField();
if (field != null) {
fields.add(field);
}
} while (field != null);
javaClass.fields = (Field[]) fields.toArray(new Field[fields.size()]);
javaClass.fields_count = javaClass.fields.length;
}
private Field parseField() throws ParsingException, GrammerException {
if (scanner.tokenType() == Attribute || scanner.tokenType() == Bracket_Right) {
return null;
}
scanner.mark();
int acc = 0;
while (scanner.tokenType() == AccessFlag) {
acc = acc | Util.getAccessFlag_Field(scanner.token());
scanner.nextToken();
}
String fieldType = scanner.token();
scanner.nextToken();
String fieldName = scanner.token();
scanner.nextToken();
String maybeEuqal = scanner.token(); // the next char may be a '=', marks the presence of a constant value attribute
if (fieldType.indexOf('(') != -1 || fieldName.indexOf('(') != -1 || maybeEuqal.indexOf('(') != -1) {
// the presence of '(' marks an method declaration
scanner.restore();
return null;
}
ArrayList attributes = new ArrayList(3);
fieldType = Util.toInnerType(fieldType);
if (scanner.tokenType() == Equal) {
scanner.nextToken();
String constValue = scanner.token();
int const_index;
Attribute_ConstantValue con = null;
switch (fieldType.charAt(0)) {
case 'B':
case 'C':
case 'I':
case 'S':
case 'Z':
const_index = cpl.addInteger(parseInteger(constValue));
con = new Attribute_ConstantValue(2, const_index);
break;
case 'D':
const_index = cpl.addDouble(parseDouble(constValue));
con = new Attribute_ConstantValue(2, const_index);
break;
case 'F':
const_index = cpl.addFloat(parseFloat(constValue));
con = new Attribute_ConstantValue(2, const_index);
break;
case 'J':
const_index = cpl.addLong(parseLong(constValue));
con = new Attribute_ConstantValue(2, const_index);
break;
case 'L':
if (fieldType.equals("Ljava/lang/String;") == true) {
const_index = cpl.addString(Util.parseViewableString(constValue.substring(1, constValue.length() - 1))); // trim
// the
// '"'
con = new Attribute_ConstantValue(2, const_index);
break;
}
default:
exception(scanner, "can.not.assign.contant.value.to.this.field.type.only.primitive.types.and.string.allowed");
}
con.attribute_name_index = cpl.addUtf8("ConstantValue");
attributes.add(con);
scanner.nextToken();
}
while (scanner.tokenType() == Attribute) {
attributes.add(parseAttribute());
}
Field ret = new Field(acc, cpl.addUtf8(fieldName), cpl.addUtf8(fieldType), attributes.size(), (Attribute[]) attributes
.toArray(new Attribute[attributes.size()]));
return ret;
}
private void parseMethods() throws ParsingException, GrammerException {
ArrayList methods = new ArrayList(10);
Object method;
do {
method = parseMethod();
if (method != null) {
methods.add(method);
}
} while (method != null);
javaClass.methods = (Method[]) methods.toArray(new Method[methods.size()]);
javaClass.methods_count = javaClass.methods.length;
}
private Method parseMethod() throws ParsingException, GrammerException {
if (scanner.tokenType() == Attribute || scanner.tokenType() == Bracket_Right || scanner.tokenType() == EOF) {
return null;
}
Method method = new Method(0, 0, 0, 0, new Attribute[0]);
LabeledInstructions li;
ArrayList attributes = new ArrayList(4), codeAttributes;
parseMethodSignature(method, attributes);
if (Util.hasMethodBody((short) method.access_flags) == true) {
codeAttributes = new ArrayList(4);
li = parseMethodInstructions(method);
Attribute_Code code = new Attribute_Code();
code.attribute_name_index = cpl.addUtf8("Code");
code.codes = li.codes;
parseMethodAttributes(method, attributes, li, code, codeAttributes);
code.code_length = li.codeLength;
code.attributes = (Attribute[]) codeAttributes.toArray(new Attribute[codeAttributes.size()]);
code.attributes_count = code.attributes.length;
code.attribute_length = 2/*max_stack*/+ 2/*max_locals*/+ 4/*code_length*/+ code.code_length/*code*/+ 2/*exception_table_length*/
+ code.exception_table_length * 8 + 2/*attribute_count*/;
for (int i = 0; i < code.attributes_count; i++) {
code.attribute_length += code.attributes[i].attribute_length + 6;
}
attributes.add(code);
} else {
parseMethodAttributes(method, attributes, null, null, null);
}
scanner.nextToken();
method.attributes = (Attribute[]) attributes.toArray(new Attribute[attributes.size()]);
method.attributes_count = method.attributes.length;
return method;
}
/**
* this method will parse method attribute: Deprecated, Synthetic
* and some of the attributes belongs to code: Max Locals, Max Stack,Local variale table, Exception table
*
* @param method
* @param attributes
*/
private void parseMethodAttributes(Method method, ArrayList attributes, LabeledInstructions li, Attribute_Code code, ArrayList codeAttributes)
throws GrammerException, ParsingException {
String temp;
while (scanner.tokenType() == Attribute) {
temp = scanner.token();
if (temp.indexOf(Constants.ATTRIBUTE_NAME_LOCAL_VARIABLE) != -1) {
codeAttributes.add(parseLocalVariableTable(temp, li.labels));
scanner.nextToken();
} else if (temp.indexOf(Constants.ATTRIBUTE_NAME_EXCEPTION_TABLE) != -1) {
code.exception_table = parseExceptionTable(temp, li.labels);
code.exception_table_length = code.exception_table.length;
scanner.nextToken();
} else if (temp.indexOf(Constants.ATTRIBUTE_NAME_MAX_STACK) != -1) {
parseMaxStackOrLocals(code);
scanner.nextToken();
} else if (temp.indexOf(Constants.ATTRIBUTE_NAME_MAX_LOCAL) != -1) {
parseMaxStackOrLocals(code);
scanner.nextToken();
} else if (temp.indexOf(Constants.ATTRIBUTE_NAME_DEPRECATED) != -1) {
attributes.add(parseAttribute());
} else if (temp.indexOf(Constants.ATTRIBUTE_NAME_SYNTHETIC) != -1) {
attributes.add(parseAttribute());
} else if (temp.indexOf(Constants.ATTRIBUTE_NAME_LINE_NUMBER_TABLE) != -1) {
scanner.nextToken();
if (false) {
parseLineNumbers(null);
}
} else {
exception(scanner, "unexpected.attribute." + scanner.token());
}
}
// // dose a code attribute must have an local variable attribute? TODO:
// boolean isLocalVariableDefined = false;
// Attribute_LocalVariableTable lv;
// for (int i = 0; i < codeAttributes.size(); i++) {
// if (codeAttributes.get(i) instanceof Attribute_LocalVariableTable) {
// isLocalVariableDefined = true;
// lv = (Attribute_LocalVariableTable) codeAttributes.get(i);
// break;
// }
// }
// if (isLocalVariableDefined == false) {
// lv = new Attribute_LocalVariableTable(2, 0, null);
// lv.attribute_name_index = cpl.addUtf8("LocalVariableTable");
// codeAttributes.add(lv);
// }
}
private Attribute parseLineNumbers(String s) {
return null;
}
private LabeledInstructions parseMethodInstructions(Method method) throws ParsingException, GrammerException {
Hashtable labelMap = new Hashtable();
ArrayList toUpdate = new ArrayList();
ArrayList codes = new ArrayList(), info;
Attribute_Code.Opcode op = null;
OpcodeInfo opinfo;
String temp, retType, type, label = null;
StringBuffer paras = new StringBuffer();
int t = 0, i = 0, j = 0, high, low, npairs, counter, tokenType, offset = 0, codeLength = 0;
byte[][] operands = null;
boolean isWide = false, record = false;
while (scanner.tokenType() != EOF && scanner.tokenType() != Attribute && scanner.tokenType() != Bracket_Right) {
switch (scanner.tokenType()) {
case JavaName:
// label met
record = true;
label = scanner.token();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -