www.pudn.com > ParseAna.rar > LexAna.java


/** 
 * this class is used for word ananalyze. 
 * @author:ºØ¾² 
 * @version:1.2 
 */ 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.StringReader; 
 
public class LexAna { 
 
	private int state; 
 
	private BufferedReader input; 
 
	private String token = ""; 
 
	private int lineNo = 1; 
 
	private ReservedWord[] reserve = new ReservedWord[] { 
			new ReservedWord("class", Type.CLASS), 
			new ReservedWord("if", Type.IF), 
			new ReservedWord("else", Type.ELSE), 
			new ReservedWord("while", Type.WHILE), 
			new ReservedWord("int", Type.INT), 
			new ReservedWord("real", Type.REAL), 
			new ReservedWord("read", Type.READ), 
			new ReservedWord("write", Type.WRITE) }; 
 
	private char[] opChar = new char[] { '+', '-', '*', '/', '<', '>', '=', 
			'{', '}', '(', ')', '[', ']', ';', ',' }; 
 
	private boolean isOper(char a) { 
		for (int i = 0; i < opChar.length; i++) { 
			if (opChar[i] == a) 
				return true; 
		} 
		return false; 
	} 
 
	private int getIdenType(String token) { 
		for (int i = 0; i < reserve.length; i++) { 
			if (reserve[i].getName().equals(token)) { 
				return reserve[i].getType(); 
			} 
		} 
		return Type.ID; 
	} 
 
	/* 
	 * i is the ASCII of the char if i is between 97 and 122, i is a-z; if i is 
	 * between 65 and 90, i is A-Z; 
	 */ 
	private boolean isLetter(char a) { 
		int i = (int) a; 
		if ((97 <= i & i <= 122) || (65 <= i & i <= 90)) { 
			return true; 
		} 
		return false; 
	} 
 
	/* 
	 * the ASCII of digits 0-9 is between 48 and 57 
	 */ 
	private boolean isDigit(char a) { 
		int i = (int) a; 
		if (48 <= i & i <= 57) { 
			return true; 
		} 
		return false; 
	} 
 
	// switch the state 
	private void reSet() throws IOException { 
		switch (state) { 
		case 0: 
			state = 8; 
			break; 
		case 8: 
			state = 11; 
			break; 
		case 11: 
			state = 14; 
			break; 
		default: 
		} 
	} 
 
	// refresh the input,"$" ÖÕÖ¹·û 
	public void setBufferInput(String s) { 
		// s = "+ >"; 
		input = new BufferedReader(new StringReader(s + "$")); 
	} 
 
