编译原理 语法分析器 (java完美运行版)

时间:2019-05-14 18:41:07下载本文作者:会员上传
简介:写写帮文库小编为你整理了多篇相关的《编译原理 语法分析器 (java完美运行版)》,但愿对你工作学习有帮助,当然你在写写帮文库还可以找到更多《编译原理 语法分析器 (java完美运行版)》。

第一篇:编译原理 语法分析器 (java完美运行版)

实验二

语法分析器

一、实验目的

通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。有利于提高学生的专业素质,为培养适应社会多方面需要的能力。

二、实验内容

 根据某一文法编制调试 LL(1)分析程序,以便对任意输入的符号串进行分析。

 构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。

 分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。

三、LL(1)分析法实验设计思想及算法

 模块结构:

(1)定义部分:定义常量、变量、数据结构。

(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);

(3)控制部分:从键盘输入一个表达式符号串;

(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。

四、实验要求

1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

2、如果遇到错误的表达式,应输出错误提示信息。

3、对下列文法,用LL(1)分析法对任意输入的符号串进行分析:

(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i 输出的格式如下:

五、实验源程序

LL1.java import java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.swing.table.DefaultTableModel;import java.sql.*;import java.util.Vector;public class LL1 extends JFrame implements ActionListener { /**

*

*/

private static final long serialVersionUID = 1L;JTextField tf1;JTextField tf2;JLabel l;JButton b0;JPanel p1,p2,p3;JTextArea t1,t2,t3;JButton b1,b2,b3;JLabel l0,l1,l2,l3,l4;JTable table;Statement sta;Connection conn;ResultSet rs;DefaultTableModel dtm;String Vn[]=null;Vector P=null;

int firstComplete[]=null;//存储已判断过first的数据

char first[][]=null;//存储最后first结果

int followComplete[]=null;//存储已判断过follow的数据

char follow[][]=null;//存储最后follow结果

char select[][]=null;//存储最后select结果

int LL=0;//标记是否为LL(1)String vt_tou[]=null;//储存Vt

Object shuju[][]=null;//存储表达式数据

char yn_null[]=null;//存储能否推出空

LL1(){ setLocation(100,0);setSize(700,780);tf1=new JTextField(13);tf2=new JTextField(13);l=new JLabel(“>>”);l0=new JLabel(“输入字符串:”);l1=new JLabel(“输入的文

法”);l2=new JLabel(“ ”);l3=new JLabel(“

析的结”);l4=new JLabel(“预测

析”);//p1=new JPanel();

p2=new JPanel();p3=new JPanel();t1=new JTextArea(24,20);t2=new JTextArea(1,30);t3=new JTextArea(24,40);b0=new JButton(“确定(S为开始)”);b1=new JButton(“ 判断文法 ”);

:果:表

b2=new JButton(“输入”);b3=new JButton(“清空”);table=new JTable();JScrollPane jp1=new JScrollPane(t1);JScrollPane jp2=new JScrollPane(t2);JScrollPane jp3=new JScrollPane(t3);p2.add(tf1);p2.add(l);p2.add(tf2);

p2.add(b0);p2.add(b1);p2.add(l0);p2.add(l2);p2.add(jp2);p2.add(b2);p2.add(b3);

p2.add(l1);p2.add(l3);p2.add(jp1);p2.add(jp3);

p3.add(l4);p3.add(new JScrollPane(table));add(p2,“Center”);add(p3,“South”);

b0.addActionListener(this);b1.addActionListener(this);b2.addActionListener(this);b3.addActionListener(this);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);table.setPreferredScrollableViewportSize(new Dimension(660,200));setVisible(true);} public void actionPerformed(ActionEvent e){ if(e.getSource()==b0){ String a=tf1.getText();String b=tf2.getText();t1.append(a+'→'+b+'n');}

if(e.getSource()==b1){ t3.setText(“");int Vnnum=0,k;Vn=new String[100];P=new Vector();String s[]=t1.getText().split(”n“);for(int i=0;i

return;}

if(s[i].charAt(0)<='Z'&&s[i].charAt(0)>='A'&&s[i].charAt(1)=='→'){ for(k=0;k=Vnnum){ Vn[Vnnum]=s[i].substring(0, 1);//存入Vn数据 Vnnum++;} P.add(s[i]);} else { t3.setText(”文法输入有误,请重新输入“);return;} } yn_null=new char[100];first=new char[Vnnum][100];int flag=0;String firstVn[]=null;firstComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++)//依次求 FIRST** { flag=0;firstVn=new String[20];

if((flag=add_First(first[i],Vn[i],firstVn,flag))==-1)return;firstComplete[i]=1;} t3.append(”first集:“+”n“);//显示FIRST**

for(int i=0;Vn[i]!=null;i++){ t3.append(”first(“+Vn[i]+”)={ “);for(int j=0;first[i][j]!='';j++){ t3.append(first[i][j]+” , “);} t3.append(”}“+”n“);}

follow=new char[Vnnum][100];String followVn[]=null;followComplete=new int[Vnnum];for(int i=0;Vn[i]!=null;i++)//求FOLLOW** { flag=0;followVn=new String[20];

if((flag=tianjiaFollow(follow[i],Vn[i],followVn,flag))==-1)return;followComplete[i]=1;} t3.append(”follow集:“+”n“);//显示FOLLOW**

for(int i=0;Vn[i]!=null;i++){ t3.append(”follow(“+Vn[i]+”)={ “);for(int j=0;follow[i][j]!='';j++){ t3.append(follow[i][j]+” , “);} t3.append(”}“+”n“);} select=new char[P.size()][100];for(int i=0;i

tianjiaSelect(select[i],(String)P.elementAt(i),flag);} t3.append(”select集:“+”n“);//显示SELECT**

for(int i=0;i

for(int i=0;Vn[i]!=null;i++)//判断select交集是否为空 { int biaozhi=0;char save[]=new char[100];for(int j=0;j

if(t.substring(0,1).equals(Vn[i])){ for(k=0;select[j][k]!='';k++){ if(puanduanChar(save,select[j][k])){ save[biaozhi]=select[j][k];biaozhi++;} else//当有交集时,不为LL(1)文法 { t3.append(”不是LL(1)文法!“+”n“);return;} } } } } char Vt[]=new char[100];int biaozhi=0;for(int i=0;i

{ if(t.charAt(j)>'Z'||t.charAt(j)<'A'){ if(puanduanChar(Vt,t.charAt(j))){ Vt[biaozhi]=t.charAt(j);biaozhi++;} } } } if(puanduanChar(Vt,'#'))//若可推出空集,则将#加入Vt。{ Vt[biaozhi]='#';biaozhi++;} vt_tou=new String[biaozhi+1];//根据select和表达式生成预测分析表

shuju=new String[Vnnum][biaozhi+1];String f=”“;vt_tou[0]=f;for(int i=0;itable.setModel(dtm);LL=1;} if(e.getSource()==b3)//清空列表 { tf1.setText(”“);tf2.setText(”“);t1.setText(”“);t2.setText(”“);t3.setText(”“);Vn=null;P=null;firstComplete=null;first=null;followComplete=null;follow=null;select=null;dtm=new DefaultTableModel();table.setModel(dtm);}

if(e.getSource()==b2)//输入字符串并预测分析 { t3.setText(”“);if(LL==1){ String s=t2.getText();for(int i=0;i

return;} } char zifu[]=new char[100];//剩余输入串

char fenxi[]=new char[100];//分析栈 zifu[0]='#';fenxi[1]='S';fenxi[0]='#';int fzifu=1;int ffenxi=2;for(int i=s.length()-1;i>=0;i--){ zifu[fzifu]=s.charAt(i);fzifu++;} int buzhou=2;char n[]=new char[65];//存储要显示的内容

t3.append(”步骤

分析栈 剩余输入串 所用产生式或匹配“+”n“);n[0]='1';n[15]='#';n[14]='S';int u=29;for(int i=fzifu-1;i>=0;i--)

{ n[u]=zifu[i];u++;}

while(!(fenxi[ffenxi-1]=='#'&&zifu[fzifu-1]=='#'))//剩余输入串不为#则分析

{ int i,j;char t=zifu[fzifu-1];char k=fenxi[ffenxi-1];if(t==k)//产生式匹配 { n[49]=k;n[50]='匹';n[51]='配';t3.append(String.copyValueOf(n)+”n“);n=new char[65];fzifu--;ffenxi--;if(buzhou<10)n[0]=(char)('0'+buzhou);//显示步骤数

{ n[0]=(n[1]=(} u=14;{ n[u]=fenxi[y];u++;} u=29;一个字符 { n[u]=zifu[y];u++;} buzhou++;}

{ } { } { else char)('0'+buzhou/10);char)('0'+buzhou%10);for(int y=ffenxi-1;y>=0;y--)//处理分析栈,出栈 for(int y=fzifu-1;y>=0;y--)//处理剩余字符串,消除continue;for(i=0;Vn[i]!=null;i++)//搜寻所用产生式的左部 if(Vn[i].equals(String.valueOf(k)))break;for(j=0;j=vt_tou.length)//全部产生式都不能符合则报错 t3.append(String.copyValueOf(n));t3.append(”n“+”该串不是该文法的句型“+”n“);return;}

Object result1=shuju[i][j];if(result1==null){ t3.append(String.copyValueOf(n));t3.append(”n“+”该串不是该文法的句型“+”n“);return;} else//找到所用产生式 { n[49]=Vn[i].charAt(0);u=50;String result=(String)result1;for(int y=0;y

ffenxi--;for(i=result.length()-1;i>0;i--)//将分析栈内非终结符换为右边表达式

{ if(result.charAt(i)!='#')

{ fenxi[ffenxi]=result.charAt(i);ffenxi++;} } } if(buzhou<10)//显示“步骤” n[0]=(char)('0'+buzhou);else { n[0]=(char)('0'+buzhou/10);n[1]=(char)('0'+buzhou%10);} u=14;for(int y=ffenxi-1;y>=0;y--){ n[u]=fenxi[y];u++;} u=29;for(int y=fzifu-1;y>=0;y--){ n[u]=zifu[y];u++;} buzhou++;} n=new char[65];n[0]='1';n[14]='#';n[29]='#';n[49]='分';n[50]='析';n[51]='成';n[52]='功';t3.append(String.copyValueOf(n));t3.append(”n“+”该串是此文法的句型“+”n“);return;} else { t3.setText(”请先依次输入LL(1)文法,并点击 文法判断 按钮“+”n“);return;} } }

private int add_First(char a[],String b,String firstVn[],int flag)//计算FIRST**(递归){

if(puanduanString(firstVn,b.charAt(0))){addString(firstVn,b);} else { return flag;} for(int i=0;i

String t=(String)P.elementAt(i);for(int k=2;k'Z'||t.charAt(k)<'A')//表达式右端第i个不是非终结符

{ if(flag==0||puanduanChar(a,t.charAt(k))){

if(t.charAt(k)=='#')//#时直接加入first { if(k+1==t.length()){ a[flag]=t.charAt(k);flag++;} int flag1=0;for(int j=0;yn_null[j]!='';j++)//所求非终结符进入yn_null**

{ if(yn_null[j]==b.charAt(0))//判断能否推出空

{ flag1=1;break;} } if(flag1==0){ int j;for(j=0;yn_null[j]!='';j++){ } yn_null[j]=b.charAt(0);} continue;} else//终结符直接加入first** { a[flag]=t.charAt(k);flag++;break;} }break;} else//非终结符 { if(!puanduanString(Vn,t.charAt(k))){ int p=firstComplete(t.charAt(k));//当该非终结符的first已经求出

if(p!=-1){ flag=addElementFirst(a,p,flag);//直接加入所求first

} else

if((flag=add_First(a,String.valueOf(t.charAt(k)),firstVn,flag))==-1)return-1;int flag1=0;for(int j=0;yn_null[j]!='';j++)//当非终结符的first有空

{ if(yn_null[j]==t.charAt(k)){ flag1=1;break;} } if(flag1==1)//当非终结符的first能推出空 {

if(k+1==t.length()&&puanduanChar(a,'#'))//之后无符号,且所求first无# { a[flag]='#';//first中加入# flag++;} continue;//判断下一个字符 } else { break;} } else//错误 { t3.setText(”文法输入有误“+”n“);return-1;} } } } } return flag;}

private int tianjiaFollow(char a[],String

b,String followVn[],int flag)//计算FOLLOW**(递归){

if(puanduanString(followVn,b.charAt(0))){addString(followVn,b);} else { return flag;} if(b.equals(”S“))//当为S时#存入follow { a[flag]='#';flag++;} for(int i=0;i

'Z'||t.charAt(j+1)<'A'))//所求为终结符

{ if(flag==0||puanduanChar(a,t.charAt(2)))//自身 { a[flag]=t.charAt(j+1);flag++;} }

else//所求为非终结符 { int k;for(k=0;Vn[k]!=null;k++){

if(Vn[k].equals(String.valueOf(t.charAt(j+1)))){ break;//找寻下一个非终结符的Vn位置 } } flag=addElementFirst(a,k,flag);//把下一个非终结符first加入所求follow集

for(k=j+1;k

if((t.charAt(j+1)>'Z'||t.charAt(j+1)<'A'))break;else { if(panduan_kong(t.charAt(k))){} else { break;} } } if(k>=t.length())//下一个非终结符可推出空,把表达式左边非终结符的follow集加入所求follow集 { int p=followComplete(t.charAt(0));if(p!=-1){ flag=addElementFollow(a,p,flag);} else

if((flag=tianjiaFollow(a,String.valueOf(t.charAt(0)),followVn,flag))==-1)return-1;} } } else//错误 { t3.setText(”文法输入有误,请重新输入“+”n");return-1;} } if(t.charAt(j)==b.charAt(0)&&j+1==t.length())//下一个字符为空,把表达式左边非终结符的follow集加入所求follow集 { int p=followComplete(t.charAt(0));if(p!=-1){ flag=addElementFollow(a,p,flag);} else

if((flag=tianjiaFollow(a,String.valueOf(t.charAt(0)),followVn,flag))==-1)return-1;

} } } return flag;} private void tianjiaSelect(char a[],String b,int flag)//计算SELECT** { int i=2;int biaozhi=0;while(i

