编译原理 mJava语法分析实验(MJava的语法规则和课程设计要求)

温馨提示

本次实验用的输入文件是词法分析实验中输出的toketOut.txt,具体格式可以前往该实验查看。

MJava的语法规则

Goal-> MainClass { ClassDeclaration } EOF

MainClass->
"class" Identifier "{" "public" "static" "void" "main" "(" "String" "[" "]" Identifier ")" "{" Statement "}" "}"

ClassDeclaration->
"class" Identifier [ "extends" Identifier ] "{"{ VarDeclaration } { MethodDeclaration } "}"

VarDeclaration ->Type Identifier ";"

MethodDeclaration->
"public" Type Identifier "(" [ Type Identifier { "," Type Identifier } ] ")" "{" { VarDeclaration } { Statement } "return" Expression ";" "}"

Statement->"{" { Statement } "}"|"if" "(" Expression ")" Statement "else" Statement |"while" "(" Expression ")" Statement |"System.out.println" "("  Expression ")" ";"| Identifier "=" Expression ";"| Identifier "[" Expression "]" "=" Expression ";"

Type->"int" "[" "]"|"boolean"|"int"| Identifier

Expression-> Expression  ( "&&" | "<" | "+" | "-" | "*" ) Expression | Expression "[" Expression "]"| Expression "." "length"| Expression "." Identifier "(" [ Expression { "," Expression } ] ")"| IntegerLiteral |"true"|"false"| Identifier |"this"|"new" "int" "[" Expression "]"|"new" Identifier "(" ")"| "!" Expression |"(" Expression ")"

注意事项

1) EOF 表示的是词法分析器在扫描到文件尾时返回的token
2) 未被引号包裹的()[]{}范式中的符号,而非词法分析中解析的token。
()表示优先级 []表示可选 {}表示重复至少0次
3) 空白、换行符和制表符在词法分析时忽略掉。

语法分析程序课程设计要求

语法分析程序设计与实现需要按照以下要求完成。
1)为描述语法规则的文法给出相应的抽象语法树结构,提交相应的语法树定义的文件,语法树的定义尽量简洁易懂,必要时提供说明(25分)。
2)写出识别语法范畴的语法分析程序,提交相应的可执行源程序。该语法分析程序的具体要求如下(75分):
(1)该语法分析程序需要读取词法分析的结果即读取文件tokenOut.txt中的单词序列进行语法分析。
(2)将tokenOut.txt中的表达式经语法分析后将结果表示为相应的抽象语法树。
(3)将语法分析的结果打印到文件SyntaxOut.txt中。
(4)给出测试方法描述,提交readme.doc,如果你还有其它需要说明的问题 须写在readme.doc中。

代码实现

我们采用递归下降分析算法,因为之前尝试LR(1)的时候发现竟然出现了上百个状态,靠手动编码非得类似不可,还很难排错。
原本写了一个几乎是面向过程的递归下降分析,结果是错漏百出,各种问题层出不穷,故做了一些封装,采用面向对象的思维来完成本次实验。

思路

递归下降需要消除左递归才能正确运行,观察上述文法,我们可以发现其中大部分规则都不含左递归,只有Expression需要我们“特别关照。”
我们展开Expression的内容,发现可以分为4大类:

// Expression -> Expression F
Expression->Expression  ( "&&" | "<" | "+" | "-" | "*" ) Expression
Expression->Expression "[" Expression "]"
Expression->Expression "." "length"
Expression->Expression "." Identifier "(" [ Expression { "," Expression }] ")"
// Expression -> G Expression H
Expression->"new" "int" "[" Expression "]" 
Expression->"(" Expression ")"
// Expression -> "!" Expression
Expression->"!" Expression
// Expression -> A
Expression->IntegerLiteral 
Expression->"true"
Expression->"false"
Expression->Identifier
Expression->"this"
Expression->"new" Identifier "(" ")"

因此,我们得到

Expression -> Expression F
Expression -> G Expression H
Expression -> "!" Expression //用一个while循环单独处理
Expression -> A

