哈工大编译原理实验2——语法分析
2016-03-05 15:18
351 查看
此次试验由于指导书的文法比较简单,且没有消除左递归(我懒),因此使用学长的文法,并加上了数组判断。
完整工程源代码:https://github.com/SalamanderJY/Compiler_Experiment
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); } } }
完整工程源代码:https://github.com/SalamanderJY/Compiler_Experiment
相关文章推荐
- 实现一个简单的计算器
- NOP(N) NOP_##N
- 编译器是如何工作的?(转)
- 写给想学java的朋友!
- 学java的必看!
- java中的加密!
- java中的使用类!
- LEX/FLEX词法分析器
- 如何模仿人的学习模式来教计算机程序解数学题?
- 上下文无关文法1
- 上下文无关文法2
- 编译原理——词法分析器
- 编译原理预习笔记------名词理解
- Simple scanner of c
- 编译原理:短语、直接短语、句柄、素短语
- 编译原理中FIRST集合与FOLLOW集合的算法
- 上下文无关文法解析
- 识别浮点常量问题-编译原理程序实现
- 计算的哲学(philosophy in coding)
- 编译原理 Chapter1 Introduction 第一章 简介