if((b.charAt(i)>'Z'||b.charAt(i)<'A')&&b.charAt(i)!='#')//是终结符 { a[flag]=b.charAt(i);//将这个字符加入到Select**,结束Select**的计算

break;} else if(b.charAt(i)=='#')//是空 { int j;for(j=0;Vn[i]!=null;j++)//将表达式左侧的非终结符的follow加入select { if(Vn[j].equals(b.substring(0,1))){ break;} } for(int k=0;follow[j][k]!='';k++){ if(puanduanChar(a,follow[j][k])){ a[flag]=follow[j][k];flag++;} } break;} else

if(b.charAt(i)>='A'&&b.charAt(i)<='Z'&&i+1

if(puanduanChar(a,first[j][k]))//把表达式右侧所有非终结符的first集加入。{ if(first[j][k]=='#')//first中存在空 { biaozhi=1;} else

{ a[flag]=first[j][k];flag++;} } } if(biaozhi==1)//把右侧所有非终结符的first中的#去除 { i++;biaozhi=0;continue;} else { biaozhi=0;break;} } else

if(b.charAt(i)>='A'&&b.charAt(i)<='Z'&&i+1>=b.length())//是非终结符且没有下一个字符 { int j;for(j=0;Vn[i]!=null;j++){ if(Vn[j].equals(String.valueOf(b.charAt(i)))){ break;} } for(int k=0;first[j][k]!='';k++){