记Expression为E,将为消除左递归引入的新非终结符表示为E’,可得:

E’-> FE’| ε
E -> GEH E’
E -> !E E’
E -> A E’

为了与实验要求中的表达式尽量保持一致,后续编程中仍将E写为Expression,将E’写为Exp。

Token.java

public class Token {
	static StringBuilder sb = new StringBuilder();
	String token;
	int type;
	Token(String t,int ty){
		sb.delete(0, sb.length());
		sb.append(t);
		token = sb.toString();
		type = ty;
	}
	public String getToken() {
		return token;
	}
	public void resetToken(String t,int ty) {
		sb.delete(0, sb.length());
		sb.append(t);
		token = sb.toString();
		type = ty;
	}
 	public int getType() {
		return type;
	}
 	
	public static String typeStr(int type){
		switch(type) {
			case 1: return "NUM";
			case 2: return "SIGN";
			case 3: return "IDENTIFIER";
			case 4: return "KEY_WORD";
		}
		return "ERROR";
	}
	public String toString() {
		sb.delete(0, sb.length());
		//sb.append("语句:").append(token).append("  类型:").append(typeStr(type));
		sb.append(token).append("\t").append(type);
		return sb.toString();
	}
}

mJava_word.java

这个是上次的词法分析代码,有微调

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;


public class mJava_word {
	static String[] keyWords = { "boolean", "class", "else", "extends", "if", "int", "length", "main", "new", "public",
			"return", "static", "String", "System.out.println", "this", "void", "while", "FALSE", "TRUE" };
	static String[] token_sign = { "[", "]", "(", ")", "{", "}", ",", ";", "=", "&&", "<", "+", "-", "*", ".", "!"};
	
	static boolean is_white_space(char ch) {
		return (ch==' '||ch=='\n'||ch=='\t'||ch=='\r');
	}

	static boolean is_keyWord(String str) {
		for (String key : keyWords) {
			if (key.equals(str))
				return true;
		}
		return false;
	}

	static boolean is_token_sign(String str) {
		for (String sign : token_sign) {
			if (sign.equals(str))
				return true;
		}
		return false;
	}

	static boolean is_identifier_letter(char ch) {
		return (('a' <= ch && ch <= 'z') || ('A' < ch && ch < 'Z'));
	}

	static boolean is_number(char ch) {
		return ('0' <= ch && ch <= '9');
	}

	static final int START = 0;
	static final int NUM = 1;
	static final int SIGN = 2;
	static final int IDENTIFIER = 3;
	static final int KEY_WORD = 4;
	static boolean END = false;
	static boolean ERROR = false;

