java编写简单的语法分析预测程序
编译原理课程中,编了一个简单的语法分析预测程序,这个程序时根据固定的文法得到预测分析表,然后编写程序来判断表达式是否会正确推到出来。
前提是程序没有左递归符合LL(1)文法:
文法如下:
E→TE'
E’ →+TE'|ε
T→FT'
T’ →*FT'|ε
F→(E)|i
为了程序便于编写将E'替换为e,T'替换为t
(2)FIRST集
FIRST(E)={(,i};
FIRST(E’)={+, ε};
FIRST(T)={(,i};
FIRST(T’)={ *, ε};
FIRST(F)={(,i};
(3)FALLOW集
FOLLOW(E)={),#};
FOLLOW(E’)={),#};
FOLLOW(T)={+,),#};
FOLLOW(T’)={+,),#};
FOLLOW(F)={*,+,),#};
(4)预测分析表
i |
+ |
* |
( |
) |
# |
|
E |
E->TE’ |
E->TE’ |
||||
E’ |
E’->+TE’ |
E’->ε |
E’->ε |
|||
T |
T->FT’ |
T->FT’ |
||||
T’ |
T’->ε |
T’->*FT’ |
T’->ε |
T’->ε |
||
F |
F->i |
F->(E) |
一、Stack.java
public class Stack {
private char s[];
private int top;
private int base;
private final int MAX = 200;
/**
*
* <p>Title: </p>
* <p>Description: 初始化栈</p>
*/
public Stack() {
initStack();
}
private void initStack() {
s = new char[MAX];
base = 0;
top = 0;
}
public boolean isEmpty() {
if(top == base) {
return true;
}else {
return false;
}
}
/**
*
* <p>Title: getTop</p>
* <p>Description: 获取栈顶元素</p>
* @return 返回栈顶元素
*/
public char getTop() {
return s[top-1];
}
/**
*
* <p>Title: push</p>
* <p>Description: 进栈方法</p>
* @param str 进栈的字符
*/
public void push(String str) {
for (int i = str.length() - 1; i >= 0; i--) {
s[top++] = str.charAt(i);
}
}
/**
*
* <p>Title: clear</p>
* <p>Description: 清空栈</p>
*/
public void clear() {
top = base;
} /**
*
* <p>Title: pop</p>
* <p>Description: 出栈</p>
* @return 栈顶元素出栈并返回出栈的元素
*/
public char pop() {
return s[--top];
}
/**
*
* <p>Title: size</p>
* <p>Description: 返回栈中元素个数</p>
* @return 栈中元素个数
*/
public int size() {
return top;
}
/**
* 打印栈里面的元素
*/
public String toString() {
StringBuffer tempStack = new StringBuffer();
for (int i = 0; i < top; i++) {
tempStack.append(s[i]);
}
return tempStack.toString();
}
}
二、GrammarAnalyze.java
package grammarAnalyze; public class GrapparAnalyze {
//分析表将E'替换为e,T'替换t
private String tab[][] = {
{ "$", "i", "+", "*", "(", ")", "#" },
{ "E", "Te", "$", "$", "Te", "$", "$" },
{ "e", "$", "+Te", "$", "$", "ε", "ε" },
{ "T", "Ft", "$", "$", "Ft","$", "$" },
{ "t", "$", "ε", "*Ft", "$", "ε", "ε" },
{ "F", "i", "$", "$", "(E)","$", "$" } };
private String input; //input中存放输入的表达式
private StringBuffer tempBuffer; //存放要输出的字符串
private int ptr, row, col, step; //指针,预测表中的行,列,当前步骤
private boolean symbol;
private Stack stack;
public GrapparAnalyze(){
stack = new Stack();
tempBuffer = new StringBuffer();
symbol=true;
input="";
stack.clear();
stack.push("#");
row=1;
ptr=0;
step=1;
}
public int column(char c) { //判断预测表中的列
switch (c) {
case 'i':
return 1;
case '+':
return 2;
case '*':
return 3;
case '(':
return 4;
case ')':
return 5;
case '#':
return 6;
default:
return -1;
}
}
public int line(char c) { //判定预测表中的行
switch (c) {
case 'E':
return 1;
case 'e':
return 2;
case 'T':
return 3;
case 't':
return 4;
case 'F':
return 5;
default:
return -1;
}
}
public void show(String str) {
tempBuffer.append(String.format("%-7d%-14s%-20s%-20s\r\n",
step, filter(stack.toString()), filter(input.substring(ptr)), filter(str)));
step++;
}
public void analyse() {
stack.push(tab[row][0]); //预测表中的第一个元素‘E’
show("初始化");
String tmp;
char ctmp; //栈顶元素
while (!(input.charAt(ptr) == '#' && stack.getTop() == '#')) {
ctmp = stack.getTop();//获取栈顶的元素
if (input.charAt(ptr) == ctmp) { //与栈顶元素比较
stack.pop();
ptr++;
show("" + ctmp + "匹配");
continue;
}
//判断ptr位置的终结符所在预测表的列位置
col = column(input.charAt(ptr));
if (col == -1) {
symbol = false;
show("未定义的字符");
ptr++;
break;
}
//判断栈顶位置所在预测表的行位置
row = line(ctmp);
if (row == -1) {
symbol = false;
show("出错");
stack.pop();
if (input.charAt(ptr) != '#') {
ptr++;
}
continue;
}
tmp = tab[row][col];
if (tmp.charAt(0) == '$') {
symbol = false;
show("出错");
stack.pop();
if (input.charAt(ptr) != '#') {
ptr++;
}
} else if (tmp.charAt(0) == 'ε') {
stack.pop();
show("" + ctmp + "->" + 'ε');
} else {
stack.pop();
stack.push(tmp);
show("" + ctmp + "->" + tmp);
}
}
}
//过滤方法将打印的字符串中e和t替换为E'和T'
public String filter(String src) {
if(src.contains("e") || src.contains("t")) {
StringBuffer result = new StringBuffer();
char item;
for(int i = 0;i < src.length(); i++) {
item = src.charAt(i);
if(item == 'e') {
result.append("E'");
continue;
}else if(item == 't') {
result.append("T'");
continue;
}
result.append(item);
}
return result.toString();
}else {
return src;
}
}
public String work(String inputExpression) {
input = inputExpression + '#';
symbol = true;
tempBuffer.append(String.format("%-8s%-20s%-20s%-20s\r\n",
"步骤","分析栈","剩余输入栈","所用产生式"));
analyse();
if (symbol) {
tempBuffer.append("\r是正确的符号串\r");
return tempBuffer.toString();
} else {
tempBuffer.append("\r不是正确的符号串\r");
return tempBuffer.toString();
} } public StringBuffer getTempBuffer() {
return tempBuffer;
}
public void setTempBuffer(StringBuffer tempBuffer) {
this.tempBuffer = tempBuffer;
}
public Stack getStack() {
return stack;
}
public void setStack(Stack stack) {
this.stack = stack;
}
public String[][] getTab() {
return tab;
}
public void setTab(String[][] tab) {
this.tab = tab;
}
public String getInput() {
return input;
}
public void setInput(String ns) {
this.input = ns;
}
public int getPtr() {
return ptr;
}
public void setPtr(int ptr) {
this.ptr = ptr;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public int getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
public boolean isBoo() {
return symbol;
}
public void setBoo(boolean boo) {
this.symbol = boo;
} }
三、主程序GrammarMain.java
package grammarAnalyze; import java.util.Scanner; public class GrammarMain {
public static void main(String[] args){
boolean isContinue = true;
while(isContinue) {
GrapparAnalyze analyze = new GrapparAnalyze();
Scanner scan = new Scanner(System.in);
System.out.println("请输入你要翻译的表达式:");
String inputExpression = scan.nextLine();
String srcdata = inputExpression.trim();
if("".equals(srcdata) || srcdata == null) {
System.out.println("输入表达式为空,请重新输入");
}else {
String result = analyze.work(srcdata);
System.out.println(result);
System.out.println("是否继续?y/n");
String yn = scan.nextLine();
if("no".equals(yn) || "n".equals(yn)) {
isContinue = false;
}
}
} } }
四、测试运行
java编写简单的语法分析预测程序的更多相关文章
- 编写简单的spring mvc程序,在tomcat上部署
编写简单的spring mvc程序,在tomcat上部署 1 用java 配置spring mvc ,可以省去web.xmlpackage hello;import org.springframewo ...
- VC++编写简单串口上位机程序
VC++编写简单串口上位机程序 转载: http://blog.sina.com.cn/s/articlelist_1809084904_0_1.html VC++编写简单串口上位机程序 串口通信 ...
- 用Python编写简单的发红包程序和计算器原理
用Python编写简单的发红包程序: 第一种解法:数轴方法解决 import random def red_packet(money,num): money = money * 100 #将钱数转换成 ...
- java编写简单的累加程序
编程思路:1.建立类包demo: 2.在类包中建立CommanParameter类: 3.利用for循环通过强制类型转换将在后台中输入的String类型的字符转换为整型并进进累加操作: package ...
- 使用Java编写并运行Spark应用程序
我们首先提出这样一个简单的需求: 现在要分析某网站的访问日志信息,统计来自不同IP的用户访问的次数,从而通过Geo信息来获得来访用户所在国家地区分布状况.这里我拿我网站的日志记录行示例,如下所示: 1 ...
- Java编写高质量代码改善程序的151个建议
第一章 Java开发中通用的方法和准则 建议1:不要在常量和变量中出现易混淆的字母: (i.l.1:o.0等). 建议2:莫让常量蜕变成变量: (代码运行工程中不要改变常量值). 建议3:三元操作符 ...
- 利用Java编写简单的WebService实例
使用Axis编写WebService比較简单,就我的理解,WebService的实现代码和编写Java代码事实上没有什么差别,主要是将哪些Java类公布为WebService. 以下是一个从编写測试样 ...
- 利用Java编写简单的WebService实例-转载
使用Axis编写WebService比较简单,就我的理解,WebService的实现代码和编写Java代码其实没有什么区别,主要是将哪些Java类发布为WebService.下面是一个从编写测试例子到 ...
- 用Java实现简单的网络聊天程序
Socket套接字定义: 套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开.读写和关闭等操作.套接字允许应用程序将I/O插入到网络中,并与网络中的其他 ...
随机推荐
- python 图像识别
这是一个最简单的图像识别,将图片加载后直接利用Python的一个识别引擎进行识别 将图片中的数字通过 pytesseract.image_to_string(image)识别后将结果存入到本地的txt ...
- 为什么程序员都不喜欢使用switch而使用if来做条件跳转
请用5秒钟的时间查看下面的代码是否存在bug. OK,熟练的程序猿应该已经发现Bug所在了,在第8行和第10行下面我没有添加关键字break; 这就导致这段代码的行为逻辑与我的设计初衷不符了. 缺 ...
- WEB新手之serialize’s revenge
最后一道题. 这道题提示比较少,一点也不友好.F12也没有什么线索.无奈之下用御剑扫下后台,发现了一个叫robots的txt文件. 打开robots.txt文件,可以得到一段代码,如下图所示. 审查代 ...
- 正则表达式,sed简单用法
一. 正则表达式 1. 常见的正则表达式字符 [] 匹配字符集 grep "bl[lo]g" oldboy.txt 表示字符‘l’或者‘o’都可匹配 * 重复前面字符任意次 g ...
- MAC系统从零开始
刚从ubuntu转过来,使用mac多有不习惯的地方,下面记录一些使用中遇到的问题,与解决方法. 1.关于应用程序菜单 在mac中的应用程序菜单,不是在应用程序自身,而是在桌面的桌面的顶部栏上,这个栏会 ...
- PHP会话cookie类的封装
<?php header('content-type:text/html;charset=utf-8');/** * 完成cookie的设置.删除.更新.读取 */class Cookie{ ...
- SQL数据库Truncate的相关用法
数据库中 Truncate的用法:这个是删除表中的所有数据语法是 Truncate Table tablename他与delete的区别在于1 delete 可以有条件的删除 而truncate 是删 ...
- PHP的curl实现get,post 和 cookie (转)
类似于dreamhost这类主机服务商,是显示fopen的使用 的.使用php的curl可以实现支持FTP.FTPS.HTTP HTPPS SCP SFTP TFTP TELNET DICT FILE ...
- python2.x提示这个错误:UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position
查了好久下面这个方法可用: 发现应该是因为python2.x的默认编码是ascii,而代码中可能由utf-8的字符导致,解决方法是设置utf-8. 找到出错的文件,在import后增加下面几行: #! ...
- 分分钟钟学会Python - 数据类型(int、bool、str)
第三天学习内容 今日内容 1.整型(int) 2.布尔类型(bool) 3.字符串(str) 内容详细 1.整型 Python中的整型用int表示. 1.python2中: 在32位机器上,整数的位数 ...