if(puanduanChar(a,first[j][k])){ if(first[j][k]=='#'){ biaozhi=1;//表达式右侧能推出空,标记 } else { a[flag]=first[j][k];//不能推出空,直接将first集加入select集

flag++;}

} } if(biaozhi==1)//表达式右侧能推出空 { for(j=0;Vn[i]!=null;j++){ if(Vn[j].equals(b.substring(0,1)))

{ break;} } for(int k=0;follow[j][k]!='';k++){ if(puanduanChar(a,follow[j][k])){ a[flag]=follow[j][k];//将将表达式左侧的非终结符的follow加入select

flag++;} } break;} else { biaozhi=0;break;} } } }

//返回b在Vt[]的位置

private int puanduanXulie(char Vt[],char b){ int i;for(i=0;Vt[i]!='';i++){ if(Vt[i]==b)break;} return i;}

//判断b是否在a中,在返回false,不在返回true

private boolean puanduanChar(char a[],char b){

for(int i=0;a[i]!='';i++){ if(a[i]==b)return false;} return true;} //判断b是否在a中,在返回false,不在返回true

private boolean puanduanString(String a[],char b){ for(int i=0;a[i]!=null;i++){ if(a[i].equals(String.valueOf(b)))return false;} return true;} //把b加入字符串组firstVn[]

private void addString(String firstVn[],String b){ int i;for(i=0;firstVn[i]!=null;i++){ } firstVn[i]=b;} //判断b是否已完成first判断

private int firstComplete(char b){ int i;for(i=0;Vn[i]!=null;i++){ if(Vn[i].equals(String.valueOf(b))){ if(firstComplete[i]==1)return i;else return-1;} } return-1;} //判断b是否已完成follow判断

private int followComplete(char b){ for(int i=0;Vn[i]!=null;i++){ if(Vn[i].equals(String.valueOf(b))){ if(followComplete[i]==1)return i;else return-1;} } return-1;} //把相应终结符添加到first**中

private int addElementFirst(char a[],int p,int flag){ for(int i=0;first[p][i]!='';i++){ if(puanduanChar(a,first[p][i])&&first[p][i]!='#'){ a[flag]=first[p][i];flag++;} } return flag;} //把相应终结符添加到follow**中

private int addElementFollow(char a[],int p,int flag){ for(int i=0;follow[p][i]!='';i++){ if(puanduanChar(a,follow[p][i])){ a[flag]=follow[p][i];flag++;} } return flag;} //判断a能是否包含空

private boolean panduan_kong(char a){ int i;for(i=0;Vn[i]!=null;i++){ if(Vn[i].equals(String.valueOf(a))){ break;} } for(int j=0;first[i][j]!='';j++){ if(first[i][j]=='#')return true;}

return false;}

public static void main(String[] args){ new LL1();

} }

六、实验结果

七、实验心得体会

通过这次的实验,我深入了解了词法分析器和LL(1)文法预测分析法设计和实现,增强了我的自学能力和独立思考能力,也让我对程序设计有了更大的兴趣,自己通过查找资料、复习课本、编程调试,写实验报告等环节,进一步掌握了以前学到的知识,并且还对编译原理应用有了更深入的认识与掌握。在完成这个程序后,真的很开心,也了使我解到编译原理的魅力所在,激发了我要解决更多更难问题的决心。通过实践的学习,我认到学好计算机要重视实践操作,不仅仅是学习java语言,还是其它的语言,以及其它的计算机方面的知识都要重在实践,所以后在学习过程中,我会更加注视实践操作,使自己便好地学好计算机。

第二篇:《编译原理》课程设计报告--词法分析器

201X-201X学年第x学期

《编译原理》课程设计报告

院 系: 计算机科学与技术 班 级: XX级XX 班 学生姓名: XXXXXX 学 号: XXXXXXXX 指导老师: XXXXXX

计算机科学与技术学院监制

20XX年X月

目录

1.课程设计的目的 2.课程设计的内容和要求 3.问题分析和相关知识介绍 4.设计思路和关键问题及其解决方案 5.测试和结果分析 6.总结和心得体会

附件1:参考文献 附件2:核心源代码

1.课程设计的目的(1)编写词法分析器

(2)加深对词法分析器工作原理的了解和认识

2.课程设计的内容和要求

编写词法分析器,词法分析器能够识别关系算符,词法分析器能够识别标识符和关键字,词法分析器能够识别无符号数。

3.问题分析和相关知识介绍

构成词法分析器的一种简单方法是用状态转换图来描述源语言词法记号的结构,然后手工把这种状态转换图翻译成为识别词法记号的程序。词法分析器的任务是把构成源程序的字符流翻译成词法记号流。

4.设计思路和关键问题及其解决方案

把自然语言构造成正规式,把正规式构造成有限自动机NFA,然后根据子集构造法把有限自动机构造成无限自动机DFA,根据极小化DFA状态数算法把DFA构造成最简DFA,其次根据最简DFA画出转换表,根据转换表画出装换图,最后根据装换图就可以编写词法分析器。