	public static void main(String args[]) throws Exception {
		String path = "test.txt";
		String path_= "tokenOut.txt";
		File f = new File(path);
		File f_= new File(path_);
		FileInputStream fin = new FileInputStream(f);
		//FileOutputStream fout = new FileOutputStream(f_);
		List<Token> tokens = new ArrayList<>();
		int c;
		int global_index = 0;
		int row = 1, col = 1;
		int state = START;
		StringBuilder sb = new StringBuilder();
		StringBuilder ofs= new StringBuilder();
		String errMsg = null;
		while ((c = fin.read()) != -1) {
			char ch = (char)c;
			++global_index;
			++col;
			if (!END) {
				switch (state) {
				case START: {
					if(ch=='\n') {row++;col=1;}
					if(is_white_space(ch)) break;
					sb.delete(0, sb.length());
					sb.append(ch);
					//单独处理双字符符号
					if (ch == '&') {state = SIGN;break;}
					//数字打头的判定为数字
					if (is_number(ch))
						state = NUM;
					//遇上字母开头的先认定为标识符,具体是否为关键词稍后判定
					else if (is_identifier_letter(ch))
						state = IDENTIFIER;
					//大部分都是单字符符号
					else if (is_token_sign(sb.toString())) {state = SIGN;END = true;}
					//出现非法字符且在首位
					else {
						END = true;
						ERROR = true;
						errMsg = "非法字符(0x01)";
					}
					break;
				}
				//处理&&出现的情况
				case SIGN:{
					if(ch=='&') {sb.append(ch);END = true;}
					else {sb.append(ch);ERROR = true;END = true;}
					break;
				}
				case NUM:{
					//正常情况下直接将数字追加到当前字符串即可
					if(is_number(ch)) sb.append(ch);
					//如果数字后面直接附加了运算符,将数字保存,并正常处理符号
					else {
						if(ch=='\n') {row++;col=1;}
						if(is_white_space(ch)) {
							END = true;
						}else if(ch=='&' && !ERROR) {
							tokens.add(new Token(sb.toString(),state));
							sb.delete(0, sb.length());
							sb.append(ch);
							state = SIGN;
						}else if(is_token_sign(String.valueOf(ch))){
							tokens.add(new Token(sb.toString(),state));
							tokens.add(new Token(String.valueOf(ch),SIGN));
							state = START;
						}else {
							sb.append(ch);
							ERROR = true;
							errMsg = "非法数字(0x02)";
						}
					}
					break;
				}
				case IDENTIFIER:{
					if(ch=='\n') {row++;col=1;}
					if(is_white_space(ch)) END = true;
					else if(ch=='&' && !ERROR) {
						tokens.add(new Token(sb.toString(),state));
						sb.delete(0, sb.length());
						sb.append(ch);
						state = SIGN;
					}
					else if(is_token_sign(String.valueOf(ch)) && !ERROR) {
						tokens.add(new Token(sb.toString(),state));
						tokens.add(new Token(String.valueOf(ch),SIGN));
						state = START;
					}
					else if(is_identifier_letter(ch)||is_number(ch)||ch=='_') sb.append(ch);
					else {
						sb.append(ch);
						ERROR = true;
						errMsg = "非法标识符(0x03)";
					}
					break;
				}
			  }
			};
			if(END) {
				if(ERROR) {
					tokens.add(0, new Token(sb.toString(), -1));
					System.err.println(sb.toString() + "出现错误[" + errMsg + "],位置:" + (global_index-sb.length()) + "(" + row + "行" + col + "列)");
					//ofs.append(sb.toString()).append("出错[").append(errMsg).append("],位置:").append(global_index-sb.length()).append("(").append(row).append("行").append(col).append("列)\n");
				}else {
					if(is_keyWord(sb.toString())) state = KEY_WORD;
					tokens.add(new Token(sb.toString(),state));
				}
				state = START;
				END = false;
				ERROR = false;
			}
		}
		fin.close();
		
		//专门针对System.out.println进行处理
		for(int i=0;i < tokens.size() - 4;i++) {
			if(tokens.get(i).getToken().equals("System")) {
				sb.delete(0, sb.length());
				// System . out . println
				sb.append(tokens.get(i).getToken()).append(tokens.get(i+1).getToken())
				.append(tokens.get(i+2).getToken()).append(tokens.get(i+3).getToken())
				.append(tokens.get(i+4).getToken());
			}
			if(sb.toString().equals("System.out.println")) {
				tokens.get(i).resetToken("System.out.println", KEY_WORD);
				//将后面4个Token删除,注意由于下标移动,只要一直删除第i+1个即可
				tokens.remove(i+1);
				tokens.remove(i+1);
				tokens.remove(i+1);
				tokens.remove(i+1);
			}
			sb.delete(0, sb.length());
		}
		//ofs.append("\n--------------\n以下是被识别的语句:\n");
		for(Token token:tokens) {
			System.out.println(token);
			ofs.append(token).append("\n");
		}
		
		FileOutputStream fout = new FileOutputStream(f_);
		fout.write(ofs.toString().getBytes());
		fout.close();
	}
}

mJava_grammar.java

这个是我们本次实验写的语法分代码

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


