1、实现一个词法分析程序,将输入字符串流分解成单词流供语法分析使用。(注意:如果单词输入错误,必须有提示)
2、在词法分析的基础上实现一个语法分析程序,对词法分析的结果进行语法分析。
3、在语法分析的基础上实现一个语义分析程序,求出输入算式的最后结果。
算术运算文法如下:
(1) E->E+E
(2) E->E-E
(3) E->EE
(4) E->E/E
(5) E->(E)
(6) E->i
(7) i->十进制整数|十进制小数|八进制整数|十进制小数|十六进制整数|十六进制小数
(8) 十进制小数->(0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)).(0|1|2|3|4
|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)
(9)八进制小数->0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7).(0|1|2|3|4|5|6|7)(0
|1|2|3|4|5|6|7)
(10) 十六进制小数 ->0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8
|9|a|b|c|d|e|f).(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)
(11) 十进制整数->0|(1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*
(12) 八进制整数-> 0(0|1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*
(13) 十六进制整数->0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8
|9|a|b|c|d|e|f)**
单词分类
运算符:+ - * / ( )
常数:十进制小数、十进制整数、十六进制小数、十六进制整数、八进制小数、八进制整数
1、State类
public class State {
char name;
double value;
int decimal;
String type;
public State(char name, double value, int decimal, String type) {
this.name = name;
this.value = value;
this.decimal = decimal;
this.type = type;
}
public char getName() {
return name;
}
public void setName(char name) {
this.name = name;
}
public double getValue() {
return value;
}
public void setValue(double value) {
this.value = value;
}
public int getDecimal() {
return decimal;
}
public void setDecimal(int decimal) {
this.decimal = decimal;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
2、IsOperator类
public final class IsOperator {
public static final char[] TOKEN=new char[]{'+','-','*','/','(',')'};
/*判断是否是运算符*/
public static boolean isPulsSign(char token){
if((token=='+')||(token=='-')||(token=='*')||(token=='/')||(token=='(')||(token==')')){
return true;
}else return false;
}
}
3、Attribute类
public class Attribute {
char ch;
double val;
public Attribute(char ch, double val) {
this.ch = ch;
this.val = val;
}
public Attribute() {
}
public char getCh() {
return ch;
}
public void setCh(char ch) {
this.ch = ch;
}
public double getVal() {
return val;
}
public void setVal(double val) {
this.val = val;
}
}
4、NumberDfa类
public final class NumberDfa {
public static final char[] STATE = new char[]{'X', 'Y', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W'};//自动机的状态
public static final char[] TOKEN = new char[]{'.', 'x', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F'};//输入的字符
public static final char S_START = 'X';//开始状态
public static final char[] S_END = new char[]{'M', 'Y', 'P', 'Q', 'U', 'V', 'W'};//终结状态
/*根据DFA状态转换图,进行各状态的转换*/
public static State tranState(State state, char token) {
if (state.name == 'X') {
if (token == '0') {
return new State('Y', state.value * 10 + (token - 48), 0, "十进制整数");
} else if (token >= '1' && token <= '9') {
return new State('M', state.value * 10 + (token - 48), 0, "十进制整数");
} else {
return null;
}
} else if (state.name == 'M') {
if (token >= '0' && token <= '9') {
return new State('M', state.value * 10 + (token - 48), 0, "十进制整数");
} else if (token == '.') {
return new State('R', state.value, 0, null);
} else {
return null;
}
} else if (state.name == 'R') {
if (token >= '0' && token <= '9') {
return new State('U', state.value + (token - 48) / pow(10, state.decimal + 1), state.decimal + 1, "十进制小数");
} else {
return null;
}
} else if (state.name == 'U') {
if (token >= '0' && token <= '9') {
return new State('U', state.value + (token - 48) / pow(10, state.decimal + 1), state.decimal + 1, "十进制小数");
} else {
return null;
}
} else if (state.name == 'Y') {
if (token == '.') {
return new State('R', state.value, 0, null);
} else if (token >= '0' && token <= '7') {
return new State('P', state.value * 8 + (token - 48), 0, "八进制整数");
} else if (token == 'x' || token == 'X') {
return new State('N', state.value, 0, null);
} else {
return null;
}
} else if (state.name == 'P') {
if (token >= '0' && token <= '7') {
return new State('P', state.value * 8 + (token - 48), 0, "八进制整数");
} else if (token == '.') {
return new State('S', state.value, 0, null);
} else {
return null;
}
} else if (state.name == 'S') {
if (token >= '0' && token <= '7') {
return new State('V', state.value + (token - 48) / pow(8, state.decimal + 1), state.decimal + 1, "八进制小数");
} else {
return null;
}
} else if (state.name == 'V') {
if (token >= '0' && token <= '7') {
return new State('V', state.value + (token - 48) / pow(8, state.decimal + 1), state.decimal + 1, "八进制小数");
} else {
return null;
}
} else if (state.name == 'N') {
if ((token >= '0' && token <= '9') || (token >= 'a' && token <= 'f') || (token >= 'A' && token <= 'F')) {
return new State('Q', (token >= '0' && token <= '9') ? state.value * 16 + (token - 48) : ((token >= 'a' && token <= 'f') ? state.value * 16 + (token - 87) : state.value * 16 + (token - 55)), 0, "十六进制整数");
} else {
return null;
}
} else if (state.name == 'Q') {
if ((token >= '0' && token <= '9') || (token >= 'a' && token <= 'f') || (token >= 'A' && token <= 'F')) {
return new State('Q', (token >= '0' && token <= '9') ? state.value * 16 + (token - 48) : ((token >= 'a' && token <= 'f') ? state.value * 16 + (token - 87) : state.value * 16 + (token - 55)), 0, "十六进制整数");
} else if (token == '.') {
return new State('T', state.value, 0, null);
} else {
return null;
}
} else if (state.name == 'T') {
if ((token >= '0' && token <= '9') || (token >= 'a' && token <= 'f') || (token >= 'A' && token <= 'F')) {
return new State('W', (token >= '0' && token <= '9') ? state.value + (token - 48) / pow(16, state.decimal + 1) : ((token >= 'a' && token <= 'f') ? state.value + (token - 87) / pow(16, state.decimal + 1) : state.value + (token - 55) / pow(16, state.decimal + 1)), state.decimal + 1, "十六进制小数");
} else {
return null;
}
} else if (state.name == 'W') {
if ((token >= '0' && token <= '9') || (token >= 'a' && token <= 'f') || (token >= 'A' && token <= 'F')) {
return new State('W', (token >= '0' && token <= '9') ? state.value + (token - 48) / pow(16, state.decimal + 1) : ((token >= 'a' && token <= 'f') ? state.value + (token - 87) / pow(16, state.decimal + 1) : state.value + (token - 55) / pow(16, state.decimal + 1)), state.decimal + 1, "十六进制小数");
} else {
return null;
}
}
return null;
}
/*用于输出词法分析的结果*/
public static boolean estimation(char[] token) {
System.out.println("词法分析的结果为:");
boolean flag=true;
if (token != null && token.length != 0) {
State state = new State(S_START, 0.0, 0, null);
ArrayList<Character> ss = new ArrayList<>();
for (int i = 0; i < token.length; i++) {
if (!IsOperator.isPulsSign(token[i])) {
state = tranState(state, token[i]);
ss.add(token[i]);
} else {
if (state.type != null) {
for (Character s : ss) {
System.out.print(s);
}
ss.clear();
System.out.println( " " +state.type);
}
System.out.println(token[i] + " 运算符");
state = new State(S_START, 0.0, 0, null);
}
if (state == null) {
for (Character s : ss) {
System.out.print(s);
}
ss.clear();
System.out.println(" 错误数据");
flag=false;
state = new State(S_START, 0.0, 0, null);
}
}
for (Character s : ss) {
System.out.print(s);
}
ss.clear();
System.out.println( " "+state.type);
}
return flag;
}
/*用于将输入的算数表达式转换成相应的句子,并存入相应的属性值(即转换完成后的十进制数),为后面的语法分析和语义分析做准备*/
public static List<Attribute> getAttribute(char token[]){
ArrayList<Attribute> att=new ArrayList<>();
if (token != null && token.length != 0) {
State state = new State(S_START, 0.0, 0, null);
for (int i = 0; i < token.length; i++) {
if (!IsOperator.isPulsSign(token[i])) {
state = tranState(state, token[i]);
} else {
if (state.type != null) {
att.add(new Attribute('i',state.value));
}
att.add(new Attribute(token[i],0));
state = new State(S_START, 0.0, 0, null);
}
if (state == null) {
state = new State(S_START, 0.0, 0, null);
}
}
att.add(new Attribute('i',state.value));
}
return att;
}
}
5、OperatorPrecedence类,采用算符优先分析法
public class OperatorPrecedence {
//算符优先关系表
public static final char[][] priorityTable = {
{'>', '>', '<', '<', '<', '>', '<', '>'},
{'>', '>', '<', '<', '<', '>', '<', '>'},
{'>', '>', '>', '>', '<', '>', '<', '>'},
{'>', '>', '>', '>', '<', '>', '<', '>'},
{'<', '<', '<', '<', '<', '=', '<', ' '},
{'>', '>', '>', '>', ' ', '>', ' ', '>'},
{'>', '>', '>', '>', ' ', '>', ' ', '>'},
{'<', '<', '<', '<', '<', ' ', '<', '='}};
public static final String[] G = {"E->E+E", "E->E-E", "E->E*E", "E->E/E", "E->(E)", "E->i"}; //文法
public static final char[] endSign = {'+', '-', '*', '/', '(', ')', 'i', '#'};//终结符
public static final char NotendSign = 'E';//非终结符
//判断是否是终结符
private static boolean isEnd(char ch) {
for (int i = 0; i < endSign.length; i++) {
if (endSign[i] == ch) {
return true;
}
}
return false;
}
private static int endPosition(char ch) {
for (int i = 0; i < endSign.length; i++) {
if (endSign[i] == ch) {
return i;
}
}
return -1;
}
//根据产生式返回右部分的左边部分
public static char retLeft(String str) {
for (int i = 0; i < G.length; i++) {
StringBuffer a = new StringBuffer();
for (int j = 3; j < G[i].length(); j++) {
a.append(G[i].charAt(j));
}
if (str.equals(a.toString())) {
return G[i].charAt(0);
}
}
return 0;
}
public void Analysis(List<Attribute> att) {
int status = 0;//0是移进1是规约
int count = 0;//步骤数
int k = 0;//栈的深度
int j = 0;
int step = 0;
String gyStr = null;//规约字符串
System.out.println("语法分析结果为:");
att.add(new Attribute('#', 0));
String sentence = "";
for (Attribute a : att) {
sentence = sentence + a.ch;
}
ArrayList<Attribute> Stack = new ArrayList<>();//栈
System.out.printf("%-7s%-13s%-7s%-9s%-8s\n", "步骤", "栈", "a读入", "剩余串", "操作");
Stack.add(new Attribute('#', 0));//栈的初始为#
Attribute a = att.get(step++);//获取当前输入的字符
while (Stack.size() != 2 || a.ch != '#') {
if (status == 0) {
if (count != 0) {
String str = "";
for (int i = 0; i < Stack.size(); i++) {
str = str + Stack.get(i).ch;
}
System.out.printf(" %-8s\n %-8d%-15s%-8c%-10s", "移进", count, str, a.ch, sentence.substring(step));
} else {
String str = "";
for (int i = 0; i < Stack.size(); i++) {
str = str + Stack.get(i).ch;
}
System.out.printf(" %-8d%-15s%-8c%-10s", count, str, a.ch, sentence.substring(step));
}
}
//System.out.println(k);
char ch = Stack.get(k).ch;
if (isEnd(ch)) {
j = k;
} else if (j >= 1) {
j = k - 1;
}
//归约
char temp = 0;
if (priorityTable[endPosition(Stack.get(j).ch)][endPosition(a.ch)] == '>') {
ArrayList<Attribute> judge = new ArrayList<>();
temp = Stack.get(j).ch;
if (isEnd(Stack.get(j - 1).ch)) {
j = j - 1;
} else {
j = j - 2;
}
while (priorityTable[endPosition(Stack.get(j).ch)][endPosition(temp)] == '>' || priorityTable[endPosition(Stack.get(j).ch)][endPosition(temp)] == '=') {
if (isEnd(Stack.get(j - 1).ch)) {
j = j - 1;
} else {
j = j - 2;
}
}
for (int i = j + 1; i < Stack.size(); i++) {
judge.add(Stack.get(i));
}
int t = Stack.size();
for (int i = j + 1; i < t; i++) {
Stack.remove(j + 1);
}
String judgeStr = "";
for (Attribute ju : judge) {
judgeStr = judgeStr + ju.ch;
}
char res = retLeft(judgeStr);
if (res != 0) {
count++;
k = j + 1;
//Stack.add(res);
if (judge.size() == 1) {
Stack.add(new Attribute(res, judge.get(0).val));
} else if(judge.get(0).ch=='('&&judge.get(2).ch==')'){
Stack.add(new Attribute(res, judge.get(1).val));
}else {
if (judge.get(1).ch == '+') {
Stack.add(new Attribute(res, judge.get(0).val + judge.get(2).val));
} else if (judge.get(1).ch == '-') {
Stack.add(new Attribute(res, judge.get(0).val - judge.get(2).val));
} else if (judge.get(1).ch == '*') {
Stack.add(new Attribute(res, judge.get(0).val * judge.get(2).val));
} else if (judge.get(1).ch == '/') {
Stack.add(new Attribute(res, judge.get(0).val / judge.get(2).val));
}
}
status = 1;
gyStr = "用" + res + "->" + judgeStr + "规约";
String str = "";
for (int i = 0; i < Stack.size(); i++) {
str = str + Stack.get(i).ch;
}
System.out.printf(" %-8s\n %-8d%-15s%-8c%-10s", gyStr, count, str, a.ch, sentence.substring(step));
}
}
//移进
if (priorityTable[endPosition(Stack.get(j).ch)][endPosition(a.ch)] == '<' || priorityTable[endPosition(Stack.get(j).ch)][endPosition(a.ch)] == '=') {
count++;
k++;
status = 0;
Stack.add(a);
} else if (priorityTable[endPosition(Stack.get(j).ch)][endPosition(a.ch)] == ' ') {
System.out.print("读入单词出错!");
return;
}
if (status == 0 && step < sentence.length()) {
a = att.get(step++);
}
if (Stack.size() == 3 && a.ch == '#') {
break;
}
}
System.out.printf("%-8s\n", "接受");
System.out.println("最终结果:"+Stack.get(1).val);
}
}
参考代码:https://blog.csdn.net/tiandc/article/details/103372651?utm_source=app
6、
public class Test {
public static void main(String[] args) {
System.out.print("请输入四则运算的算数运算式:");
Scanner input = new Scanner(System.in);
String str = input.next();
char ss[] = str.toCharArray();
System.out.println();
boolean flag = true;
if (!estimation(ss)) {
System.out.println("单词出现错误,不能进行语法分析!");
flag = false;
}
if (flag) {
boolean flagg = true;
for (Attribute a : getAttribute(ss)) {
if (flagg) {
System.out.println();
System.out.print("该算数运算式对应的句子:");
flagg = false;
}
System.out.print(a.ch);
}
System.out.println();
OperatorPrecedence op = new OperatorPrecedence();
op.Analysis(getAttribute(ss));
}
}
}