5.测试和结果分析

6.总结和心得体会

通过本次试验,不仅仅是我学会了C#基础知识,而且还是我对词法分析器有了更深入的认识,虽然在编写词法分析器过程中遇到了很多困难,例如:C#语言不熟悉,对此法分析器的工作原理分析的不透彻,但在老师和同学的帮助下,我有了很大的提高,通过不断的努力最终顺利的完成了课程设计,很感谢帮助我的XX同学和XX老师。附件1:参考文献

《编译原理(第2版)》 高等教育出版社; 《C#程序设计及应用教程(第2版)》 人民教育出版社。附件2:

1.Code文档截图

2.程序源代码

using System;using System.Collections.Generic;using System.Text;using System.IO;

namespace LexicalAnalysis { class Program { static string[] keys = { “static”, “true”, “return”, “string”, “Length”, “break”, “Console”, “WriteLine”, “bool”, “false”, “ture”, “void”, “if”, “else”, “while”, “int”, “float”, “for”, “enum”, “default”, “case”, “double”, “do” };

static List key = new List();//保存关键字

static List bsf = new List();//保存标识符

static List sz = new List();//保存数字

static List gx = new List();//保存关系运算符

static List ys = new List();//保存数字运算符

//数字,标识符,空白,关系符,运算符

static void Main(string[] args){

string[] date = File.ReadAllLines(@“d:code.txt”);//路径,并存入data

for(int i = 0;i < date.Length;i++){ Console.WriteLine(“第” +(i + 1)+ “行code: ” + date.GetValue(i));analysisByLine(date[i]);

} //分别输出存储在四个List中的String

Console.WriteLine(“关键字,输入回车”);//输出所有的关键字 Console.ReadLine();

foreach(string id in key){ Console.WriteLine(id);

}

Console.WriteLine(“标识符,输入回车”);//输出所有的标识符

Console.ReadLine();foreach(string id in bsf){ Console.WriteLine(id);

}

Console.WriteLine(“数字,输入回车”);Console.ReadLine();foreach(string id in sz){ Console.WriteLine(id);

}

Console.WriteLine(“关系运算符,输入回车”);Console.ReadLine();foreach(string id in gx){ Console.WriteLine(id);

}

Console.WriteLine(“算数运算符,输入回车”);Console.ReadLine();foreach(string id in ys){ Console.WriteLine(id);

}

Console.WriteLine(“输入回车退出”);

Console.ReadLine();

} static void analysisByLine(string code)

//输出所有的数字 //输出所有的关系运算符//输出所有的算数运算符

{

char a = ' ';string temp = “";int j = 0;while(j < code.Length){ a = code[j];temp = ”“;if(Char.IsLetter(a)|| a == '_')//是否为标识符 { temp = temp + a.ToString();j++;a = code[j];while(Char.IsLetterOrDigit(a)){ temp = temp + a.ToString();j++;a = code[j];} if(isKey(temp)){

//Console.WriteLine(”保留字:“+temp);

if(!key.Contains(temp)){ // Console.WriteLine(”添加成功“);key.Add(temp);}

} else {

//Console.WriteLine(”标识符:“+temp);

if(!bsf.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);bsf.Add(temp);} }

} else if(Char.IsDigit(a)){ temp = temp + a.ToString();j++;a = code[j];while(Char.IsDigit(a)){ temp = temp + a.ToString();j++;a = code[j];

} //判断是否是小数

if(a.Equals('.')){ temp = temp + a.ToString();j++;a = code[j];while(Char.IsDigit(a)){ temp = temp + a.ToString();j++;a = code[j];} //判读是否是科学记数法

if(a.Equals('E')|| a.Equals('e')){ temp = temp + a.ToString();j++;a = code[j];while(Char.IsDigit(a)){

temp = temp + a.ToString();j++;a = code[j];} }

}

// Console.WriteLine(”数字:“+temp);if(!sz.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);sz.Add(temp);} } else if(a == '<'){ temp = temp + a.ToString();j++;a = code[j];if(a == '='){ temp = temp + a.ToString();j++;a = code[j];} else if(a == '>'){ temp = temp + a.ToString();j++;a = code[j];} //Console.WriteLine(”关系符“+temp);if(!gx.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);gx.Add(temp);} } else if(a == '='){ temp = temp + a.ToString();j++;

a = code[j];// Console.WriteLine(”关系符“+temp);if(!gx.Contains(temp)){ //Console.WriteLine(”添加成功关系==“);gx.Add(temp);} } else if(a == '>'){ temp = temp + a.ToString();j++;a = code[j];if(a == '='){ temp = temp + a.ToString();j++;a = code[j];}

// Console.WriteLine(”关系符“+temp);if(!gx.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);gx.Add(temp);}

} else { if(a == '+' || a == '-' || a == '/' || a == '*'){ temp = temp + a.ToString();j++;a = code[j];//Console.WriteLine(”运算符“+temp);if(!ys.Contains(temp)){ //Console.WriteLine(”添加成功标识符==“);ys.Add(temp);} } else

{ j++;}

} } }

//判断是不是保留字的IsKey方法

static bool isKey(string key){

bool flag = false;for(int i = 0;i < keys.Length;i++)

if(keys[i] == key){ flag = true;//Console.WriteLine(key+”是不是key“+flag);break;} else { flag = false;

} //Console.WriteLine(key+”是不是key“);// Console.WriteLine(flag+”是不是key");return flag;

} } }

第三篇:编译原理课程设计 LL递归下降分析器

仲恺农业技术学院

编译原理课程设计

课程设计题目 :LL(1)递归下降分析器

名 : 院(系):

专业班级 : 学

号 :

指导教师 :

设计日期 :

目 录

1、需求分析...................................................................................................1

2、概要设计...................................................................................................2

3、详细设计...................................................................................................3

4、测试分析...................................................................................................8

5、用户手册...................................................................................................9

6、课程总结...................................................................................................9

7、参考文献.................................................................................................10

题目:LL(1)递归下降分析器

1、需求分析

语法分析是编译过程的核心部分。语法分析器的任务是识别和处理比单词更大的语法单位。如:程序设计语言中的表达式,各种说明和语句乃至全部源程序,指出其中的语法错误;必要时,可生成内部形式,便于下一阶段处理。

我们知道,语言的语法结构是用上下文无关文法描述的。按照语法分析树的建立方法,我们可以粗略地把语法分析办法分成两类,一类是自上而下分析,另一类是自下而上分析法。而自上而下这种方法是带“回溯”的,且存在许多困难和缺点。

首先,是文法的左递归性问题。一个文法是含有左递归的,如果存在非终结符P且PP,含有左递归的文法使上述的自上而下的分析过程陷入无限循环。即,当试图用P去匹配输入串时,我们会发现,在没有识别任何输入符号的情况下,有得重新要求P去进行新的匹配。因此,使用自上而下分析法必须消除文法的左递归性。