class tokenList{
	private int CURRENT_TokenPOS = 0;
	private static List<Token> tokenList = new ArrayList<>();
	private static List<String> errorLog = new ArrayList<>();
	private static StringBuilder sb = new StringBuilder();
	public void add(Token t) {
		tokenList.add(t);
	}
	
	public String toString() {
		if(errorLog.size()==0) return "no syntax error detected!\n";
		else {
			sb.delete(0, sb.length());
			for(String err:errorLog) {
				sb.append(err).append("\n");
			}
			return sb.toString();
		}
	}
	
	public Token currentToken() {
		if(CURRENT_TokenPOS > tokenList.size()) return null;
		else return tokenList.get(CURRENT_TokenPOS);
	}
	
	public Token getToken(int relativePos) {
		int pos = CURRENT_TokenPOS + relativePos;
		if(0< pos && pos < tokenList.size()) return tokenList.get(pos);
		else return new Token("", 0);
	}

	private void log(String reason) {
		sb.delete(0, sb.length());
		sb.append("an error occured near ").append(getToken(-1).getToken()).append(" ")
		.append(getToken(0).getToken()).append(" ").append(getToken(1).getToken()).append(" :").append(reason);
		errorLog.add(sb.toString());
	}
	
	public void removeLastErr() {
		//errorLog.remove(errorLog.size()-1);
	}
	
	public void goBack() {
		--CURRENT_TokenPOS;
	}
	
	public boolean match(int type) {
		return match(type,true);
	}
	/**
	 * 按类型匹配词法分析的结果,只有在正确匹配后位置才会后移
	 * @param type 类型
	 * @param must 是否必须匹配,如果为是匹配不上会报错
	 * @return 
	 * @return
	 */
	public boolean match(int type, boolean must) {
		if(CURRENT_TokenPOS>=tokenList.size()||CURRENT_TokenPOS<0) return false;
		if(tokenList.get(CURRENT_TokenPOS).getType()==type) {
			++CURRENT_TokenPOS;
			return true;
		}else if(must) {
			log(Token.typeStr(type) + " expected");
			return false;
		}
		return false;
	}
	
	public boolean match(String[] tokens) {
		for(String t:tokens) {
			if(!match(t)) return false;
		}
		return true;
	}
	
	public boolean match(String token) {
		return match(token,true);
	}
	/**
	 * 按单词匹配词法分析的结果,只有在正确匹配后位置才会后移
	 * @param token 单词
	 * @param must 是否必须匹配,如果为是匹配不上会报错
	 * @return
	 */
	public boolean match(String token, boolean must) {
		if(CURRENT_TokenPOS>=tokenList.size()||CURRENT_TokenPOS<0) return false;
		if(tokenList.get(CURRENT_TokenPOS).getToken().equals(token)) {
			++CURRENT_TokenPOS;
			return true;
		}else if(must) {
			log(token + " expected");
			return false;
		}
		return false;
	}
	
}

class SyntaxTreeNode{
	String name;
	String value;
	
	private static final int JSON = 2333;
	private static final int XML =  3222;
	
