当前位置:文档之家› 编译原理实验四

编译原理实验四

编译原理实验四
编译原理实验四

编译原理实验报告

实验名称NFA转换为DFA

实验时间2014-5-18

院系计算机科学与技术学院

班级

学号

姓名

1.试验目的

不确定有限状态自动机的确定化(Affirmation of the indefinitely finite automata)

2.实验原理

一个确定的有限自动机(DFA)M可以定义为一个五元组,M=(K,∑,F,S,Z),其中:

(1)K是一个有穷非空集,集合中的每个元素称为一个状态;

(2)∑是一个有穷字母表,∑中的每个元素称为一个输入符号;

(3)F是一个从K×∑→K的单值转换函数,即F(R,a)=Q,(R,Q∈K)表示当前状态为R,如果输入字符a,则转到状态Q,状态Q称为状态R的后继状态;

(4)S∈K,是惟一的初态;

(5)Z?K,是一个终态集。

由定义可见,确定有限自动机只有惟一的一个初态,但可以有多个终态,每个状态对字母表中的任一输入符号,最多只有一个后继状态。

对于DFA M,若存在一条从某个初态结点到某一个终态结点的通路,则称这条通路上的所有弧的标记符连接形成的字符串可为DFA M所接受。若M的初态结点同时又是终态结点,则称ε可为M所接受(或识别),DFA M所能接受的全部字符串(字)组成的集合记作L(M)。

一个不确定有限自动机(NFA)M可以定义为一个五元组,M=(K,∑,F,S,Z),其中:

(1)k是一个有穷非空集,集合中的每个元素称为一个状态;

(2)∑是一个有穷字母表,∑中的每个元素称为一个输入符号;

(3)F是一个从K×∑→K的子集的转换函数;

(4)S?K,是一个非空的初态集;

(5)Z?K,是一个终态集。

由定义可见,不确定有限自动机NFA与确定有限自动机DFA的主要区别是:

(1)NFA的初始状态S为一个状态集,即允许有多个初始状态;

(2)NFA中允许状态在某输出边上有相同的符号,即对同一个输入符号可以有多个后继状态。即DFA中的F是单值函数,而NFA中的F是多值函数。

因此,可以将确定有限自动机DFA看作是不确定有限自动机NFA的特例。和DFA一样,NFA也可以用矩阵和状态转换图来表示。

对于NFA M,若存在一条从某个初态结点到某一个终态结点的通路,则称这条通路上的所有弧的标记(ε除外)连接形成的字符串可为M所接受。NFA M所能接受的全部字符串(字)组成的集合记作L(M)。

由于DFA是NFA的特例,所以能被DFA所接受的符号串必能被NFA所接受。

设M

1和M

2

是同一个字母集∑上的有限自动机,若L(M

1

)=L(M

2

),则称有

限自动机M

1和M

2

等价。

由以上定义可知,若两个自动机能够接受相同的语言,则称这两个自动机等

价。DFA是NFA的特例,因此对于每一个NFA M

1总存在一个DFA M

2