其次,由于回溯,就碰到一大堆麻烦问题。如果我们走了一大段错路,最后必须回头,那么,就应把已经做的一大堆语义工作(指中间代码产生工作和各种表格的簿记工作)推倒重来。这些事情既麻烦又费时间,所以,最好应设法消除回溯。

第三,在自上而下分析过程中,当一个非终结符用某一候选匹配成功时,这种成功可能仅是暂时的。

第四,当最终报告分析不成功时,我们难于知道输入串中出错的确切位置。

最后,由于带回溯的自上而下分析实际上采用了一种穷尽一切可能的试探法,因此,效率很低,代价极高。严重的低效使得这种分析法只有理论意义,而在实践上价值不大。

由于上述原因,我们需要把原算术表达式改写为LL(1)文法,LL(1)文法的文法条件如下: 文法不含左递归。

对于文法中每一个非终结符A的各个产生式的候选首集符两两不相交。即,若A1|2||n,则FIRSTiFIRSTj ij

对文法中的每个非终结符A,若它存在某个候选首符集包含ε,则FIRSTAFOLLOWA

LL(1)中的第一个L表示从左到右扫描输入串,第二个L表示最左推导,1表示分析时每 一步只需向前查看一个符号。当一个文法满足LL(1)条件时,我们就可以为它构造一个不带回溯的自上而下分析程序,这个分析程序是由一组递归过程组成的,每个过程对应文法的一个非终结符。这样的一个分析程序称为递归下降分析器。

2、概要设计

编程实现给定算术表达式的递归下降分析器。算术表达式文法如下: E-->E+T|E-T|T T-->T*F|T/F|F F-->(E)| i 首先改写文法为LL(1)文法;然后为每一个非终结符,构造相应的递归过程,过程的名字表示规则左部的非终结符;过程体按规则右部符号串的顺序编写。

上述算法表达式文法属于比较典型的递归下降语法分析。需要先将原算术表达式方法改写为LL(1)文法为:

E-->TE’

E’-->+TE’|-TE’| ε T-->FT’

T’-->*FT’|/FT’| ε F-->(E)| i 然后再为每个非终结符设计一个对应的函数,通过各函数之间的递归调用从而实现递归下降语法分析的功能。

具体方法为:

(1)当遇到终结符a时,则编写语句

If(当前读到的输入符号==a)读入下一个输入符号(2)当遇到非终结符A时,则编写语句调用A()。(3)当遇到A-->ε规则时,则编写语句

If(当前读到的输入符号不属于Follow(A))error()(4)当某个非终结符的规则有多个候选式时,按LL(1)文法的条件能唯一地选择一个候选式进行推导.递归下降子程序流程图:

图1递归下降子程序流程图

3、详细设计

#include char inputstream[50];//存储输入句子 int temp=0;//数组下标 int right;//判断输出信息 void e();void e1();void t();void t1();void f();

void main(){

}

void e(){

}

void e1()right=1;cout<<“--------------------”<>inputstream;cout<<“--------------------”<TE'”<

}

void t(){

} if(inputstream[temp]=='+'){

} else if(inputstream[temp]=='-'){

} else if(inputstream[temp]!='#'||inputstream[temp]!=')'){

} else right=0;cout<<“T'->^”<-TE'”<+TE'”<FT'”<

if(inputstream[temp]=='*'){

} else if(inputstream[temp]=='/'){

} else cout<<“T'->/FT'”<*FT'”<

}

void f(){

{

} cout<<“T'->^”<i”<

} } else

if(inputstream[temp]=='('){

cout<<“F->(E)”<

} else } right=0;cout<<“F->(E)”<

4、测试分析

图2 测试分析成功

图3 测试分析失败

5、用户手册

开发工具:visual c++ 6.0 开发环境:windows XP操作系统

运行环境:windows 9x,windows NT,Windows 2000,windows XP 注意:输入时,程序最多只能接受50个字符,输入完算术表达式后要以“#”号结束。

6、课程总结

通过一个星期的努力,终于把编译原理课程设计给完成了。我觉得编译原理这门课是一门非常难学的课程,它涉及文法、词法分析、语法分析属性文法和语义分析等等一系列内容,课本里的内容和定义也非常的抽象且枯燥。如果上课没有好好的认真听课,自己独自学习就感到非常的吃力,而且效果也不好。本人因为上课无法做到打醒十二分专心听课,经常会分神,所以学习的效果也不怎么好。这也给做编译原理课程设计带来了困难。本次课程设计,我选的课程设计题目是LL(1)递归下降分析器,这个题目涉及的内容有关课本第四章 语法分析——自上而下分析里面的内容。在开始动手对题目进行设计和编程之前,我重复的仔细认真的阅读和理解课本第四章里面的内容,弄懂自上而下分析面临的问题、何谓左递归,搞清楚如何消除左递归、如何消除回溯、提左因子,理解构造LL(1)文件需要什么条件。虽然这花费了一定的时间和精力,但那点付出也是值得的,通过复习让我加深理解了有关自上而下语法分析的内容,而且也为用高级语言实现递归下降分析器带来便利。

在用C++编程时,基本上没有遇到什么困难,只需把所有递归过程都写出就行了。但是要注意的是,在编写代码时,要根据LL(1)文法的工作原理去设计。通过本次课程设计清楚地了解到递归下降分析法的优缺点,其优点是简单、直观,易于构造分析程序。缺点是对文法要求高,必须是LL(1)文法,同时由于递归调用较多,影响分析器的效率。

课程设计虽然只有短短的一周,但让我认识到学习好编译原理,是对程序设计和编译的一个很好的进化桥梁和奠基石。今后学习的日子还很长,希望通过这次编译原理的课程设计,不仅对编程语言的进一步复习,还是对更深层次的学习作一个简单的准备。编程的能力不是一朝一夕能锻炼出来,坚持学习,坚持编程的学习,多看,多编是最好的学习和提高方法。

通过本次编译原理课程设计,对面向对象的定义又有了更深一步的理解,对编译程序有了进一步的理解,同时也认识到自己各方面知识的薄弱点,以后在学习中也能有针对性对这方面进行深入学习。学习更好的知识重在基础,编译原理的学习为我们提供非常好的桥梁和道路。

7、参考文献

《编译原理》 机械工业出版社出版

Alfred V.Aho Ravi Sethi Jeffrey D,Ullman著

李建中 姜守旭等译

《程序设计语言 编译原理(第三版)》 国防工业出版社出版

陈火旺 刘春林 谭庆平赵克佳 刘越 著

第四篇:编译原理实验二(设计一个词法分析器)

编译原理实验二

1.实验名称:一个简单语言词法分析器设计

2.实验内容

(1)阅读并理解教材第三章词法分析p42“简单语言”词法分析构造实例

(2)完善P45给出的“简单语言”词法分析程序,使得该程序能够在计算机上运行,完