	public SyntaxTreeNode(String name) {
		this.name = name;
		this.value = null;
	}
	public SyntaxTreeNode(String name,String value) {
		this.name = name;
		this.value= value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	private static StringBuilder sb = new StringBuilder();
	List<SyntaxTreeNode> subNode = new ArrayList<>();
	public void add(SyntaxTreeNode s) {
		if(s!=null)
			subNode.add(s);
	}
	
	private void toString(int level,int format) {
		//默认情况下,按照层级关系输出语法树
		if(format!=JSON&&format!=XML) {
			//for(int i=0;i<level;i++) sb.append('\t');
			//sb.append("SyntaxTree at level ").append(level).append('\n');
			for(int i=0;i<level;i++) sb.append('\t');
			sb.append(name);
			if(value!=null) sb.append(" --> ").append(value);
			sb.append('\n');
			if(subNode.size()>0) {
				for(int i=0;i<level;i++) sb.append('\t');
				sb.append(" subNode(s):\n");
				for(SyntaxTreeNode s : subNode) {
					s.toString(level + 1,format);
				}
			}
			//for(int i=0;i<level;i++) sb.append('\t');
			//sb.append("exit\n");
		}
		if(format==JSON) {
			//按照json格式输出语法树(可以用标准工具解析)
			sb.append('{');
			sb.append("\"name\":").append('"').append(name).append('"');
			if(value!=null) sb.append(',').append("\"value\":").append('"').append(value).append('"');
			if(subNode.size()==0) {sb.append('}');return;}
			sb.append(',').append("\"subNode\":[");
			for(SyntaxTreeNode s : subNode) {
				s.toString(level+1,format);
				sb.append(',');
			}
			//删掉多余的逗号
			sb.deleteCharAt(sb.length()-1);
			sb.append(']');
			sb.append('}');
			
		}else if(format==XML) {
			//按照xml格式输出语法树(可以用标准工具解析)
			for(int i=0;i<level;i++) sb.append('\t');
			sb.append("<").append(name);
			if(value!=null) sb.append(" value=\"").append(value).append('"');
			if(subNode.size()==0) {sb.append("/>\n");return;}
			sb.append('>').append('\n');
			for(SyntaxTreeNode s:subNode) {
				s.toString(level+1,format);
			}
			for(int i=0;i<level;i++) sb.append('\t');
			sb.append("</").append(name).append('>').append('\n');
		}
	}
	

	public String toString() {
		sb.delete(0, sb.length());
		toString(0,XML);
		return sb.toString();
	}
}

public class mJava_grammar {
	
	private static final int NUM = 1;
	//private static final int SIGN = 2;
	private static final int IDENTIFIER = 3;
	//private static final int KEY_WORD = 4;
	private static tokenList T = new tokenList();
	//private static StringBuilder result = new StringBuilder();
	//private static List<Token> tokenList = new ArrayList<>();
	
	/**
	 * 读取词法分析的结果,并保存在特定的数据结构中
	 * @param filePath
	 * @throws IOException
	 */
	private static void readToken(String filePath,tokenList tl) throws IOException {
		FileInputStream fin = new FileInputStream(new File(filePath));
		int c;
		boolean isType = false;
		StringBuilder Tokenname = new StringBuilder();
		while((c = fin.read())!=-1) {
			char ch = (char)c;
			if(!isType) {
				switch(ch) {
					case '\t':{
						isType = true;
						break;
					}
					case '\n':{
						break;
					}
					default:{
						Tokenname.append(ch);
					}
				}
			}else {
				isType = false;
				if(c == '-') {
					fin.close();
					System.err.println("词法分析结果中有错误,请修改后再运行程序");
					return;
				}
				c -= '0';
				tl.add(new Token(Tokenname.toString(), c));
				Tokenname.delete(0, Tokenname.length());
			}
		}
		fin.close();
	}
	
	private static SyntaxTreeNode Goal() {
		SyntaxTreeNode goal = new SyntaxTreeNode("Goal");
		goal.add(MainClass());
		SyntaxTreeNode classDec = ClassDeclaration();
		while(classDec!=null) {
			goal.add(classDec);
			classDec = ClassDeclaration();
		}
		T.removeLastErr();
		return goal;
	}
	
	private static SyntaxTreeNode Identifier() {
		if(T.match(IDENTIFIER,false)) {
			return new SyntaxTreeNode("Identifier", T.getToken(-1).getToken());
		}else return null;
	}
	
	
	private static SyntaxTreeNode MainClass() {
		SyntaxTreeNode mainclass = null;
		if(T.match("class")) {
			//System.out.println("mainClass found!");
			mainclass = new SyntaxTreeNode("MainClass");
			//识别并加入标识符
			mainclass.add(Identifier());
			//快速匹配固定内容的字符串
			if(!T.match(new String[] {"{","public","static","void","main","(","String","[","]"})) return null;
			//加入下一个标识符
			mainclass.add(Identifier());
			//匹配固定内容的字符串
			if(!T.match(new String[] {")","{"})) return null;
			//目前正确匹配到此处
			//匹配Statement,只有一个
			mainclass.add(Statement());
//			for(int i = -3;i<4;i++) {
//				System.err.print(T.getToken(i).getToken());
//			}
			if(!T.match(new String[] {"}","}"})) return null;
			//System.out.println(mainclass);

			return mainclass;
		}
		return null;
	}