,使得L(M

1

=L(M

2

)。即一个不确定有限自动机能接受的语言总可以找到一个等价的确定有限自动机来接受该语言。

NFA确定化为DFA

同一个字符串α可以由多条通路产生,而在实际应用中,作为描述控制过程的自动机,通常都是确定有限自动机DFA,因此这就需要将不确定有限自动机转换成等价的确定有限自动机,这个过程称为不确定有限自动机的确定化,即NFA 确定化为DFA。

下面介绍一种NFA的确定化算法,这种算法称为子集法:

(1)若NFA的全部初态为S1,S2,…,S n,则令DFA的初态为:

S=[S1,S2,…,S n],

其中方括号用来表示若干个状态构成的某一状态。

(2)设DFA的状态集K中有一状态为[S i,S i+1,…,S j],若对某符号a∈∑,在NFA 中有F({ S i,S i+1,…,S j },a)={ S i’,S i+1’,…,S k’ }

则令F({ S i,S i+1,…,S j},a)={ S i’,S i+1’,…,S k’}为DFA的一个转换函数。

若[ S i’,S i+1’,…,S k‘ ]不在K中,则将其作为新的状态加入到K中。

(3)重复第2步,直到K中不再有新的状态加入为止。

(4)上面得到的所有状态构成DFA的状态集K,转换函数构成DFA的F,DFA的字母表仍然是NFA的字母表∑。

(5)DFA中凡是含有NFA终态的状态都是DFA的终态。

对于上述NFA确定化算法——子集法,还可以采用另一种操作性更强的描述方式,下面我们给出其详细描述。首先给出两个相关定义。

假设I是NFA M状态集K的一个子集(即I∈K),则定义ε-closure(I)为:

(1)若Q∈I,则Q∈ε-closure(I);

(2)若Q∈I,则从Q出发经过任意条ε弧而能到达的任何状态Q’,则Q’∈ε-closure(I)。

状态集ε-closure(I)称为状态I的ε闭包。

=ε-closure 假设NFA M=(K,∑,F,S,Z),若I∈K,a∈∑,则定义I

a

(J),其中J是所有从ε-closure(I)出发,经过一条a弧而到达的状态集。

NFA确定化的实质是以原有状态集上的子集作为DFA上的一个状态,将原状态间的转换为该子集间的转换,从而把不确定有限自动机确定化。经过确定化后,状态数可能增加,而且可能出现一些等价状态,这时就需要简化。

3.实验内容

输入:非确定有限(穷)状态自动机。

输出:确定化的有限(穷)状态自动机

4.实验心得

此次实验采用了java可视化的界面来编程的,编程的主要思想是:首先构造NFA的状态的子集的算法,再来计算ε-closure。完成这些子模块的设计后,再通过某一中间模块的总控程序对其调用,最后再由主程序总调用,也就实现了NFA转化为其等价的DFA,接下来就是在实现DFA的化简,最后加以验证,经多次代码的修改成型。通过实验,我可以更好的掌握了NFA到DFA的转化的原理。

5.实验代码与结果

5.1实验运行结果截图如下:

左侧为输入的每个NFA的每个状态,右侧为显示的结果,显示了子集个数,和由NFA构造的·DFA状态。

5.2代码:

package wy;

import java.awt.Graphics;

import java.awt.Graphics2D;

import java.awt.Image;

import java.awt.Toolkit;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.util.ArrayList;

import javax.swing.*;

class Node{ //每一个结点包含的有以该结点为起始的整条边的信息:String data; //本结点值

String condition;//条件值空符号串用ε表示

String next;//指向下一个结点的结点值

Node(String d)//终止结点

{

data=d;

condition=null;

next=null;

}

Node(String d,String c,String s)//非终止结点

{

data=d;

condition=c;

next = s; //下一个结点的值

}

}

public class NFA_DFA extends JFrame{

public static void main(String[] args) {

NFA_DFA nfa_dfa=new NFA_DFA();

nfa_dfa.NFA_DFA();

}

public JLabel jl0 = new JLabel("----每条边的信息如下:----------------");

public JLabel jl_start = new JLabel("起点状态:");

public JLabel jl_condition = new JLabel("条件:");

public JLabel jl_end = new JLabel("终点状态:");

public JTextField jtf_start = new JTextField();

public JTextField jtf_condition = new JTextField();

public JTextField jtf_end = new JTextField();

public JButton jbt0 = new JButton("确定");

public JLabel jl_start0 = new JLabel("初态:");

public JLabel jl_end0 = new JLabel("终态:");

public JButton jbt1 = new JButton("确定");

public JTextField jtf_start0 = new JTextField();

public JTextField jtf_end0 = new JTextField();

public JTextArea jta_display = new JTextArea();

public JScrollPane sta1 = new JScrollPane(jta_display);

public JButton jbt_result = new JButton("结果显示");

public JTextArea jta_display1 = new JTextArea();

public JScrollPane sta2 = new JScrollPane(jta_display1);

public ArrayList node = new ArrayList();//非终止结点

public ArrayList node_end = new ArrayList();//终止结点public ArrayList condition = new ArrayList();//条件符号public ArrayList> C=new ArrayList>();//子集族C

public ArrayList CC=new ArrayList();//重命名的C

public String start0;//初态值

public void NFA_DFA(){

this.setTitle("NFA转换为DFA----WY");

this.setContentPane(new MyPanel5());

this.setLayout(null);

this.setSize(700, 700);

jl_start0.setBounds(150, 35, 70, 30);

add(jl_start0);

jtf_start0.setBounds(200, 35,120, 30);

add(jtf_start0);

jl_end0.setBounds(350, 35, 70, 30);

add(jl_end0);

jtf_end0.setBounds(400, 35, 120, 30);

add(jtf_end0);

jbt1.setBounds(555, 35, 60, 30);

add(jbt1);

jl0.setBounds(200, 80,200, 30);

add(jl0);

jl_start.setBounds(145, 110, 70, 30);

add(jl_start);

jl_condition.setBounds(300, 110,50, 30);

add(jl_condition);

jl_end.setBounds(445, 110, 70, 30);

add(jl_end);

jtf_start.setBounds(130, 140, 80, 30);

add(jtf_start);

jtf_condition.setBounds(280, 140,80, 30);

add(jtf_condition);

jtf_end.setBounds(430, 140, 80, 30);

add(jtf_end);

jbt0.setBounds(555, 140, 60, 30);

add(jbt0);

sta1.setBounds(80, 250, 200, 400);

add(sta1);

sta2.setBounds(300, 250, 300, 400);

add(sta2);

jbt_result.setBounds(300, 200, 100, 30);

add(jbt_result);

this.setVisible(true);

jta_display.append("每条边的显示:\n");

jbt1.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

start0=jtf_start0.getText(); //初态

String str3 = jtf_end0.getText();

String[] ss3 = new String[100];

ss3 = str3.split(","); // 终态在输入的时候以","隔开

for (int i = 0; i < ss3.length; i++) {

Node node_end0=new Node(ss3[i]);

node_end.add(node_end0); //将终态加入终止结点中

}

}

});

jbt0.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

jta_display.append(jtf_start.getText()+"—>"+jtf_condition.getText()

+"—>"+jtf_end.getText()+"\n");

Node node_temp=new Node(jtf_start.getText(),jtf_condition.getText(),jtf_end.getText());

node.add(node_temp); //加入非终止结点

if(!condition.contains(jtf_condition.getText())

&& !jtf_condition.getText().equals("ε"))

condition.add(jtf_condition.getText()); //加入条件符号

jtf_start.setText(null);

jtf_condition.setText(null);

jtf_end.setText(null);

}

});

jbt_result.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

myNFA_DFA();

}

});

}