全达到词法分析器的设计基本要求:

① 读入“简单语言”源程序

②滤掉“简单语言”源程序中的“空白”字符

③滤掉“简单语言”源程序中的“注释”字符

④能够识别出“简单语言”源程序中的合法“单词”并输出识别出的一个个“单词”符号序列。

⑤ 识别出的一个个“单词”符号要求为二元组形式: 指出单词类别属性,标识符自身值,常数值.3.提交实验报告

 “简单语言”词法分析程序“源程序”文件

 “简单语言”词法分析程序“源程序”可执行文件

 对“简单语言”词法分析程序的测试实例:“简单语言”源程序及其词法分析结果。

第五篇:编译原理课程设计

课 程 设 计 报 告

设计题目:一个简单文法的编译器前端的设计与实现

级: 计算机1206 组长学号:201239 组长姓名:闫智宣 指导教师:李晓华 设计时间:2014年12月

[在此处键入]

设计分工

组长学号及姓名: 20123974

闫智宣

分工:

语法分析,四元式生成,目标代码优化及生成 组员1学号及姓名:20123977

廖峭 分工:

词法分析,错误处理 组员2学号及姓名:20123959

郭天龙

分工:

符号表生成,语义动作插入,操作界面[在此处键入]

摘要

编译原理课程设计是通过C语言编译器相关子系统的设计,进一步加深对编译器构造的理解;第一部分词法分析,设计各单词的状态转换图,并为不同的单词设计种别码,制作扫描器识别一个个单词,返回值为识别码的序号,返回Token序列。将词法分析器设计成供语法分析器调用的子程序。词法分析器具备预处理功能。将不翻译的注释等符号先滤掉,只保留要翻译的符号串,即要求设计一个供词法分析调用的预处理子程序;第二部分,语法分析,用递归下降法,实现对表达式、各种说明语句、控制语句进行语法分析。若语法正确,则用语法制导翻译法进行语义翻译;生成并打印出语法树;若语法错误,要求指出出错性质和出错位置(行号)。

我们还做了附加功能,即编译后端,有中间代码优化,生成目标代码汇编语言。通过此次课程设计,提高了我们的独立分析问题、解决问题的能力,以及系统软件设计的能力; 提高程序设计能力、程序调试能力,团结协作能力

关键词:词法分析,语法分析,四元式生成,错误处理,符号表生成,语义动作插入,中间代码优化,生成目标代码 [在此处键入]

目录

摘要

1.概述

2.课程设计任务及要求

2.1 设计任务

2.2 设计要求

3.算法及数据结构

3.1算法的总体思想(流程)

3.2 词法分析模块

3.2.1 功能

3.2.2 数据结构

3.2.3 算法

3.3 语法分析模块

3.3.1功能

3.3.2 数据结构

3.3.3算法

3.4 符号表模块

3.4.1功能

3.4.2 数据结构

3.4.3算法

3.5 四元式模块

3.5.1功能

[在此处键入]

3.5.2 数据结构

3.5.3算法

3.6 语义动作分析模块

3.6.1功能 3.6.2 数据结构

3.6.3算法

3.7 错误处理模块

3.7.1功能

3.7.2 数据结构

3.7.3算法

3.8 目标代码模块

3.8.1功能

3.8.2 数据结构

3.8.3算法

4.程序设计与实现

4.1 程序流程图

4.2 程序说明

4.3 实验结果

5.结论 6.参考文献。7.收获、体会和建议。

[在此处键入]

1.概述

编译器是将C语言翻译为汇编语言代码的计算机程序。编译器将源程序(source language)编写的程序作为输入,翻译产生目标语言(target language)机器代码的等价程序。通常地,源程序为高级语言(high-level language),C语言程序,而目标则是 机器语言的目标代码(object code),也就是可以在计算机硬件中运行的机器代码软件程序。这一过程可以表示为:

源程序→编译器 →目标机器代码程序

2.课程设计任务及要求

2.1设计任务

学生在学习《编译原理》课程过程中,结合各章节的构造编译程序的基本理论,要求用C#语言描述及上机调试,实现一个 C编译程序(包括词法分析,语法分析等重要子程序),使学生将理论与实际应用结合起来,受到软件设计等开发过程的全面训练,从而提高学生软件开发的能力。

2.2设计要求 要求:

(1)设计词法分析器

设计各单词的状态转换图,并为不同的单词设计种别码。将词法分析器设计成供语法分析器调用的子程序。功能包括:

a.具备预处理功能。将不翻译的注释等符号先滤掉,只保留要翻译的符号串,即要求设计一个供词法分析调用的预处理子程序;

b.能够拼出语言中的各个单词; [在此处键入]

c.返回(种别码,属性值,行号)。

(2)语法分析

要求用学习过的自底向上或自顶向下的分析方法等,实现对表达式、各种说明语句、控制语句进行语法分析。若语法正确,则用语法制导翻译法进行语义翻译;生成并打印出语法树;若语法错误,要求指出出错性质和出错位置(行号)。

3.算法及数据结构

3.1算法的总体思想(流程)

本节主要分析程序的代码结构和代码工程文件的划分。(程序由几个类组成: Token类和Variable类SymbolTable类ObjectCode类Lexical类Grammar类Four_Yuan类Action类ErrorItem类,分别为词法分析和语法分析类。工程分为几个文件:Form1.cs,Token.cs,Variable.cs,SymbolTable.cs,ObjectCode.cs,Lexical.cs,Grammar.cs,Four_Yuan,cs,Action.cs,ErrorItem.cs分别对应Token类和Variable类SymbolTable类ObjectCode类Lexical类Grammar类Four_Yuan类Action类ErrorItem类的声明和实现文件)。本程序采用C#语言以面向对象的思想编写,程序分为几部分:词法分析(Lexical),语法分析(Grammer),目标代码生成(ObjectCode)。Lexical类主要的工作是词法分析获取Token。Grammer类的主要工作是根据Lexical类词法分析之后的Token进行语法分析,生成语法树,最后并输出语法树。在处理过程中,Token类的对象作为Lexical类的一个成员变量,配合Grammer类进行语法分析。

工程文件总体上是按照九个类的格局分为十个文件,分别是九个类的声明文件和实现文件。十个文件为Form1.cs,Token.cs,Variable.cs,SymbolTable.cs,ObjectCode.cs,Lexical.cs,Grammar.cs,Four_Yuan,cs,Action.cs,ErrorItem.cs,他们分别是Lexical类声明文件、Lexical类实现文件、Grammer类声明文件、Grammer类实现文件。[在此处键入]

程序流程

在程序中,Lexical类的对象(Token)作为Grammer类中的一个成员变量,配合Grammer类进行语法分析。它们的关系是这样的:Grammer类的一个成员变量temp首先对源程序删除注释,然后进行词法分析获取所有Token,并将获取的Token存储在Token对象的tokenList(List类型)中。然后Grammer类的语法分析程序就根据tokenList中的Token进行语法分析,生成语法树,最后打印语法树。同时,这也是程序的流程。[在此处键入]