	private static SyntaxTreeNode Statement() {
		SyntaxTreeNode statement = new SyntaxTreeNode("Statement");
		// Statement->"{"{Statement}"}"
		if(T.match("{",false)) {
			SyntaxTreeNode st = Statement();
			while(st!=null) {
				statement.add(st);
				st = Statement();
			}
			if(!T.match("}")) return null;
			
			// Statement->"if" "(" Expression ")" Statement "else" Statement
		}else if(T.match("if",false)) {
			if(!T.match("(")) return null;
			statement.add(Expression());
			if(!T.match(")")) return null;
			statement.add(Statement());
			if(!T.match("else")) return null;
			statement.add(Statement());
			
			//Statement->"while" "(" Expression ")" Statement 
		}else if(T.match("while",false)) {
			statement.setValue("loop sequence");
			if(!T.match("(")) return null;
			statement.add(Expression());
			if(!T.match(")")) return null;
			statement.add(Statement());
			
			//"System.out.println" "("  Expression ")" ";"
		}else if(T.match("System.out.println",false)) {
			statement.setValue("output sequence");
			if(!T.match("(")) return null;
			statement.add(Expression());
			if(!T.match(")")) return null;
			if(!T.match(";")) return null;
		}else {
			//在这里匹配以标识符开头的情况
			SyntaxTreeNode Id = Identifier();
			if(Id == null) return null;
			
			statement.add(Id);
			//Statement-> Identifier "=" Expression ";"
			if(T.match("=",false)) {
				statement.setValue("assignment");
				//System.out.println("Statement-> Identifier \"=\" Expression \";\"");
				statement.add(Expression());
				if(!T.match(";")) return null;
				
				//Statement->Identifier "[" Expression "]" "=" Expression ";"
			}else if(T.match("[",false)) {
				statement.add(Expression());
				if(!T.match("]")) return null;
				if(!T.match("=")) return null;
				statement.add(Expression());
				if(!T.match(";")) return null;
			}
		}
		return statement;
		
	}

	
	//以下是表达式六人帮,成员有 Expression() 队长 和 5个辅助G() H() A() F() Exp() 
	private static SyntaxTreeNode Expression() {
		
		SyntaxTreeNode expression = new SyntaxTreeNode("Expression");
		//Expression -> !Expression Exp
		if(T.match("!",false)) {
			boolean falseExp = false; 
			//消除掉连续的 非运算符
			while(T.match("!",false)) {falseExp = !falseExp;}
			if(falseExp) expression.add(new SyntaxTreeNode("logical", "false"));
			expression.add(Expression());
			expression.add(Exp());
		}
		
		//E -> A Exp
		SyntaxTreeNode helper = A();
		if(helper!=null) {
			expression.add(helper);
			expression.add(Exp());
		}else {
			helper = G();
			// E -> GEH Exp
			if(helper!=null) {
				expression.add(helper);
				expression.add(Expression());
				expression.add(H());
				expression.add(Exp());
			}else return null;
		}
		
		return expression;
	}

	private static SyntaxTreeNode H() {
		if(T.match("]",false)) return new SyntaxTreeNode("H","]");
		if(T.match(")",false)) return new SyntaxTreeNode("H",")");
		return null;
	}

	private static SyntaxTreeNode G() {
		// new int [
		if(T.match("new",false)) {
			//int 没有匹配上,new 可能是A()的成分
			if(!T.match("int",false)) {
				return null;
			}
			if(T.match("[")) {
				return new SyntaxTreeNode("G","new int [");
			}
			// (
		}else if(T.match("(",false)) return new SyntaxTreeNode("G","(");
		
		return null;
	}