public void myNFA_DFA(){

ArrayList flag=new ArrayList();//标记

//1、找起始结点,计算起始结点的T0=e_closure(start0); 此时T0没有标记,是子集族C中唯一的元素

ArrayList T0=new ArrayList();

T0=e_closure(start0);

C.add(T0);

flag.add(false);//此时T0没有标记

//2.标记T0;T1=e_closure(move(T0,a)),T2=e_closure(move(T0,b))····,将T1,T2加入C中,但是未标记

flag.set(0,true);//标记T0

for(int i=0;i

{ ArrayList T=new ArrayList();

ArrayList t1=new ArrayList();

t1=move(T0,condition.get(i));

T=e_closure0(t1);

if(!C.contains(T))

{

C.add(T);

flag.add(false);

}

}

//3.分别标记flag=false的对应的C中的项

while(flag.contains(false)){

int index=flag.indexOf(false);

flag.set(index,true);//标记C的index,即

ArrayList C_temp=new ArrayList();

C_temp=C.get(index);

for(int i=0;i

{ ArrayList T=new ArrayList();

ArrayList t1=new ArrayList();

t1=move(C_temp,condition.get(i));

T=e_closure0(t1);

if(!C.contains(T))

{

C.add(T);

flag.add(false);

}

}

}

display();//在文本域中显示结果

}

public void display(){

jta_display1.append("算法终止共构造了"+C.size()+"个子集:\n");

for(int i=0;i

{

jta_display1.append("T"+i+" = "+C.get(i)+"\n");

CC.add("T"+i); //给新得的子集重新命名T1,T2,T3....

}

jta_display1.append("给定NFA构造的DFA为:\n");

jta_display1.append("1、S={");

for(int i=0;i

jta_display1.append("["+CC.get(i)+"],");

jta_display1.append("["+CC.get(CC.size()-1)+"]}\n");

jta_display1.append("2、ε={");

for(int i=0;i

jta_display1.append(CC.get(i)+",");

jta_display1.append(CC.get(CC.size()-1)+"}\n");

ArrayList D=new ArrayList();

D=transform(C);

jta_display1.append("3、\n");

for(int i=0;i

jta_display1.append(D.get(i)+"\n");

jta_display1.append("4、S0= ["+CC.get(0)+"]\n");

jta_display1.append("5、St= ["+CC.get(CC.size()-1)+"]\n");

}

public ArrayList transform(ArrayList> c){ //转换函数D

ArrayList r=new ArrayList();

ArrayList r_temp = new ArrayList();

for(int i=0;i

ArrayList c_temp = new ArrayList();

c_temp=c.get(i);

for(int j=0;j

r_temp=e_closure0(move(c_temp,condition.get(j)));

for(int k=0;k

if(r_temp.equals(C.get(k)))

r.add(" D( ["+CC.get(i)+"] , "+condition.get(j)+" ) = ["+CC.get(k)+"]");

}

}

}

return r;

}

public ArrayList e_closure0(ArrayList AA){

ArrayList T1=new ArrayList();

for(int i=0;i

{

ArrayList T=new ArrayList();

T=e_closure(AA.get(i));

for(int j=0;j

T1.add(T.get(j));

}

}

return T1;

}

public ArrayList e_closure(String A){

ArrayList T=new ArrayList();

for(int k=0;k

if(A.equals(node_end.get(k).data)){

if(!T.contains(A))

T.add(A); //e_closure()将自身也包含进去的

}

}

for(int i=0;i

if(A.equals(node.get(i).data) ){

if(!T.contains(A))

T.add(A); //e_closure()将自身也包含进去的

if(node.get(i).condition.equals("ε")){

T.add(node.get(i).next); //经过一条ε弧

for(int j=0;j

if(node.get(i).next.equals(node.get(j).data)

&& node.get(j).condition.equals("ε")){

T.add(node.get(j).next); //经过两条ε弧

for(int k=0;k

if(node.get(j).next.equals(node.get(k).data)

&& node.get(k).condition.equals("ε")){

T.add(node.get(k).next); //经过三条ε弧

for(int m=0;m

&&

node.get(m).condition.equals("ε")){

T.add(node.get(m).next); //经过四条ε弧

}

}

}

}

}

}

}

}

}

return T;

}

public ArrayList move(ArrayList TT,String a){ //move(I,a)函数

ArrayList T=new ArrayList();

for(int i=0;i

for(int j=0;j

if(TT.get(i).equals(node.get(j).data) && node.get(j).condition.equals(a)){

T.add(node.get(j).next);

}

}

}

return T;

}

}

class MyPanel5 extends JPanel {

public void paintComponent(Graphics g) {

Graphics2D g2 = (Graphics2D) g;

super.paintComponent(g);

Image img = Toolkit.getDefaultToolkit().getImage(

"./src/1.jpg");

g2.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);

}

}

编译原理实验报告

课程实验报告课程名称:《编译原理》 专业班级:计算机科学与技术11级10班 学号:XXXXXXX 姓名:X X 指导教师:刘铭 报告日期:2014年6月16日

计算机科学与技术学院 目录 目录 (2) 1 实验一词法分析 (3) 1.1实验目的 (3) 1.2实验要求 (3) 1.3算法思想 (4) 1.4实验程序设计说明 (5) 1.5词法分析实现 (6) 1.6词法实验结果及结果分析 (12) 2 实验二语法分析 (13) 2.1 实验目的 (13) 2.2 实验要求 (13) 2.3 算法思想 (13) 2.4 实验程序设计说明 (15) 2.5 语法分析实现 (15) 4 实验中遇到的问题及解决 (22) 参考资料 (23)

1 实验一词法分析 1.1 实验目的 设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 1.2 实验要求 1、待分析的简单的词法 (1)关键字: begin if then while do end 所有的关键字都是小写。 (2)运算符和界符 := + - * / < <= <> > >= = ; ( ) # (3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义: ID = letter (letter | digit)* NUM = digit digit* (4)空格有空白、制表符和换行符组成。空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。 2、各种单词符号对应的种别码: 表1 各种单词符号对应的种别码 3、词法分析程序的功能: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。 其中:syn为单词种别码; token为存放的单词自身字符串;

编译原理实验(布置版)

编译原理实验(布置版) 实验一:基于有限自动机方法的简单词法分析程序的设计与实现 ——无符号实数识别程序 1、实验目的 通过本实验,使学生进一步熟悉词法分析程序所用的工具——自动机方法,掌握文法转换成自动机的技术及用C语言实现有穷自动机识别单词的方法。 2、实验内容 根据教材P46无符号实数的状态转换图,用C或C++语言编制识别无符号实数的程序。 要求:程序执行时,首先给出提示“Please input a unsigned real number:”,输入数据后,给出对该数据的分析结果信息如“The number is right!”或“The number is error!”,反复输入数据和分析,直到输入回车或其他键符,退出程序执行。 3、实验报告要求 按照实验报告模板格式要求组织内容,必须要有以下内容: (1)无符号实数词法分析的思想。 (2)无符号实数的文法和根据文法生成的状态转换图(即有穷自动机)。 (3)程序处理的流程图 (4)程序运行(测试)结果截图 (5)源程序清单 实验二:综合词法分析程序的设计与实现 1、实验目的 设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。 2、实验内容 (1)本程序自行规定: 关键字:“begin”,“end”,“if”,“then”,“else”,“while”,“write”,“read”,“do”,“call”,“const”,“char”,“until”,“procedure”,“repeat”。 运算符:“+”,“-”,“*”,“/”,“=” 界符:“{”,“}”,“[”,“]”,“;”,“,”,“.”,“(”,“)”,“:” 标识符:以字母开头的字符串。 空格、回车、换行符跳过。 (2)用C或C++语言编制程序,实现对下述一段源程序的词法分析。 //源程序文件位置及名称:F:\…\MY.TXT begin x:=9 if x>0 then x:=x+1; while a:=0 do b:=2*x/3; end;

编译原理实验指导

编译原理实验指导 实验安排: 上机实践按小组完成实验任务。每小组三人,分别完成TEST语言的词法分析、语法分析、语义分析和中间代码生成三个题目,语法分析部分可任意选择一种语法分析方法。先各自调试运行,然后每小组将程序连接在一起调试,构成一个相对完整的编译器。 实验报告: 上机结束后提交实验报告,报告内容: 1.小组成员; 2.个人完成的任务; 3.分析及设计的过程; 4.程序的连接; 5.设计中遇到的问题及解决方案; 6.总结。

实验一词法分析 一、实验目的 通过设计编制调试TEST语言的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 二、实验预习提示 1.词法分析器的功能和输出格式 词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符号常常表示 成以下的二元式(单词种别码,单词符号的属性值)。 2.TEST语言的词法规则 |ID|ID |NUM →a|b|…|z|A|B|…|Z →1|2|…|9|0 →+|-|*|/|=|(|)|{|}|:|,|;|<|>|! →>=|<=|!=|== →/* →*/ 三、实验过程和指导 1.阅读课本有关章节,明确语言的语法,画出状态图和词法分析算法流程图。 2.编制好程序。 3.准备好多组测试数据。 4.程序要求 程序输入/输出示例:

编译原理实验报告

编译原理实验报告 姓名: 学号: 班级: 学院: 南昌大学信息工程学院计算机系 2014年6月

目录 实验一 (3) 实验二 (8) 实验三 (15)

实验1 词法分析程序的设计 学生姓名:学号:专业班级: 实验类型:□验证□综合□设计□创新实验日期:实验成绩: 一、实验目的 掌握计算机语言的词法分析程序的开发方法。 二、实验内容 编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。 三、实验要求 1、根据以下的正规式,编制正规文法,画出状态图; 标识符<字母>(<字母>|<数字字符>)* 十进制整数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)(0|1|2|3|4|5|6|7)* 十六进制整数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)* 运算符和界符+ - * / > < =<= >=( ) ;{ } 关键字main if then else while do int (可根据需要添加) 2、根据状态图,设计词法分析函数int scan( ),完成以下功能: 1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词, 2)以二元式形式输出单词<单词种类,单词属性> 其中单词种类用整数表示: 0:标识符 1:十进制整数 2:八进制整数 3:十六进制整数 运算符和界符,关键字采用一字一符,不编码 其中单词属性表示如下: 标识符,整数由于采用一类一符,属性用单词表示 运算符和界符,关键字采用一字一符,属性为空 3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。 四、实验环境 PC微机 DOS操作系统或Windows 操作系统 Turbo C 程序集成环境或Visual C++ 程序集成环境

编译原理实验教(学)案

实验教学进度表

实验一 C语言子集编译程序 一、实验目的 用C语言对一个C语言的子集编制一个一遍扫描的编译程序,以加深对编译原理的理解,掌握编译程序的实现方法和技术。 1.设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 2.编制一个递归下降分析程序,并对C语言的简单子集进行分析。 3.通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换中间代码的语义翻译方法。 二、实验要求、容及学时 词法分析部分:2学时 (一)待分析的C语言子集的词法: 1.关键字 main if else int return void while 所有关键字都是小写。 2.专用符号 = + - * / < <= > >= == != ; : , { } [ ] ( ) 3.其他标记ID和NUM 通过以下正规式定义其他标记: ID→letter(letter|digit)*NUM→digit(digit)* letter→a|…|z|A|…|Z digit→0|…|9 4.空格由空白、制表符和换行符组成 空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段空格通

(二)词法分析程序的功能: 输入:所给文法的源程序字符串。 输出:二元组(syn,token或sum)构成的序列。其中, syn 为单词类别码。 token 为存放的单词自身字符串。 sum 为整型常量。 具体实现时,可以将单词的二元组用结构进行处理。 例如:对源程序 main() { int i=10; while(i) i=i-1; } 的源文件,经词法分析后输出如下序列: (1,main) (26,() (27,)) (30,{) (2,int) (10,i) (21,=) (20,10) (34,;) (7,while) (26,() (10,i) (27,)) (10,i) (21,=) (10,i) (23,-) (20,1) (34,;) (31, }) (三)词法分析程序主要算法思想: 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 : 注: ①关键字表初值 关键字作为特殊标识符处理,把它们预先安排在一表格中(称为关键字),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表可处理为一个字符串数组(实际为指向字符数组的指针数组),其描述如下: char *KEY_WORDS[8]= {“main”,”int”,”char”,”if”,”else”,”for”,”while”}; 为分析方便,这里把main作关键字处理。 ②程序中需要用到的主要变量:syn,token和sum。 2.扫描子程序(scaner)的算法思想

编译原理实验 中间代码生成

实验四中间代码生成 一.实验目的: 掌握中间代码的四种形式(逆波兰式、语法树、三元式、四元式)。 二.实验内容: 1、逆波兰式定义:将运算对象写在前面,而把运算符号写在后面。用这种表示法表示的表 达式也称做后缀式。 2、抽象(语法)树:运算对象作为叶子结点,运算符作为内部结点。 3、三元式:形式序号:(op,arg1,arg2) 4、四元式:形式(op,arg1,arg2,result) 三、以逆波兰式为例的实验设计思想及算法 (1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。 (2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。 (3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。 (4)如果不是数字,该字符则是运算符,此时需比较优先关系。 做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将此运算符栈顶的运算符从栈中弹出,将该字符入栈。 (5)重复上述操作(1)-(2)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。 四、程序代码: //这是一个由中缀式生成后缀式的程序 #include<> #include<> #include<> #include<> #define maxbuffer 64 void main() { char display_out(char out_ch[maxbuffer], char ch[32]); //int caculate_array(char out_ch[32]); static int i=0; static int j=0; char ch[maxbuffer],s[maxbuffer],out[maxbuffer]; cout<<"请输入中缀表达式: ";

编译原理实验报告实验一编写词法分析程序

编译原理实验报告实验名称:实验一编写词法分析程序 实验类型:验证型实验 指导教师:何中胜 专业班级:13软件四 姓名:丁越 学号: 电子邮箱: 实验地点:秋白楼B720 实验成绩: 日期:2016年3 月18 日

一、实验目的 通过设计、调试词法分析程序,实现从源程序中分出各种单词的方法;熟悉词法分析 程序所用的工具自动机,进一步理解自动机理论。掌握文法转换成自动机的技术及有穷自动机实现的方法。确定词法分析器的输出形式及标识符与关键字的区分方法。加深对课堂教学的理解;提高词法分析方法的实践能力。通过本实验,应达到以下目标: 1、掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示文件的方法。 2、掌握词法分析的实现方法。 3、上机调试编出的词法分析程序。 二、实验过程 以编写PASCAL子集的词法分析程序为例 1.理论部分 (1)主程序设计考虑 主程序的说明部分为各种表格和变量安排空间。 数组 k为关键字表,每个数组元素存放一个关键字。采用定长的方式,较短的关键字 后面补空格。 P数组存放分界符。为了简单起见,分界符、算术运算符和关系运算符都放在 p表中 (编程时,还应建立算术运算符表和关系运算符表,并且各有类号),合并成一类。 id和ci数组分别存放标识符和常数。 instring数组为输入源程序的单词缓存。 outtoken记录为输出内部表示缓存。 还有一些为造表填表设置的变量。 主程序开始后,先以人工方式输入关键字,造 k表;再输入分界符等造p表。 主程序的工作部分设计成便于调试的循环结构。每个循环处理一个单词;接收键盘上 送来的一个单词;调用词法分析过程;输出每个单词的内部码。 ⑵词法分析过程考虑 将词法分析程序设计成独立一遍扫描源程序的结构。其流程图见图1-1。 图1-1 该过程取名为 lexical,它根据输入单词的第一个字符(有时还需读第二个字符),判断单词类,产生类号:以字符 k表示关键字;i表示标识符;c表示常数;p表示分界符;s表示运算符(编程时类号分别为 1,2,3,4,5)。 对于标识符和常数,需分别与标识符表和常数表中已登记的元素相比较,如表中已有 该元素,则记录其在表中的位置,如未出现过,将标识符按顺序填入数组id中,将常数 变为二进制形式存入数组中 ci中,并记录其在表中的位置。 lexical过程中嵌有两个小过程:一个名为getchar,其功能为从instring中按顺序取出一个字符,并将其指针pint加1;另一个名为error,当出现错误时,调用这个过程, 输出错误编号。 2.实践部分

编译原理实验报告《LL(1)语法分析器构造》

《LL(1)分析器的构造》实验报告 一、实验名称 LL(1)分析器的构造 二、实验目的 设计、编制、调试一个LL(1)语法分析器,利用语法分析器对符号串的识别,加深对语法分析原理的理解。 三、实验内容和要求 设计并实现一个LL(1)语法分析器,实现对算术文法: G[E]:E->E+T|T T->T*F|F F->(E)|i 所定义的符号串进行识别,例如符号串i+i*i为文法所定义的句子,符号串ii+++*i+不是文法所定义的句子。 实验要求: 1、检测左递归,如果有则进行消除; 2、求解FIRST集和FOLLOW集; 3、构建LL(1)分析表; 4、构建LL分析程序,对于用户输入的句子,能够利用所构造的分析程序进行分析,并显示出分析过程。 四、主要仪器设备 硬件:微型计算机。 软件: Code blocks(也可以是其它集成开发环境)。 五、实验过程描述 1、程序主要框架 程序中编写了以下函数,各个函数实现的作用如下: void input_grammer(string *G);//输入文法G

//将文法G预处理得到产生式集合P,非终结符、终结符集合U、u, int eliminate_1(string *G,string *P,string U,string *GG);//消除文法G中所有直接左递归得到文法GG int* ifempty(string* P,string U,int k,int n);//判断各非终结符是否能推导为空 string* FIRST_X(string* P,string U,string u,int* empty,int k,int n);求所有非终结符的FIRST集 string FIRST(string U,string u,string* first,string s);//求符号串s=X1X2...Xn的FIRST集 string** create_table(string *P,string U,string u,int n,int t,int k,string* first);//构造分析表 void analyse(string **table,string U,string u,int t,string s);//分析符号串s 2、编写的源程序 #include #include #include using namespace std; void input_grammer(string *G)//输入文法G,n个非终结符 { int i=0;//计数 char ch='y'; while(ch=='y'){ cin>>G[i++]; cout<<"继续输入?(y/n)\n"; cin>>ch; } } void preprocess(string *G,string *P,string &U,string &u,int &n,int &t,int &k)//将文法G预处理产生式集合P,非终结符、终结符集合U、u, { int i,j,r,temp;//计数 char C;//记录规则中()后的符号 int flag;//检测到() n=t=k=0; for( i=0;i<50;i++) P[i]=" ";//字符串如果不初始化,在使用P[i][j]=a时将不能改变,可以用P[i].append(1,a) U=u=" ";//字符串如果不初始化,无法使用U[i]=a赋值,可以用U.append(1,a) for(n=0;!G[n].empty();n++) { U[n]=G[n][0]; }//非终结符集合,n为非终结符个数 for(i=0;i

《编译原理实验》

《编译原理实验》 —LR分析器 院、系(部) 计算机科学与技术学院 专业及班级计算机科学与技术专业1403班 学号1408030322 姓名朱浩 日期2017年5月29日

一、实验目的与任务 设计一个非递归预测分析器,实现对表达式语言的分析,理解自上而下语法分析方法的基本思想,掌握设计非递归预测分析器的基本方法。 二、实验要求 建立文法及其LL(1)分析表表示的数据结构,设计并实现相应的预测分析器,对源程序经词法分析后生成的二元式代码流进行预测分析,如果输入串是文法定义的句子则输出“是”,否则输出“否”。 三、文法描述及其LL(1)分析表 表达式语言(XL) 的语法规则如下: 1.程序→ 表达式; 2.|表达式;程序 3.表达式→ 表达式+ 项 4.|项 5.项→ 项* 因式 6.|因式 7.因式→ num_or_id 8.|(表达式) 将该语言的文法转换为如下的LL(1)文法: 1prgm → expr;prgm’ 8 term → factor term’ 2prgm’ → prgm 9 term’ → *factor term’ 3prgm’ →ε 10 term’ →ε 4expr → term expr’ 11 factor → (expr) 5expr →ε 12 factor → num 6expr’ → +term expr’ 13 system_goal → prgm 7expr’ →ε

四、文法及其LL(1)分析表的数据结构 文法的产生式可用数组Yy_pushtab[]存放。数组的第一个下标是产生式号,第一个产生式的序号为0;每列按逆序存放该产生式右部各符号的常数值,并以0结束。对于该表达式语言XL的LL(1)分析表,可用数组Yy_d[]存放。第一个下标是非终结符数值,第二个下标是终结符数值,数组元素的值为:0(表示接受) ,1(表示产生式号) ,-1(表示语法错) 。 数组Yy_d[]的具体内容及表示如下: 0 1 2 3 4 5 6 prgm 256 prgm’ 257 expr 258 term 259 expr’ 260 factor 261 term’ 262 system_goal 263 数组Yy_pushtab[]的具体内容及表示如下:

编译原理实验报告

院系:计算机科学学院 专业、年级: 07计科2大班 课程名称:编译原理 学号姓名: 指导教师: 2010 年11月17 日 组员学号姓名

实验 名称 实验一:词法分析实验室9205 实验目的或要求 通过设计一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。 具体要求:输入为某语言源代码,达到以下功能: 程序输入/输出示例:如源程序为C语言。输入如下一段: main() { int a,b; a=10; b=a+20; } 要求输出如下(并以文件形式输出或以界面的形式输出以下结果)。 (2,”main”) (5,”(“) (5,”)“) (5,”{“} (1,”int”) (2,”a”) (5,”,”) (2,”b”) (5,”;”) (2,”a”) (4,”=”) (3,”10”) (5,”;”) (2,”b”) (4,”=”) (2,”a”) (4,”+”) (3,”20”) (5,”;”) (5,”}“) 要求: 识别保留字:if、int、for、while、do、return、break、continue等等,单词种别码为1。 其他的标识符,单词种别码为2。常数为无符号数,单词种别码为3。 运算符包括:+、-、*、/、=、>、<等;可以考虑更复杂情况>=、<=、!= ;单词种别码为4。分隔符包括:“,”“;”“(”“)”“{”“}”等等,单词种别码为5。

编译原理实验二

编译原理二 -------词法分析器一.问题描述 词法分析程序的功能: 输入源程序,输出单词符号,如图所示: 单词符号 处理过程:在扫描源程序字符串时,一旦识别出关键字、分隔符、标识符、无符号常数中之一,即以单词形式(各类单词均采用相同的结构,即二元式编码形式)输出。每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直至整个源程序全部扫描完毕,并形成相应的单词串形式的源程序。 二.需求分析 1.对给定的程序通过词法分析器能够识别一个个单词符号,并以二元式(单词类型,单词符号)显示; 2.可以将要分析的程序保存到文件中进行读取; 3.删除无用的空白字符、回车符、及其它非实质性符号。 三.程序设计 本程序规定: (1)关键字"begin","end","if","then","else","while","write","read", "do", "call","const","char","until","procedure","repeat"

(2)运算符:"+","-","*","/","=" (3)界符:"{","}","[","]",";",",",".","(",")",":" (4)其他标记如字符串,表示以字母开头的标识符。 (5)空格、回车、换行符跳过。 对于一段可能的输入代码,其结果在屏幕上显示如下: ( 1 , 无符号整数) ( begin , 关键字) ( if , 关键字) ( +, 运算符) ( ;, 界符) ( a , 普通标识符) 关键字或标识符的判断:读入一串字符,将ASCII码在字母范围的字符存入数组中,将该数组与设置好的关键字比较,如果相等则输出是关键字,否则继续读入直至下一字符既非数字也非字母,输出为标识符; 数字的判断:若跟在字母后面则一起输出为标识符,否则输出为数字; 界符、运算符的判断:直接判断其ASCII码 运行过程为: 1.预处理:把源文件一个字符一个字符的读入词法分析程序设置的输入字符结构体数组中(输入缓冲区),读入过程要删除多余的空格; 2.源程序字符数组中获得单词, 编码为二元式.:二元式采用结构体数组存储, 把单词类型和词元记录下来。

编译原理实验报告一

实验一词法分析程序实现 一、实验目得与要求 通过编写与调试一个词法分析程序,掌握在对程序设计语言得源程序进行扫描得过程中,将字符流形式得源程序转化为一个由各类单词符号组成得流得词法分析方法 二、实验内容 基本实验题目:若某一程序设计语言中得单词包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符与四个算术运算符,试构造能识别这些单词得词法分析程序(各类单词得分类码参见表I)。 表I语言中得各类单词符号及其分类码表 输入:由符合与不符合所规定得单词类别结构得各类单词组成得源程序文件。 输出:把所识别出得每一单词均按形如(CLASS,VALUE)得二元式形式输出,并将结果放到某个文件中。对于标识符与无符号常数,CLASS字段为相应得类别码得助记符;V AL UE字段则就是该标识符、常数得具体值;对于关键字与运算符,采用一词一类得编码形式,仅需在二元式得CLASS字段上放置相应单词得类别码得助记符,V ALUE字段则为“空". 三、实现方法与环境 词法分析就是编译程序得第一个处理阶段,可以通过两种途径来构造词法分析程序.其一就是根据对语言中各类单词得某种描述或定义(如BNF),用手工得方式(例如可用C语言)构造词法分析程序。一般地,可以根据文法或状态转换图构造相应得状态矩阵,该状态矩阵连同控制程序一起便组成了编译器得词法分析程序;也可以根据文法或状态转换图直接编写词法分析程序。构造词法分析程序得另外一种途径就是所谓得词法分析程序得自动生成,即首先用正规式对语言中得各类单词符号进行词型描述,并分别指出在识别单词时,词法分析程

《编译原理》实验指导书

《编译原理》实验指导书 实验目的和内容 编译原理实验的目的是使学生将编译理论运用到实际当中,实现一个简单语言集的词法、语法和语义分析程序,验证实际编译系统的实现方法,并加深对编译技术的认识。 实验内容共需实现编译器的词法、语法和语义分析程序三个组成部分。要求学生必须完成每个实验的基本题目要求,有余力的同学可尝试实验的扩展要求部分。 实验报告 要求每人针对所完成的实验内容上交一份实验报告,其中主要包括三方面内容:1、实验设计:实验采用的实现方法和依据(如描述语言的文法及其机内表示,词分析 的单词分类码表、状态转换图或状态矩阵等,语法分析中用到的分析表或优先矩阵等,语法制导翻译中文法的拆分和语义动作的设计编写等);具体的设计结果(应包括整体设计思想和实现算法,程序结构的描述,各部分主要功能的说明,法以及所用数据结构的介绍等)。 2、程序代码:实验实现的源程序清单,要求符合一般的程序书写风格,有详细的注释。 3、实验结果分析:自行编写若干源程序作为测试用例,对所生成的编译程序进行测试 (编译程序的输入与输出以文件的形式给出);运行结果分析(至少包括一个正确和一个错误单词或语句的运行结果);以及改进设想等。 注意事项 1、电子版实验报告和源程序在最后一次机时后的一周内上交。(每个同学上交一个压 缩文件,其命名格式为“学号_姓名.rar”,内含实验报告和一个命名为“源程序” 的文件夹。注意提交的源程序应是经过调试、测试成功的较为通用的程序,并应有相应的注释、运行环境和使用方法简介。) 2、不接受不完整的实验报告和没有说明注释的源程序,或者说明与程序、运行结果不 符合的作业。 特别鼓励:扩展题目 1、为亲身经历一个小型编译器的开发全过程,触摸一下与实际编译器开发相关的工作, 大家可以自由组成3人左右的小组,推举组长,模拟一个团队分工协作开发大型软件的实战环境,融入软件工程的思想规范和一般理论方法,初步体验从系统分析设计、编码测试到交付维护的一个完整编译器软件的开发过程。要求组长为每个小组成员分配主要负责的任务,完成相应的分析设计员、程序员和测试员等角色的工作,并以小组为单位提交一份实验报告和源程序,在报告封面上写明每个同学主要完成和负责的部分。 2、以组为单位完成的实验内容至少必须整合词法、语法和语义三个部分的实验,对于 选定的适当规模的文法(如C语言的一个大小适宜的子集),进行系统的总体设计、功能分析、编码测试等工作。完成一个从对源程序的词法分析开始,到中间代码生成的完整的编译器前端的开发,使所涉及到的编译系统的各个组成模块有机地衔接在一起,提交一份完整的实验报告和源程序,并将以下几个方面描述清楚:

编译原理实验指导书2010

《编译原理》课程实验指导书 课程编号: 课程名称:编译原理/Compiler Principles 实验总学时数: 8 适用专业:计算机科学与技术、软件工程 承担实验室:计算机学院计算机科学系中心实验室、计算机技术系中心实验室 一、实验教学的目的与要求 上机实习是对学生的一种全面综合训练,是与课堂听讲、自学和练习相辅相成的必不可少的一个教学环节。通常,实习题中的问题比平时的练习题要复杂,也更接近实际。编译原理这门课程安排的2次上机实验都属于一种设计类型的实验,每个实验的训练重点在于基本的编译技术和方法,而不强调面面俱到;实验的目的是旨在使学生进一步巩固课堂上所学的理论知识,深化理解和灵活掌握教学内容;培养学生编制算法的能力和编程解决实际问题的动手能力。 要求学生在上机前应认真做好各种准备工作,熟悉机器的操作系统和语言的集成环境,独立完成算法设计和程序代码的编写;上机时应随带有关的编译原理教材或参考书;要学会程序调试与纠错。 每次实验后要交实验报告,实验报告的内容应包括: (1)实验题目、班级、学号、姓名、完成日期; (2)简要的需求分析与概要设计; (3)详细的算法描述; (4)源程序清单; (5)给出软件的测试方法和测试结果; (6)实验的评价、收获与体会。 开发工具: (1)DOS环境下使用Turbo C; (2)Windows环境下使用Visual C++ 。 考核: 实验成绩占编译原理课程结业成绩的10%。 三、单项实验的内容和要求: 要求每个实验保证每个学生一台微机。 实验一(4学时):单词的词法分析程序设计。 (一)目的与要求 1.目的 通过设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。

编译原理实验题目及报告要求

编译原理上机实验试题 一、实验目的 通过本实验使学生进一步熟悉和掌握程序设计语言的词法分析程序的设计原理及相关的设计技术, 如何针对确定的有限状态自动机进行编程序;熟悉和 掌握程序设计语言的语法分析程序的设计原理、熟悉 和掌握算符优先分析方法。 二、实验要求 本实验要求:①要求能熟练使用程序设计语言编程;②在上机之前要有详细的设计报告(预习报告); ③要编写出完成相应任务的程序并在计算机上准确 地运行;④实验结束后要写出上机实验报告。 三、实验题目 针对下面文法G(S): S→v = E E→E+E│E-E│E*E│E/E│(E)│v │i 其中,v为标识符,i为整型或实型数。要求完成 ①使用自动机技术实现一个词法分析程序; ②使用算符优先分析方法实现其语法分析程序,在 语法分析过程中同时完成常量表达式的计算。

1、题目(见“编译原理---实验题目.doc,“实验题目”中的第一项) 2、目的与要求(见“编译原理---实验题目.doc”) 3、设计原理: (1)单词分类:标识符,保留字,常数,运算符,分隔符等等 (2)单词类型编码 (3)自动机 4、程序流程框图 5、函数原型(参数,返回值) 6、关键代码(可打印,只打印关键代码) 7、调试: (1)调试过程中遇到的错误,如何改进的; (2)需要准备测试用例(至少3个,包含输入和输出)——(可打印) 8、思考: (1)你编写的程序有哪些要求是没有完成的,你觉得该采用什么方法去完成; (2)或者是你觉得程序有哪些地方可以进一步完善,简述你的完善方案。

1、题目(见“编译原理---实验题目.doc,“实验题目”中的第二项) 2、目的与要求(见“编译原理---实验题目.doc”) 3、设计原理:构造出算法优先关系表 4、程序流程框图 5、函数原型(参数,返回值) 6、关键代码(可打印,只打印关键代码) 7、调试: (1)调试过程中遇到的错误,如何改进的; (2)需要准备测试用例(至少3个,包含输入和输出)——(可打印) 8、思考: (1)你编写的程序有哪些要求是没有完成的,你觉得该采用什么方法去完成; (2)或者是你觉得程序有哪些地方可以进一步完善,简述你的完善方案。

编译原理实验1

大学学生实验报告 开课学院及实验室:年月日 实验目的 设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。 针对表达各类词语的一组正规表达式,设计一个确定化的最简的有限自动机,对输入的符号串进行单词划分及词类识别。 实验容 将词法分析器分解为以下几个部分: 1.正规表达式的解析:将正规表达式中的符号分解为常量字符、正规表达 式标识符和正规表达式运算符,然后基于正规表达式运算将正规表达式 分解为更小的正规表达式(通过正规表达式运算符进行串接)。 2.正规表达式到NFA的转换:根据转换规则,基于正规表达式运算,将正 规表达式转换为非确定有限自动机,并确定各类词的终止状态。

3.NFA的确定化:通过计算各状态的传递闭包,将NFA确定化,并确定 各类词的终止状态。 4.最小化:通过子集法,求得最简的确定有限自动机,并确定各类词的终 止状态。 例如:分析C语言子集的词法 1)关键字 main if else int return void while (都是小写)2)专用符号 = + —* / < <= < >= = = != ;:,{ } [ ] ( ) 3)其他模式(正规表达式) STRING::=" [^"]* ID::=letter(letter|digit)* INT::=digit digit* letter::= a|…|z|A|…|Z digit::= 0|…|9 4)空格由空白、制表符和换行符组成 空格一般用来分隔ID、NUM、专用符号和关键字,词法分析阶段通常被忽略。 部分单词符号对应的种别码

