温馨提示
本次实验用的输入文件是词法分析实验中输出的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项目中即可正常运行。