⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sourcecodeparser.java

📁 JASML is a java byte code compiler, providing yet another approach to view, write and edit java clas
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
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 + -