词法分析程序的功能 输入:所给文法的源程序字符串 输出:二元组(syn, token或sum)构成的序列。其中syn 为单词种别码;token 为存放的单词自身字符串;sum为整型常量(作为常量的值)。实现时,可将单词的二元组用结构进行处理 代码: #include #include

编译原理实验报告

《编译原理》实验报告软件131 陈万全132852

一、需求分析 通过对一个常用高级程序设计语言的简单语言子集编译系统中词法分析、语法分析、语义处理模块的设计、开发,掌握实际编译系统的核心结构、工作流程及其实现技术,获得分析、设计、实现编译程序等方面的实际操作能力,增强设计、编写和调试程序的能力。 通过开源编译器分析、编译过程可视化等扩展实验,促进学生增强复杂系统分析、设计和实现能力,鼓励学生创新意识和能力。 1、词法分析程序设计与实现 假定一种高级程序设计语言中的单词主要包括五个关键字begin、end、if、then、else;标识符;无符号常数;六种关系运算符;一个赋值符和四个算术运算符,试构造能识别这些单词的词法分析程序。 输入:由符合和不符合所规定的单词类别结构的各类单词组成的源程序文件。 输出:把所识别出的每一单词均按形如(CLASS,VALUE)的二元式形式输出,并将结果放到某个文件中。对于标识符和无符号常数,CLASS字段为相应的类别码的助记符;VALUE字段则是该标识符、常数的具体值;对于关键字和运算符,采用一词一类的编码形式,仅需在二元式的CLASS字段上放置相应单词的类别码的助记符,VALUE字段则为“空”。 2、语法分析程序设计与实现 选择对各种常见高级程序设计语言都较为通用的语法结构——算术表达式的