	private static SyntaxTreeNode A() {
		SyntaxTreeNode INT = IntegerLiteral();
		if(INT!=null) {
			SyntaxTreeNode a = new SyntaxTreeNode("A","IntegerLiteral");
			a.add(INT);
			return a;
		}
		
		SyntaxTreeNode Id = Identifier();
		if(Id!=null) {
			SyntaxTreeNode a = new SyntaxTreeNode("A","Identifier");
			a.add(Id);
			return a;
		}
		
		if(T.match("true",false)) return new SyntaxTreeNode("A","true");
		if(T.match("false",false)) return new SyntaxTreeNode("A","false");
		if(T.match("this",false)) return new SyntaxTreeNode("A","this");
		if(T.match("new",false)) {
			Id = Identifier();
			if(Id==null) {
				T.goBack();
				return null;
			}else {
				SyntaxTreeNode a = new SyntaxTreeNode("A","new Identifier()");
				a.add(Id);
				return a;
			}
		}
		return null;
	}

	private static SyntaxTreeNode IntegerLiteral() {
		if(T.match(NUM,false)) {
			return new SyntaxTreeNode("IntegerLiteral", T.getToken(-1).getToken());
		}else return null;
	}

	private static SyntaxTreeNode Exp() {
		SyntaxTreeNode f = F();
		//System.out.println(f);
		// Exp -> ε
		if(f==null) return null;
		// Exp -> F Exp
		SyntaxTreeNode exp = new SyntaxTreeNode("exp");
		exp.add(f);
		exp.add(Exp());
		//System.out.println(exp);
		return exp;
	}

	private static SyntaxTreeNode F() {
		// F-> ( "&&" | "<" | "+" | "-" | "*" ) Expression
		SyntaxTreeNode f = new SyntaxTreeNode("F");
		if(T.match("&&",false)||T.match("<",false)||T.match("+",false)||T.match("-",false)||T.match("*",false)) {
			f.setValue(T.getToken(-1).getToken());
			f.add(Expression());
			return f;
			// F -> "[" Expression "]"
		}else if(T.match("[",false)) {
			f.add(Expression());
			if(!T.match("]")) return null;
			else return f;
		}else if(T.match(".",false)) {
			// F -> "." "length"
			if(T.match("length",false)) {f.setValue(".length");return f;}
			
			// F -> "." Identifier "(" [ Expression { "," Expression }] ")"
			SyntaxTreeNode Id = Identifier();
			if(Id!=null) {
				f.add(Id);
				if(!T.match("(")) return null;
				SyntaxTreeNode exp = Expression();
				f.add(exp);
				while(T.match(",",false)||exp!=null) {
					exp = Expression();
					f.add(exp);
				}
				if(!T.match(")")) return null;
				return f;
			}else return null;
		}
		return null;
	}

	private static SyntaxTreeNode ClassDeclaration() {
		// "class"
		if(T.match("class")) {
			SyntaxTreeNode classDeclaration = new SyntaxTreeNode("ClassDeclaration");
			// Identifier
			classDeclaration.add(Identifier());
			// [extends Identifier]
			if(T.match("extends",false)) classDeclaration.add(Identifier());
			// {
			if(!T.match("{")) return null;
			//System.out.println("----------------------------");
			
			// {VarDeclaration}
			//尝试匹配变量声明
			SyntaxTreeNode varD = VarDeclaration();
			//System.out.println(varD);
			while(varD != null) {
				//System.out.println(varD);
				classDeclaration.add(varD);
				varD = VarDeclaration();
			}
			T.removeLastErr();
			// {MethodDeclaration}
			//尝试匹配方法声明
			SyntaxTreeNode methodD = MethodDeclaration();
			while(methodD!= null) {
				classDeclaration.add(methodD);
				methodD = MethodDeclaration();
			}
			//循环退出时会产生误报,故消除
			T.removeLastErr();
			
			if(!T.match("}")) return null;
			return classDeclaration;
		}else return null;
	}

