编译原理 - 递归向下法语法分析(Java版)
2017-12-23 15:11
387 查看
这个程序有些局限性,即不能分析任意语法。
分析的语法如下:
代码结构如下:
代码如下:
Main.java:
RecursionDown.java:
Util.java:
然后我们运行一下看一下效果:
有兴趣的可以试试分析一下其他的语法,代码有bug欢迎指出~
分析的语法如下:
代码结构如下:
代码如下:
Main.java:
package cn.porkbar.recursion; import java.io.IOException; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入要分析的文件路径,输入-1退出:"); String op; RecursionDown parser; while (sc.hasNext()) { op = sc.next(); if (op.equals("-1")) { System.out.println("谢谢使用!"); break; } else { try { parser = new RecursionDown(op); parser.Parser(); } catch (IOException e) { System.out.println("无法打开文件!"); } } System.out.println("*****************************\n请输入要分析的文件路径,输入-1退出:"); } } }
RecursionDown.java:
/* 规则: ⑴<程序>::=begin<语句串>end ⑵<语句串>::=<语句>{;<语句>} ⑶<语句>::=<赋值语句> ⑷<赋值语句>::=ID:=<表达式> ⑸<表达式>::=<项>{+<项> | -<项>} ⑹<项>::=<因子>{*<因子> | /<因子> ⑺<因子>::=ID | NUM | (<表达式>) syn映射表: -1:未知的符号 0:结束符$ 10:自定义变量名 1、2...9:begin和end关键字(3-9为保留串,后续可继续扩充) 11:数字 12、13、14、15:加减乘除符号 16:';'字符 17:':='字符 18、19:左右括号 */ package cn.porkbar.recursion; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import cn.porkbar.util.Util; public class RecursionDown { private File file; //要读取的文件 static private String[] rwtab = {"begin","end"}; //关键字映射表 private char[] pro = new char[1024*1024]; //可以读取1M以内的文件 private int pos; //扫描的位置 private int syn; //扫描结果的特征值,对应的映射表在上面注释 private StringBuffer token; //扫描出来的字符串 private int num; //扫描出来的数字 public RecursionDown(String road) throws IOException { file = new File(road); FileInputStream in = new FileInputStream(file); { int pos = 0; int t; while ((t = in.read()) != -1) pro[pos++] = (char)t; //Debug // System.out.println(new String(pro,0,pos)); } in.close(); pos = 0; System.out.println("待编译的本文为:"); System.out.println(String.valueOf(pro).trim()); } private boolean Scan() { char ch; do //忽略空格、换行符、制表符 { ch = pro[pos++]; }while (ch == ' ' || ch == '\t' || ch == '\n'); if (Util.isAlpha(ch)) { token = new StringBuffer(""); token.append(ch); while(Util.isAlpha(pro[pos]) || Util.isDigit(pro[pos])) { ch = pro[pos++]; token = token.append(ch); } //Debug // System.out.println(token.toString()); syn = 10; for (int i = 0 ; i < rwtab.length ; i++) { if (token.toString().equals(rwtab[i])) { syn = i+1; break; } } return true; } else if (Util.isDigit(ch)) { num = 0; num = ch-'0'; while (Util.isDigit(pro[pos])) num = num*10 + pro[pos++] - '0'; syn = 11; if (Util.isAlpha(pro[pos])) //后面如果跟上字母则出错 return false; return true; } else { switch(ch) { case '+': syn = 12; break; case '-': syn = 13; break; case '*': syn = 14; break; case '/': syn = 15; break; case ';': syn = 16; break; case ':': if (pro[pos] == '=') pos++; else { syn = -1; return false; } syn = 17; break; case '(': syn = 18; break; case ')': syn = 19; break; case '$': syn = 0; break; default: syn = -1; return false; } return true; } } private boolean SentenceAnalysis() { if (!Statement()) return false; while (syn == 16) //这个地方应该用循环,表示可以多个语句 { Scan(); if (!Statement()) return false; } return true; } private boolean Factor() { if (syn == 10 || syn == 11) { Scan(); return true; } if (syn == 18) { Scan(); if (!Expression()) return false; if (syn == 19) { Scan(); return true; } else { System.out.println("缺少')'!"); return false; } } else { System.out.println("因子编译出错!"); return false; } } private boolean Term() { if (!Factor()) return false; if (syn == 14 || syn == 15) { Scan(); if (!Factor()) return false; } return true; /*else if (syn == 16) //若项后面没有*或/号,也可能为空,不用出错处理,给上一级扫描即可 { Scan(); return true; } else { System.out.println("项编译出错!"); return false; }*/ } private boolean Expression() { if (!Term()) return false; if (syn == 12 || syn == 13) { Scan(); if (!Term()) return false; } return true; /*else if (syn == 2) //没有+-号丢给上一级处理 { Scan(); return true; } else { System.out.println("表达式编译出错!"); return false; }*/ } private boolean Statement() { if (syn == 10) //自定义变量名 { Scan(); if (syn == 17) { Scan(); if (!Expression()) return false; return true; } else { System.out.println("不合法的赋值语句!"); return false; } } else { System.out.println("不合法的变量名!"); return false; } } public void Parser() { Scan(); if (syn == 1) { Scan(); if (!SentenceAnalysis()) { return; } if (syn == 2) { Scan(); if (syn == 0) { System.out.println("语法分析成功!"); return; } else { System.out.println("没有找到合法的结束符!"); } } else System.out.println("代码结束符end读取出错!"); } else { System.out.println("代码开始符begin读取出错!"); } } }
Util.java:
package cn.porkbar.util; import java.util.ArrayList; public class Util { static public boolean isAlpha(char ch) //判断是否是字母 { if ((ch >= 'a' && ch <= 'z') || (ch >='A' && ch <= 'Z')) return true; return false; } static public boolean isDigit(char ch) { if (ch >= '0' && ch <= '9') return true; return false; } static public ArrayList<String> getItems(String str) { char[] chs = str.toCharArray(); ArrayList<String> items = new ArrayList<String>(); for (char ch : chs) { if (ch == '\'') { String t = items.get(items.size()-1) + "'"; items.remove(items.size()-1); items.add(t); } else { String t = Character.toString(ch); items.add(t); } } return items; } }
然后我们运行一下看一下效果:
有兴趣的可以试试分析一下其他的语法,代码有bug欢迎指出~
相关文章推荐
- java编译原理
- java编译原理
- 编译原理虎书java版本--Chapter 1
- java程序-编译原理实验
- 关于JAVA,特点,历史,编译式的语言&解释式的语言,什么是java?JDK?DOS?一次编译到处运行原理。
- Java编译原理
- Java的编译原理
- 【编译原理】语法分析(二)
- 编译原理-递归下降语法分析器(Java)
- Java编译原理写算符优先算法
- JVM原理(Java代码编译和执行的整个过程+JVM内存管理及垃圾回收机制)
- Java编译原理
- 预测分析法进行语法分析(编译原理)
- Java核心知识点-Java编译原理
- java编译运行原理
- 编译原理课程设计---用java写的SNLCompiler(简单嵌套语言SNL的编译程序)
- 编译原理实验二——语法分析(预测分析)
- Java版编译原理Chomsky文法判断Java版
- C C++ Java C# JS编译、执行过程的原理入门分析
- 编译原理知识(1)--Java实现本地时间获取