一个简化子集——作为分析对象,根据如下描述其语法结构的BNF定义G2[<算术表达式>],任选一种学过的语法分析方法,针对运算对象为无符号常数和变量的四则运算,设计并实现一个语法分析程序。 G2[<算术表达式>]: <算术表达式>→<项> | <算术表达式>+<项> | <算术表达式>-<项> <项>→<因式>|<项>*<因式>|<项>/<因式> <因式>→<运算对象> | (<算术表达式>) 若将语法范畴<算术表达式>、<项>、<因式>和<运算对象>分别用E、T、F和i 代表,则G2可写成: G2[E]:E → T | E+T | E-T T → F | T*F | T/F F → i | (E) 输入:由实验一输出的单词串,例如:UCON,PL,UCON,MU,ID······输出:若输入源程序中的符号串是给定文法的句子,则输出“RIGHT”,并且给出每一步分析过程;若不是句子,即输入串有错误,则输出“ERROR”,并且显示分析至此所得的中间结果,如分析栈、符号栈中的信息等,以及必要的出错说明信息。 3、语义分析程序设计与实现 对文法G2[<算术表达式>]中的产生式添加语义处理子程序,完成运算对象是简单变量(标识符)和无符号数的四则运算的计值处理,将输入的四则运算转换为四元式形式的中间代码。 输入:包含测试用例(由标识符、无符号数和+、?、*、/、(、)构成的算术表达式)的源程序文件。 输出:将源程序转换为中间代码形式表示,并将中间代码序列输出到文件中。 若源程序中有错误,应指出错误信息 二、设计思路 1、词法分析程序设计与实现 1)单词分类 为了编程的实现。我们假定要编译的语言中,全部关键字都是保留字,程序员不得将它们作为源程序中的标识符;作了这些限制以后,就可以把关键字和标识符的识别统一进行处理。即每当开始识别一个单词时,若扫视到的第一个字符为字母,则把后续输入的字母或数字字符依次进行拼接,直至扫视到非字母、数字字符为止,以期获得一个尽可能长的字母数字字符串,然后以此字符串查所谓保留字表(此保留字表要事先造好),若查到此字符串,则取出相应的类别码;反之,则表明该字符串应为一标识符。