3.2 词法分析模块 3.2.1功能

Lexical类主要的工作是词法分析获取Token序列。

3.2.2数据结构

词法分析阶段的代码被封装成一个类——Lexical,Token中主要是Lexical类的声明代码,Lexical.cs中主要是Lexical类的实现代码。Lexical类对外提供的函数主要有:

static public int RecogId(string str, int i),static public int RecogDig(string str,int i),static public int RecogOperator(string str, int i),static public int RecogBound(string str, int i),以上几个函数构成了词法分析的骨架,在Lexical类中还有其他成员变量和函数,主要作为这三个函数处理过程的中间步骤,为这三个函数服务。Lexical类的代码结构和主要的成员变量和函数及其含义如下图所示:

3.2.3算法

算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是[在此处键入]

根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。

主程序示意图:

主程序示意图如图3-1所示。

⑴ 关键字表的初值。

关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。

(2)程序中需要用到的主要变量为type和number 扫描子程序的算法思想:

首先设置3个变量: [在此处键入]

①token用来存放构成单词符号的字符串; ②number用来整型单词;

③type用来存放单词符号的种别码。

Token定义

Token定义:

Token类型(TokenType):

3.3 语法分析模块

3.3.1功能

语法分析是编译过程的一个逻辑阶段。语法分析的功能是在词法分析的基础上将单词序列组合成各类语法短语,如“程序”,“语句”,“表达式”等等.语法分析程序判断源程序在结构上是否正确.源程序的结构由上下文无关文法描述.3.3.2 数据结构

下图为实现语法分析的类Grammar,属性与方法的作用都已说明 在此处键入]

3.3.3算法

1.文法

下面终结符与非终结符意义

B程序开始

Z 数据类型,如int,char,float等

V 标识符

S 语句

P 语句块

E 加减算术表达式

D 逗号表达式

T 乘除算术表达式

C 关系表达式

L 逻辑表达式

Q 标识符或圆括号

e 表示空

i 表示标识符 a)函数文法

B----ZV()S

[

[在此处键入]

b)语句块文法

P----SP|e

S----{P} c)语句文法

表达式语句文法

S----V=E

goto语句文法

S----i:S

S----goto i

if语句文法

S----if(E)S[else S]

while语句文法

S----while(E)S

声明语句文法

S----ZVD

D----,VD|=ED|e d)表达式文法

E----T|E+T|E-T

T----F|T*F|T/F

C----C|CL|C==C|C<= L|C>=L

L----Q|L&&Q|L||Q

Q----i|(E)|!Q

2.递归下降程序流程图

对应于每个文法编写如下递归下降子程序

主程序(B)[在此处键入] [在此处键入]

3.4 符号表模块

3.4.1功能

进行符号表的储存,添加,更新,查找,保存标识符活跃信息以及输出。3.4.2 数据结构

在此处键入]

3.4.3算法

3.5 四元式模块

3.5.1功能

四元式为中间代码,编译程序进行完语义分析后,先生成中间代码作为过渡,此时中间代码与目标代码已经比较相似

3.5.2 数据结构

[ 在此处键入]

3.5.3算法

3.6语义动作分析模块

3.6.1功能

在语法分析中嵌入相应的语义动作,生成四元式 3.6.2 数据结构

[

[在此处键入]

3.6.3算法 GEQ(+)(-)(*)(/)

(+,i1,i2,t)PUSH(i)ASSI(=)

(=,t,_,POP)LABER(i)

(lb,_,_,i)GOTO(i)

(gt,_,_,i)IF(if)

(if,a,_,_)EL(el)

(el,_,_,_)IE(ie)

(ie,_,_,_)WH()

(wh,_,_,_)DO()

(do,a,_,_)WE(we)

(we,_,_,_)

3.7 错误处理模块

3.7.1功能 保存运行时发现的错误,储存行号已经详细信息并输出。

3.7.2 数据结构

3.7.3算法 [在此处键入]

public static void AddErrorMessage(int lineno,string content)函数用作在发现错误时保存错误信息以及行号。

public static string PrintErrorList()把所有发现的错误格式化后统一输出。

错误信息在语法分析,语义分析,符号表检错中添加。3.8 目标代码模块

3.8.1功能

目标代码生成把优化后的中间代码变换成目标代码,此处的目标代码为汇编代码,采用单寄存器生成目标代码 3.8.2 数据结构[在此处键入]

3.8.3算法

对于一个基本块有如下流程图

W:操作符,B:第一操作数,C:第二操作数,R:寄存器

5.结论

网上找一段话抄上 [在此处键入]

6.测试

测试打开文件

测试保存文件

如果没打开文件,直接敲代码,点保存时会弹出另存为窗口[在此处键入]

测试错误检测,程序缺少main函数的类型,错误列表中显示第一行函数缺少错误类型。

测试错误检测,程序缺少分号,错误列表中显示该行缺少语句结束标志';' 单击错误列表,会自动选定错误行

编译成功,生成并显示token串、符号表、四元式与目标代码 [在此处键入]

测试if与while语句,而且while嵌套在if当中

测试goto语句,结果正确。[在此处键入]

测试优化,输入课件中的代码,结果与课件一样

6.参考文献。

1、陈火旺.《程序设计语言编译原理》(第3版).北京:国防工业出版社.2000.2、美 Alfred V.Aho Ravi Sethi Jeffrey D.Ullman著.李建中,姜守旭译.《编译原理》.24 [在此处键入]

北京:机械工业出版社.2003.3、美 Kenneth C.Louden著.冯博琴等译.《编译原理及实践》.北京:机械工业出版社.2002.4、金成植著.《编译程序构造原理和实现技术》.北京:高等教育出版社.2002.7.收获、体会和建议。

直接拷贝好歹也检查一下错误

对于编译原理的这次课程设计,自己经历了从刚开始的不懂明白任务的要求和内容理论知识的了解开始着手写代码完成基本功能根据DFA及自顶向下等理论修改完善代码等这些过程。

自己着手写词法分析的时候还不清楚词法分析的任务内容,还不知道词法分析的结果是什么,词法分析出错的情况和类型有哪些,也总是将词法分析和语法分析混在一起,不明白哪些错误在词法分析中报,哪些错误在语法分析中判断,后来经过查书、网上资料、请教同学等途径逐步清晰了词法分析的工作内容是从源代码文件中获取出Token,供语法分析使用。在充分了解了语法分析需要哪些信息时,我才真正了解了词法分析的工作内容和目标,才知道词法分析需要完成哪些任务获取到哪些信息。充分了解了词法分析的任务之后,就开始理论知识的学习。经过揣摩书上的例子,自己理解和掌握了怎么设计过滤注释和分析程序中Token的DFA,于是开始根据设计好的DFA进行编码,最后经过调试已经可以正确地完成词法阶段的任务了。这只是词法分析的原始代码,在之后还进行了两次彻底的改动。虽然之前写的词法分析的代码已经完成了词法分析的需求,也是根据DFA的原理编写的,但是在代码结构上却难以体现,在对书上的根据已知DFA写代码的例子进行了详细的研究之后,发现自己的代码并没有像书上那样完全按照所依据的DFA各状态转移的关系进行编写,所以对代码进行了重写,像书上一样严格按照状态之间转移的方式进行编写,将状态划分成11个状态,状态分别按1~11进行标注,程序也按照DFA来编写,也实现了词法分析的功能。再后来写报告的时候,发现分析出Token的那个DFA并不是最简的,有很多多余的状态,完全可以用一个flag标志来标识,从而简化代码结构,于是又重写了一次词法分析函数scan()的代码,将状态缩减为5个,且不再用1-5来表示,而是像书上那样分别取了名字(START、INNUM、INID、INDBSYM、DONE),同时为了简化代码将输出Token到文件的部分从scan()中剥离开来,而在Lexical类中加了一个printToken()的函数,使scan()函数逻辑更加清晰,使读者能够容易地将代码与DFA进行查看比照。

在写语法分析的时候,已经对编译器的语法分析的内容有了一定的了解,所以直接进行了理论的学习。首先自己对递归向下分析法进行了学习,将书上的几个递归向下分析的伪代码看过之后,自己对递归向下的分析方法的原理有了初步的认识,大概知道了根据文法怎么分析,但是对于如何编写代码却还在此处键入]

