一丶实验名称
语法分析器
二丶实验目的及要求
通过设计、编制、调试-个典型的语法分析程序(任选有代表性的语法分析方法,如LL(1)、递归下降分析法、LR、 算符优先分析法)等,作为编制语法分析程序的依据,对词法分析器所提供的单词序列进行语法检测和结构分析,实现并进- -步掌握常用的语法分析方法。
三、实验内容
选择对各种常见高级程序设计语言都较为通用的语法结构作为分析对象(例如表达式、if、 while、for 等等),给出其文法规则描述(注意,文法规则的描述要符合所选分析方法的要求,比如用LL(1)分析法,文法必须是LL(1)文法),设计并实现一一个完整的语法分析程序。
输入:源程序以文件的形式输入。
输出:对于输入的源程序,如果输入源程序是给定文法定义的合法程序,则输出“success",如果不是,即输入源程序有错误,则输出“Error”,并且尽可能指出出错位置和原因。
四、实验算法描述
文法规则:
E→TZ
Z→+TZ|ε
T→FY
Y→*FY|ε
F→(E)|i
程序描述(LL(1)文法)
本程序是基于以构建好的某一语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。
基本实现思想:接收用户输入的字符串(字符串以“#”表示结束)后,对用作分析栈的一维数组和存放分析表的二维数组进行初始化。然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,则出错,则语法分析结束,输入的字符串为文法的一个句子,否则出错,若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。若不为“#”且不与当前输入符号一样,则出错。
1.First集和Follow集
FIRST(E)={(,i} FOLLOW(E)={),#}
FIRST(Z)={+,ε} FOLLOW(Z)={),#}
FIRST(T)={(,i} FOLLOW(T)={+,),#}
FIRST(Y)={*,ε} FOLLOW(Y)={+,),#}
FIRST(F)={(,i} FOLLOW(F)={*,+,),#}
2.构建好的预测分析表
| i | + | * | ( | ) | # |
E | →TZ |
|
| →TZ | synch | synch |
Z |
| →+TZ |
|
| →ε | →ε |
T | →FY | synch |
| →FY | synch | synch |
Y |
| →ε | →*FY |
| →ε | →ε |
F | →i | synch | synch | →(E) | synch | synch |
LL(1)预测分析表
3.运行结果
输入正确的源程序截图:
输出结果截图
输入错误的源程序截图:
输出结果截图
五、设计技巧和心得体会
这次实验编写了一个语法分析方法的程序。但是在LL (1)分析器的编写中我只达到了最低要求,就是自己手动输入的文法规则然后通过程序将预测分析表构造出来,然后自已编写总控程序根据分析表进行分析。
通过本次试验,我能够设计一个简单的语法分析程序,实现对文法规则进行语法检查和结构分析,进一步掌握常用的语法分析方法。
六、源程序清单(电子版)
import java.util.Stack;
public class GramerAnasys {
//加入同步符号的LL(1)分析表
private String [][] analysisTable = new String[][]{
{"TZ","","","TZ","synch","synch"},
{"","+TZ","","","ε","ε"},
{"FY","synch","","FY","synch","synch"},
{"","ε","*FY","","ε","ε"},
{"i","synch","synch","(E)","synch","synch"}
};
//存储终结符
private String [] VT = new String[]{"i","+","*","(",")","#"};
//存储终结符
private String [] VN = new String[]{"E","Z","T","Y","F"};
//输入串
private StringBuilder strToken = new StringBuilder("i*i)+i");
//分析栈
private Stack<String> stack = new Stack<String>();
//a保存从输入串中读取的一个输入符号,当前符号
private String a = null;
//X中保存stack栈顶符号
private String X = null;
//flag标志预测分析是否成功
private boolean flag = true;
//记录输入串中当前字符的位置
private int cur = 0;
//记录步数
private int count = 0;
//输出语法规则
protected void print(){
System.out.printf("E→TZ \n"+"Z→+TZ|ε \n"+"T→FY \n"+"Y→*FY|ε \n"+"F→(E)|i \n");
}
//初始化
protected void init(){
strToken.append("#");
stack.push("#");
System.out.printf("%-9s %-38s %6s %-20s\n","步骤 ","符号栈 "," 输入串 "," 所用产生式 ");
stack.push("E");
curCharacter();
System.out.printf("%-6d %-20s %6s \n",count,stack.toString(),strToken.substring(cur, strToken.length()));
}
//读取当前栈顶符号
protected String stackPeek(){
X = stack.peek();
return X;
}
//返回输入串中当前位置的字母
private String curCharacter(){
a = String.valueOf(strToken.charAt(cur));
return a;
}
//判断X是否是终结符
protected boolean XisVT(){
for(int i = 0 ; i < (VT.length - 1); i++){
if(VT[i].equals(X)){
return true;
}
}
return false;
}
//查找X在非终结符中分析表中的横坐标
protected String VNTI(){
int Ni = 0 , Tj = 0;
for(int i = 0 ; i < VN.length ; i++){
if(VN[i].equals(X)){
Ni = i;
}
}
for(int j = 0 ; j < VT.length ; j++){
if(VT[j].equals(a)){
Tj = j;
}
}
return analysisTable[Ni][Tj];
}
//判断M[A,a]={X->X1X2...Xk}
//把X1X2...Xk推进栈
//X1X2...Xk=ε,不推什么进栈
protected boolean productionType(){
if(VNTI() != ""){
return true;
}
return false;
}
//推进stack栈
protected void pushStack(){
stack.pop();
String M = VNTI();
String ch;
for(int i = (M.length() -1) ; i >= 0 ; i--){
ch = String.valueOf(M.charAt(i));
stack.push(ch);
}
System.out.printf("%-6d %-20s %6s %-1s->%-12s\n",(++count),stack.toString(),strToken.substring(cur, strToken.length()),X,M);
}
//总控程序
protected void totalControlProgram(){
while(flag == true){
stackPeek();
if(XisVT() == true){
if(X.equals(a)){
cur++;
a = curCharacter();
stack.pop();
System.out.printf("%-6d %-20s %6s \n",(++count),stack.toString(),strToken.substring(cur, strToken.length()));
}else{
ERROR();
}
}else if(X.equals("#")){
if(X.equals(a)){
flag = false;
}else{
ERROR();
}
}else if(productionType() == true){
if(VNTI().equals("synch")){
ERROR();
}else if(VNTI().equals("ε")){
stack.pop();
System.out.printf("%-6d %-20s %6s %-1s->%-12s\n",(++count),stack.toString(),strToken.substring(cur, strToken.length()),X,VNTI());
}else{
pushStack();
}
}else{
ERROR();
}
}
}
//出现错误
protected void ERROR(){
System.out.println("Error.输入串出现错误,无法进行分析");
System.exit(0);
}
//打印存储分析表
protected void printf(){
if(flag == false){
System.out.println("********success");
}else {
System.out.println("********Error");
}
}
public static void main(String[] args) {
GramerAnasys gramerAnasys= new GramerAnasys();
gramerAnasys.print();
gramerAnasys.init();
gramerAnasys.totalControlProgram();
gramerAnasys.printf();
}
}