编译原理实验-词法分析器的设计说明

集美大学计算机工程学院实验报告 课程名称:编译原理班级: 指导教师:: 实验项目编号:实验一学号: 实验项目名称:词法分析器的设计实验成绩: 一、实验目的 通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。 二、实验容 编写一个词法分析器,从输入的源程序(编写的语言为C语言的一个子集)中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续显示) 三、实验要求 1、词法分析器的功能和输出格式 词法分析器的功能是输入源程序,输出单词符号。词法分析器的单词符 2 别单词的类型,将标识符和常量分别插入到相应的符号表中,增加错误处理等。 3、编程语言不限。

四、实验设计方案 1、数据字典 本实验用到的数据字典如下表所示:

3、实验程序 #include #include #include #include //判断读入的字符是否为字母 bool isLetter(char c){ if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){ return true; } else return false; } //判断读入的字符是否为数字 bool isDigit(char c){ if(c >='0' && c <= '9'){ return true; } else return false; } //判断是否为关键字 bool isKey(char *string) { if(!strcmp(string,"void") || !strcmp(string,"if")|| !strcmp(string,"for")|| !strcmp(string,"wh ile") || !strcmp(string,"do")|| !strcmp(string,"return")|| !strcmp(stri ng,"break") || !strcmp(string,"main")|| !strcmp(string,"int")|| !strcmp(strin g,"float")|| !strcmp(string,"char") || !strcmp(string,"double")|| !strcmp(string,"String"))