	private static SyntaxTreeNode MethodDeclaration() {
		SyntaxTreeNode methodD = new SyntaxTreeNode("MethodDeclaration");
		if(!T.match("public",false)) return null;
		methodD.add(Type());
		methodD.add(Identifier());

		if(!T.match("(")) return null;
		SyntaxTreeNode tp = Type();
		SyntaxTreeNode id = null;
		//[ Type Identifier
		if(tp!=null) {
			methodD.add(tp);
			id = Identifier();
			if(id==null) return null;
			methodD.add(id);
			// { "," Type Identifier } ]
			while(T.match(",",false)&&tp!=null) {
				tp = Type();
				id = Identifier();
				methodD.add(tp);
				methodD.add(id);
			}
		}
		// ")" "{"
		if(!T.match(")")) return null;
		if(!T.match("{")) return null;
		//System.out.println("now near VarDeclaration!" + T.getToken(0).getToken());
		SyntaxTreeNode vd = VarDeclaration();
		while(vd != null) {
			methodD.add(vd);
			vd = VarDeclaration();
		}
		
		//System.out.println("now near Statement!" + T.getToken(0).getToken());
		SyntaxTreeNode st = Statement();
		while(st!=null) {
			methodD.add(st);
			st = Statement();
		}
		
		if(!T.match("return")) {System.out.println("Method Declaration missing RETURN!");return null;}
		
		//System.out.println(methodD);
		
		methodD.add(Expression());
		if(!T.match(";")) return null;
		if(!T.match("}")) return null;
		return methodD;
	}

	private static SyntaxTreeNode Type() {
		// TODO 自动生成的方法存根
		//boolean
		//System.out.println("Type confiming... " + T.getToken(0).getToken());
		if(T.match("boolean",false)) return new SyntaxTreeNode("Type","boolean");
		if(T.match("int",false)) {
			if(T.match("[",false)) {
				// int[]
				if(T.match("]")) return new SyntaxTreeNode("Type","int[]");
				else return null;
			}else {
				// int
				//System.out.println("Type ---- int");
				return new SyntaxTreeNode("Type","int");
			}
		}
		SyntaxTreeNode Id = Identifier();
		if(Id==null) return null;
		else {
			SyntaxTreeNode tp = new SyntaxTreeNode("Type","Identifier");
			tp.add(Id);
			return tp;
		}
	}

	private static SyntaxTreeNode VarDeclaration() {
		SyntaxTreeNode vd = new SyntaxTreeNode("VarDeclaration");
		// Type
		SyntaxTreeNode tp = Type();
		if(tp!=null) vd.add(tp);
		else return null;
		//System.out.println(vd);
		// Identifier
		//注意之前的Type可以为Identifier,所以如果此处匹配失败,先前的步骤要回退!
		SyntaxTreeNode Id = Identifier();
		if(Id!=null) vd.add(Id);
		else {T.goBack();return null;}
		
		// ";"
		if(!T.match(";")) return null;
		return vd;
	}

	public static void main(String[] args) throws IOException {
		
		// TODO 自动生成的方法存根
		readToken("tokenOut.txt",T);
		//至此,我们成功读取了词法分析的结果,保存在T中,只有在词法分析无错误的时候,才进行语法分析
		//本次分析采用递归下降法
		//通过Goal() 启动分析
		SyntaxTreeNode root = Goal();
		
		System.err.println(root);
		FileOutputStream fout = new FileOutputStream(new File("SyntaxOut.xml"));
		fout.write(root.toString().getBytes());
		fout.close();
		System.err.println(T);
	}
}

drive.java

最后,再写一个驱动类,一次运行,直接按次序调用词法分析和语法分析,简化使用流程

public class drive {

	public static void main(String[] args) throws Exception {
		// TODO 自动生成的方法存根
		mJava_word.main(null);
		mJava_grammar.main(null);
	}
}

直接讲代码复制粘贴到你的Java项目中即可正常运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值