哈工大編譯原理實驗2——語法分析
阿新 • • 發佈:2019-01-05
此次試驗由於指導書的文法比較簡單,且沒有消除左遞迴(我懶),因此使用學長的文法,並加上了陣列判斷。
S -> func funcs funcs -> func funcs funcs -> $ func -> type IDN ( args ) func_body type -> int type -> short type -> long type -> char type -> float type -> double type -> void type -> unsigned type args -> type IDN arg args -> $ arg -> , type IDN arg arg -> $ func_body -> ; func_body -> block block -> { define_stmts stmts } define_stmts -> define_stmt define_stmts define_stmts -> $ define_stmt -> type IDN init vars ; init -> = expression init -> [ INT10 ] init -> $ vars -> , IDN init vars vars -> $ stmts -> stmt stmts stmts -> $ stmt -> assign_stmt stmt -> jump_stmt stmt -> iteration_stmt stmt -> branch_stmt assign_stmt -> expression ; jump_stmt -> continue ; jump_stmt -> break ; jump_stmt -> return isnull_expr ; iteration_stmt -> while ( logical_expression ) block_stmt iteration_stmt -> for ( isnull_expr ; isnull_expr ; isnull_expr ) block_stmt iteration_stmt -> do block_stmt while ( logical_expression ) ; branch_stmt -> if ( logical_expression ) block_stmt result result -> else block_stmt result -> $ logical_expression -> ! expression bool_expression logical_expression -> expression bool_expression bool_expression -> lop expression bool_expression bool_expression -> $ lop -> && lop -> || branch_stmt -> switch ( IDN ) { case_stmt case_stmts default_stmt } case_stmts -> case_stmt case_stmts case_stmts -> $ case_stmt -> case const : stmts default_stmt -> default : stmts block_stmt -> { stmts } isnull_expr -> expression isnull_expr -> $ expression -> value operation operation -> compare_op value operation -> equal_op value operation -> $ compare_op -> > compare_op -> >= compare_op -> < compare_op -> <= compare_op -> == compare_op -> != equal_op -> = equal_op -> += equal_op -> -= equal_op -> *= equal_op -> /= equal_op -> %= value -> item value' value' -> + item value' value' -> - item value' value' -> $ item -> factor item' item' -> * factor item' item' -> / factor item' item' -> % factor item' item' -> $ factor -> ( value ) factor -> IDN call_func factor -> const call_func -> ( es ) call_func -> $ es -> isnull_expr isnull_es isnull_es -> , isnull_expr isnull_es isnull_es -> $ const -> num_const const -> FLOAT const -> CHAR const -> STR num_const -> INT10 num_const -> INT8 num_const -> INT16
//獲取First集 public void getFirst(){ //終結符全部求出first集 ArrayList<String> first; //求出所有終結符的First集 for (int i = 0; i < terminals.size(); i++) { first = new ArrayList<String>(); first.add(terminals.get(i)); firsts.put(terminals.get(i), first); } //給所有非終結符註冊一下 for (int i = 0; i < nonterminals.size(); i++) { first = new ArrayList<String>(); firsts.put(nonterminals.get(i), first); } boolean flag; while (true) { flag = true; String left; String right; String[] rights; for (int i = 0; i < productions.size(); i++) { //遍歷每一個產生式 left = productions.get(i).returnLeft(); rights = productions.get(i).returnRights(); for (int j = 0; j < rights.length; j++) { //遍歷每個產生式右部的每個元素 right = rights[j]; //right是否存在,遇到空怎麼辦 //如果right不為空 if(!right.equals("$")) { for (int l = 0; l < firsts.get(right).size(); l++) { if(firsts.get(left).contains(firsts.get(right).get(l))){ continue; } else { firsts.get(left).add(firsts.get(right).get(l)); flag=false; } } } //如果右部可以為空 if (isCanBeNull(right)) { continue; } else { break; } } } if (flag == true) { break; } } //非終結符的first集 } //判斷是否產生$ public boolean isCanBeNull(String symbol) { String[] rights; for (int i = 0; i < productions.size(); i++) { //找到產生式 if (productions.get(i).returnLeft().equals(symbol)) { rights = productions.get(i).returnRights(); if (rights[0].equals("$")) { return true; } } } return false; }
//獲得Follow集 public void getFollow() { //所有非終結符的follow集初始化一下 ArrayList<String> follow; for (int i = 0; i < nonterminals.size(); i++) { follow = new ArrayList<String>(); follows.put(nonterminals.get(i), follow); } //將#加入到follow(S)中 follows.get("S").add("#"); boolean flag; boolean fab; while (true) { flag = true; //迴圈,遍歷所有產生式 for (int i = 0; i < productions.size(); i++) { String left; String right; String[] rights; rights = productions.get(i).returnRights(); //遍歷產生式右部 for (int j = 0; j < rights.length; j++) { right = rights[j]; //非終結符 if (nonterminals.contains(right)) { fab = true; for(int k = j+1; k < rights.length; k++) { //查詢first集 for(int v = 0; v < firsts.get(rights[k]).size(); v++) { //將後一個元素的first集加入到前一個元素的follow集中 if(follows.get(right).contains(firsts.get(rights[k]).get(v))) { continue; } else { follows.get(right).add(firsts.get(rights[k]).get(v)); flag=false; } } if (isCanBeNull(rights[k])) { continue; } else { fab = false; break; } } //如果存在一個產生式A→αB,或存在產生式A→αBβ且FIRST(β) 包含ε, //那麼 FOLLOW(A)中的所有符號都在FOLLOW(B)中 if(fab) { left = productions.get(i).returnLeft(); for (int p = 0; p < follows.get(left).size(); p++) { if (follows.get(right).contains(follows.get(left).get(p))) { continue; } else { follows.get(right).add(follows.get(left).get(p)); flag = false; } } } } } } //全部處理後跳出迴圈 if(flag==true){ break; } } //清除follow集中的# String left; for (int j = 0; j < nonterminals.size(); j++) { left = nonterminals.get(j); for (int v=0; v<follows.get(left).size(); v++) { if(follows.get(left).get(v).equals("#")) follows.get(left).remove(v); } } }
//獲取Select集
public void getSelect() {
String left;
String right;
String[] rights;
ArrayList<String> follow = new ArrayList<String>();
ArrayList<String> first = new ArrayList<String>();
for (int i = 0; i < productions.size(); i++) {
left = productions.get(i).returnLeft();
rights = productions.get(i).returnRights();
if(rights[0].equals("$")) {
// select(i) = follow(A)
follow = follows.get(left);
for (int j = 0; j < follow.size(); j++) {
if(productions.get(i).select.contains(follow.get(j))){
continue;
}
else {
productions.get(i).select.add(follow.get(j));
}
}
}
//如果文法G的第i個產生式為A→aβ,則定義
//SELECT(i)={a}
else {
boolean flag = true;
for (int j = 0; j < rights.length; j++) {
right = rights[j];
first = firsts.get(right);
for (int v = 0; v < first.size(); v++) {
if (productions.get(i).select.contains(first.get(v))) {
continue;
}
else {
productions.get(i).select.add(first.get(v));
}
}
if(isCanBeNull(right)) {
continue;
}
else {
flag = false;
break;
}
}
//First集中有空
if (flag) {
follow = follows.get(left);
for (int j = 0; j < follow.size(); j++) {
if (productions.get(i).select.contains(follow.get(j))) {
continue;
}
else {
productions.get(i).select.add(follow.get(j));
}
}
}
}
}
}
//語法分析
public void Parsing() {
//遍歷輸入緩衝區
/*for(int i = 0; i < inputCache.size(); i++) {
System.out.println(inputCache.get(i));
}*/
//初始符號壓入棧
stack.add("S");
String right;
String leftandinput;
String process="";
//當棧非空,輸入緩衝區存在
while (stack.size()>0 && inputCache.size()>0 ) {
//輸入緩衝區與推導符號串第一個字元相等的話,刪掉
try {
if(inputCache.get(0).equals(stack.get(stack.size()-1))) {
inputCache.remove(0);
stack.remove(stack.size()-1);
continue;
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
//匹配字元
leftandinput = stack.get(stack.size()-1)+"-"+inputCache.get(0);
//能夠找到匹配的
if((right=predictMap.get(leftandinput))!=null) {
//輸出產生式和推導過程
process = "";
for (int i = stack.size()-1; i>-1; i--) {
process = process + stack.get(i)+" ";
}
//輸出
DefaultTableModel tableModel = (DefaultTableModel) jtable4.getModel();
tableModel.addRow(new Object[] {stack.get(stack.size()-1)+" -> "+right, process});
jtable4.invalidate();
//刪掉產生的字元,壓入堆疊
stack.remove(stack.size()-1);
if(right.equals("$")) {
//只彈不壓
}
//壓入後序字元
else {
String[] arg = right.split(" ");
for(int i = arg.length-1; i>-1; i--) {
//反向壓入堆疊
stack.add(arg[i]);
}
}
}
//否則的話報錯
else {
//重新書寫process
process="";
for (int i = stack.size()-1; i>-1; i--) {
process = process + stack.get(i)+ " ";
}
//tbmodel_lex_result.addRow(new String[]{process, "ERROR! 無法識別的字元"+input_cache.get(0)+"產生式"+leftandinput});
DefaultTableModel tableModel = (DefaultTableModel) jtable2.getModel();
tableModel.addRow(new Object[] { "無法識別的字元:"+ inputCache.get(0),"產生式:"+leftandinput});
jtable4.invalidate();
inputCache.remove(0);
}
}
}