编译原理实验报告(词法分析器语法分析器)

编译原理实验报告

实验一 一、实验名称:词法分析器的设计 二、实验目的:1,词法分析器能够识别简单语言的单词符号 2,识别出并输出简单语言的基本字.标示符.无符号整数.运算符.和界符。 三、实验要求:给出一个简单语言单词符号的种别编码词法分析器 四、实验原理: 1、词法分析程序的算法思想 算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。 2、程序流程图 (1 (2)扫描子程序

3

五、实验内容: 1、实验分析 编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符。字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。 2 实验词法分析器源程序: #include #include #include int i,j,k; char c,s,a[20],token[20]={'0'}; int letter(char s){ if((s>=97)&&(s<=122)) return(1); else return(0); } int digit(char s){ if((s>=48)&&(s<=57)) return(1); else return(0); } void get(){ s=a[i]; i=i+1; } void retract(){ i=i-1; } int lookup(char token[20]){ if(strcmp(token,"while")==0) return(1); else if(strcmp(token,"if")==0) return(2); else if(strcmp(token,"else")==0) return(3); else if(strcmp(token,"switch")==0) return(4); else if(strcmp(token,"case")==0) return(5); else return(0); } void main() { printf("please input string :\n"); i=0; do{i=i+1; scanf("%c",&a[i]);

相关主题
文本预览
相关文档 最新文档