是难以下手,于是就对照TINY语言的文法看了几遍书后面的TINY语言的递归向下分析的语法分析程序,这样就基本知道了C-语言的语法分析程序怎么写。由于C-语言给出的文法有左递归存在,于是自己将存在左递归的文法改写成EBNF的形式,并据此进行代码编写。由于在编写代码的过程中需要确定分析是否正确或选择多个文法中的某一个文法进行分析,有时必须探测需要的或下一个Token的类型,在这种情况下需要求First集合,在推导中若存在empty,又需要求Follow集合,所以这样又需要我了解First集合和Follow集合,自己在程序中也根据求出的First集合和Follow集合进行判断,以确定程序的走向。在编写过程中,还有一类问题,就是存在公共左因子,如文法expression→ var = expression | simple-expression,左因子为ID,在分析过程中,由于已经取出了一个ID的Token,且生成了一个IdK的节点,但是在当前状态无法确定是哪一个推导,然而IdK节点已经生成,又无法回退,并且是使用自顶向下的分析方法,已经生成的IdK在程序上方无法使用,自己通过查阅资料等途径的学习确定了在这种情形下的处理方式:将已经生成的IdK节点传到下方的处理程序,所以TreeNode * simple_expression(TreeNode * k)、TreeNode * additive_expression(TreeNode * k)等函数都被设计成有节点类型参数的函数,目的就是将已经生成的节点传到下面的分析函数中去。

通过这次的编译原理课程的学习和实践,自己获益良多。首先最基本的成果是完成了课程设计的任务,实现了编译器的词法分析和语法分析阶段的功能,词法分析主要能过滤注释、分析出语法分析阶段需要的Token并满足语法阶段的所有要求,能够判别词法分析阶段是否出错和出错类型和位置。语法分析主要能根据递归向下的分析思想和C-文法对词法分析获取的Token进行语法分析,能够构造出语法树,能够判别语法分析过程中是否出错以及出错位置和错误类型。

由于在编写程序过程中,涉及到了正则表达式、DFA、提取公共左因子、消除左递归、EBNF、求First集合和Follow集合、递归向下分析方法以及编程语言方面的知识,所以,通过本次的课程设计的实践,使得自己对编译原理这门课的许多知识点有了更加深刻和具体的理解,而不再只限制于做题。此外,对以前那些已掌握的知识有了温习和动手锻炼的机会。如:以前在编译原理课上虽然知道First集合和Follow集合怎么求的,却不知道First集合和Follow集合到底是干什么的,通过编写程序自己明白了他们的实际作用,使得自己不仅知其然还知其所以然,从而使得自己加深了对知识点的理解和掌握。由于以前编写代码都是使用JAVA语言,所以C/C++很多内容都忘记了,通过本次的实践,自己又重新拾起了以前的知识。此外,由于在做报告的时候,需要描绘DFA和程序流程图,使得自己初步掌握了使用visio和word画图的能力。此外,对于文档的编写和美化自己也获得了许多有用的经验。[

下载编译原理 语法分析器 (java完美运行版)word格式文档
下载编译原理 语法分析器 (java完美运行版).doc
将本文档下载到自己电脑,方便修改和收藏,请勿使用迅雷等下载。
点此处下载文档

文档为doc格式


声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:645879355@qq.com 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

相关范文推荐

    编译原理 学习心得

    国际学院 0802 杨良燕 200819100227《编译原理》课程学习心得 《编译原理》是计算机专业的一门重要课程,正如教材 第一章的引论所述,“编译程序是现代计算机系统的基本组成部......

    编译原理论文

    编译原理心得体会 编译原理是计算机专业的一门重要专业课,旨在介绍编译程序构造的一般原理和基本方法,在计算机本科教学中占有十分重要的地位。 该课程理论性与实践性都很强,我......

    编译原理实验报告[合集]

    编译原理实验报告 报告完成日期 2018.5.30 一. 组内分工与贡献介绍 二. 系统功能概述; 我们使用了自动生成系统来完成我们的实验内容。我们设计的系统在完成了实验基本要求的......

    编译原理课程设计简介

    编译原理实践课程 编译原理课程是计算机专业必修的一门重要的专业基础课程,也是计算机系统软件中非常重要的一个分支,经过多年建设取得了丰硕的教学成果:2003年被评为“吉林大......

    《编译原理课程设计》教学大纲

    《编译原理课程设计》教学大纲 课程名称: 课程编号: 适用专业: 总 学 分: 总 周 时: 主 撰 人: 撰写日期: 一、目的与任务 通过程序设计上机调试程序实现算法,学习编译程序调试技巧......

    合肥工业大学编译原理课程设计

    关于《编译原理》课程设计的有关说明 《编译原理》是计算机专业的一门重要的专业课程,其中包含大量软件设计思想。大家通过课程设计,实现一些重要的算法,或设计一个完整的编译......

    编译原理课程设计教案

    黄冈师范学院 《编译原理课程设计》教案 (2011·春) 授 课 教 师: 张 瑞 红 授 课 班 级: 计科2008级 授 课 时 间: 2010-2011 二 课题一 有限自动机的运行 一、设计题目:有限......

    编译原理课程设计心得体会

    编译原理课程设计心得体会 经过一个星期的编译原理课程设计,本人在刘贞老师的指导下,顺利完成该课程设计。通过该课程设计,收获颇多。一、对实验原理有更深的理解通过该课程......