	/* 
	 * the main method of word annalyze 0:operator; 8:key word or identify; 
	 * 11:number 
	 */ 
	public Token getToken() throws IOException { 
		int c = input.read(); 
		char charToken = (char) c; 
		state = 0; 
		int lineNO = 0; 
		String token2 = " "; 
		while (c != -1) { 
			switch (state) { 
			case 0: 
				if (charToken == ' ') 
					; 
				else if (charToken == '\n') 
					lineNo++; 
				else if (charToken == '+' || charToken == '>' 
						|| charToken == '[' || charToken == ']' 
						|| charToken == '(' || charToken == ')' 
						|| charToken == '{' || charToken == '}' 
						|| charToken == ';' || charToken == ',') { 
					token = String.valueOf(charToken); 
					switch (charToken) { 
					case '+': 
						return new Token(token, Type.ADD, lineNo); 
					case '>': 
						return new Token(token, Type.BIGGER, lineNo); 
					case '{': 
						return new Token(token, Type.LEFTBig, lineNo); 
					case '}': 
						return new Token(token, Type.RIGHTBig, lineNo); 
					case '[': 
						return new Token(token, Type.LEFTMid, lineNo); 
					case ']': 
						return new Token(token, Type.RIGHTMid, lineNo); 
					case '(': 
						return new Token(token, Type.LEFTSmall, lineNo); 
					case ')': 
						return new Token(token, Type.RIGHTSmall, lineNo); 
					case ';': 
						return new Token(token, Type.SEMI, lineNo); 
					case ',': 
						return new Token(token, Type.COMMA, lineNo); 
					} 
				} else if (charToken == '<') { 
					state = 1; 
					input.mark(2); 
				} else if (charToken == '=') { 
					state = 2; 
					input.mark(2); 
				} else if (charToken == '-') { 
					state = 3; 
					input.mark(2); 
				} else if (charToken == '/') { 
					state = 4; 
					input.mark(2); 
				} else if (charToken == '*') { 
					state = 7; 
					input.mark(2); 
				} else { 
					reSet(); 
					break; 
				} 
				c = input.read(); 
				charToken = (char) c; 
				break; 
			case 1: 
				if (charToken == '>') { 
					token = "<>"; 
					return new Token(token, Type.NOTEQUAL, lineNo); 
				} else { 
					input.reset(); 
					token = "<"; 
					return new Token(token, Type.LESS, lineNo); 
				} 
			case 2: 
				if (charToken == '=') { 
					token = "=="; 
					return new Token(token, Type.EQUAL, lineNo); 
				} else { 
					input.reset(); 
					token = "="; 
					return new Token(token, Type.ASSIGN, lineNo); 
				} 
			case 3: 
				if (token.equals("+") || token.equals("-") || token.equals("*") 
						|| token.equals("/") || token.equals("<") 
						|| token.equals(">") || token.equals("<>") 
						|| token.equals("=") || token.equals("==") 
						|| token.equals("(") || token.equals(",") 
						|| token.equals("[")) { 
					if (isDigit(charToken)) { 
						token = "<->"; 
						state = 11; 
						break; 
					} else { 
						token = "-"; 
						input.reset(); 
						return new Token(token, Type.MINUSUNI, lineNo); 
					} 
				} else { 
					token = "-"; 
					input.reset(); 
					return new Token(token, Type.MINUSBI, lineNo); 
				} 
			case 4: 
				if (charToken == '*') { 
					state = 5; 
					c = input.read(); 
					charToken = (char) c; 
				} else { 
					token = "/"; 
					input.reset(); 
					return new Token(token, Type.DIVID, lineNo); 
				} 
				break; 
			case 5: 
				if (charToken == '*') 
					state = 6; 
				else { 
					if (charToken == '\n') 
						lineNO++; 
					state = 5; 
				} 
				c = input.read(); 
				charToken = (char) c; 
				break; 
			case 6: 
				if (charToken == '/') { 
					lineNo = lineNo + lineNO; 
					lineNO = 0; 
					state = 0; 
				} else if (charToken == '*') 
					state = 6; 
				else { 
					if (charToken == '\n') 
						lineNO++; 
					state = 5; 
				} 
				c = input.read(); 
				charToken = (char) c; 
				break; 
			case 7: 
				if (charToken == '/') { 
					return new Token("*/", -30, lineNo); 
				} else { 
					token = "*"; 
					input.reset(); 
					return new Token(token, Type.MULTI, lineNo); 
				} 
			case 8: 
				if (isLetter(charToken)) { 
					state = 9; 
					token2 = String.valueOf(charToken); 
					input.mark(2); 
					c = input.read(); 
					charToken = (char) c; 
				} else 
					reSet(); 
				break; 
			case 9: 
				if (isLetter(charToken) || isDigit(charToken) 
						|| charToken == '_') { 
					token2 += String.valueOf(charToken); 
					state = 9; 
					input.mark(2); 
					c = input.read(); 
					charToken = (char) c; 
				} else 
					state = 10; 
				break; 
			case 10: 
				token = token2; 
				if (token2.endsWith("_")) { 
					return new Token(token, -31, lineNo); 
				} else { 
					input.reset(); 
					return new Token(token, getIdenType(token), lineNo); 
				} 
			case 11: 
				if (isDigit(charToken)) { 
					state = 12; 
					token2 = String.valueOf(charToken); 
					input.mark(2); 
					c = input.read(); 
					charToken = (char) c; 
				} else 
					reSet(); 
				break; 
			case 12: 
				if (isDigit(charToken) || charToken == '.') { 
					token2 += String.valueOf(charToken); 
					state = 12; 
					input.mark(1); 
					c = input.read(); 
					charToken = (char) c; 
				} else 
					state = 13; 
				break; 
			case 13: 
				if (isLetter(charToken)) { 
					token = token2 + charToken; 
					return new Token(token, -32, lineNo); 
				} else { 
					try { 
						if (token2.contains(".")) { 
							if (token2.endsWith(".")) { 
								token = token2; 
								return new Token(token, -33, lineNo); 
							} else { 
								double num = Double.parseDouble(token2); 
								token2 = "" + num; 
							} 
						} else { 
							int num = Integer.parseInt(token2); 
							token2 = "" + num; 
						} 
						if (token.equals("<->")) { 
							token = "-" + token2; 
						} else 
							token = token2; 
						input.reset(); 
						return new Token(token, Type.NUM, lineNo); 
					} catch (NumberFormatException nfe) { 
						token = token2; 
						return new Token(token, -35, lineNo); 
					} 
				} 
			case 14: 
				if (isOper(charToken)) { 
					state = 0; 
				} else if (isLetter(charToken)) { 
					state = 8; 
				} else if (isDigit(charToken)) 
					state = 11; 
				else 
					state = 15; 
				break; 
			case 15:// 16£ºerror 
				token = String.valueOf(charToken); 
				if (charToken == '$' & input.readLine() == null) { 
					return new Token(token, Type.END, lineNo); 
				} else { 
					return new Token(token, -34, lineNo); 
				} 
			} 
		} 
		if (state == 5 || state == 6) { 
			return new Token("/*", -30, lineNo); 
		} 
		return null; 
	} 
}