《合肥工業(yè)大學(xué)編譯原理實(shí)驗(yàn)》由會(huì)員分享,可在線閱讀,更多相關(guān)《合肥工業(yè)大學(xué)編譯原理實(shí)驗(yàn)(28頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
宣城校區(qū)
實(shí) 驗(yàn) 報(bào) 告
課 程 名 稱 編譯原理
專 業(yè) 班 級(jí) 計(jì)算機(jī)0001班
學(xué)生姓名及學(xué)號(hào) 趙保飛 2015216768
指 導(dǎo) 教 師 李芒宏
實(shí) 驗(yàn) 地 點(diǎn) 計(jì)算機(jī)中心樓第四機(jī)房
2017 ~ 2018 學(xué)年第 一 學(xué)期
《編譯原理》課程實(shí)驗(yàn)報(bào)告
實(shí)驗(yàn)名稱
詞法分析設(shè)計(jì)
姓 名
趙保飛
系院專業(yè)
計(jì)算機(jī)科學(xué)與技術(shù)
班級(jí)
計(jì)算機(jī)01班
學(xué)號(hào)
2015216768
實(shí)驗(yàn)日期
2017.10.18
指導(dǎo)教師
李芒宏
成績
一、實(shí)驗(yàn)?zāi)康暮鸵?
通過本實(shí)驗(yàn)的編程實(shí)踐,使學(xué)生了解詞法分析的任務(wù),掌握詞法分析程序設(shè)
計(jì)的原理和構(gòu)造方法,使學(xué)生對編譯的基本概念、原理和方法有完整的和清楚的
理解,并能正確地、熟練地運(yùn)用。
二、實(shí)驗(yàn)原理
(1)實(shí)驗(yàn)數(shù)據(jù)結(jié)構(gòu)說明
K[]String數(shù)組-關(guān)鍵字表;s[]char數(shù)組—分界符;m[]char數(shù)組—算術(shù)運(yùn)算符;r[]String數(shù)組—關(guān)系運(yùn)算符;ArrayList型String數(shù)組ci—常數(shù);ArrayList型String數(shù)組id—標(biāo)識(shí)符
(2)實(shí)驗(yàn)算法描述
(3)算法流程圖
三、源程序代碼和測試結(jié)果
package lexicalAnalysis;
import java.util.*;
import java.io.*;
public class lexicalAnalysis {
static String k[]={"for","main","if","while","void","public","static","printf","scanf","asm","do","return","typedef","auto","double","break","short","using","default","long"};//關(guān)鍵字
static char s[]={,,;,(,),[,],{,}};//2分界符
static char m[]={+,-,*,/};//3算術(shù)運(yùn)算符
static String r[]={"<","<=","=",">",">=","<>"};//4關(guān)系運(yùn)算符
ArrayList
ci=new ArrayList();//5常數(shù)
ArrayList id=new ArrayList();//6標(biāo)識(shí)符
String tempToken="";//臨時(shí)存放組成一個(gè)“詞”單位串
int pint ,row = 1,line = 1;//當(dāng)前指針指示,行數(shù),列數(shù)
char ch;//存放最新讀入源程序字符
String instring;//存放輸入de源程序代碼
public static void main(String[] args)throws Exception{
// TODO Auto-generated method stub
lexicalAnalysis one = new lexicalAnalysis();
System.out.println("單詞"+"\t二元序列"+"\t類 型"+"\t位置(行,列)");
one.readtext();
}
boolean isdigit(char c){//判斷所讀字符是否為數(shù)字,是則返回ture,否則返回false
if(c>=48 && c<=57 )
return true;
else
return false;
}
boolean isletter(char c){//判斷所讀字符是否為字母,是則返回true,否則返回false
if((c>64&&c<91)||(c>96&&c<123))
return true;
else
return false;
}
boolean isline(char c){//判斷字符c是否是下劃線"_"
if(c==_)
return true;
else
return false;
}
boolean remove(){//用于在判斷關(guān)系運(yùn)算符時(shí),判斷是否是要再讀一個(gè)字符
char b=instring.charAt(pint+1);//string類charAt() 方法用于返回指定索引處的字符。索引范圍為從 0 到 length()-1
if(b===||b==>)//當(dāng)其后的字符是=或>時(shí),要再讀一個(gè)字符。否則不要再讀。
return true;
else
return false;
}
void clearBlank(){//檢查空白直到讀入字符非空白
while(ch== ){
getchar();
}
}
void getchar(){
pint++;
if(pint <= instring.length()-1){
ch=instring.charAt(pint);
if(ch == \n){
change_row_line();
getchar();
}
}
else
ch= ;//instring數(shù)據(jù)讀取完,需重新讀入
}
void retract(){//讀入前一個(gè)字符
pint--;
ch=instring.charAt(pint);
}
void distinguishLeter(){//識(shí)別字符串
tempToken="";//清空
while(isletter(ch) || isdigit(ch) || isline(ch)){//字母,數(shù)字,下劃線仍是字符串合法組成,繼續(xù)識(shí)別
tempToken=tempToken + ch;
getchar();
}
}
void distinguishDigit(){//識(shí)別數(shù)字串
tempToken="";//先將strtoken置空
while(isdigit(ch)){//當(dāng)數(shù)字時(shí)繼續(xù)識(shí)別數(shù)字串
tempToken=tempToken+ch;//將新識(shí)別的字符加到strtoken后
getchar();
}
if(isletter(ch)||isline(ch)){//識(shí)別完數(shù)字串而其后是字母,下劃線時(shí)出錯(cuò)處理
while(isletter(ch)||isline(ch)||isdigit(ch)){//當(dāng)是字母,數(shù)字,下劃線時(shí)繼續(xù)識(shí)別錯(cuò)誤數(shù)字串
tempToken=tempToken+ch;//將新識(shí)別的字符加到strtoken后
getchar();
}
display(0,tempToken, );//輸出錯(cuò)誤數(shù)字串
tempToken="";//將strtoken置空返回
}
}
void display(int i,String s,char a){//各種輸出處理
switch(i){
case -1:System.out.println(a+"\tError"+"\tError"+"\t"+row+","+line+")");
break;
case 0:System.out.println(s+"\tError"+"\tError"+"\t("+row+","+line+")");
break;
case 1:System.out.println(s+"\t(1,"+s+")"+"\t關(guān)鍵字 "+"\t("+row+","+line+")");
break;
case 2:System.out.println(a+"\t(2,"+a+")"+"\t分界符"+"\t("+row+","+line+")");
break;
case 3:System.out.println(a+"\t(3,"+a+")"+"\t算術(shù)運(yùn)算符"+"\t("+row+","+line+")");
break;
case 4:System.out.println(s+"\t(4,"+s+")"+"\t關(guān)系運(yùn)算符 "+"\t("+row+","+line+")");
break;
case 5:System.out.println(s+"\t(5,"+s+")"+"\t常數(shù)"+"\t"+"("+row+","+line+")");
break;
case 6:System.out.println(s+"\t(6,"+s+")"+"\t標(biāo)識(shí)符"+"\t("+row+","+line+")");
break;
}
line++;//列數(shù)加一
}
void change_row_line(){//改變行數(shù)和列數(shù)
row++;
line=1;
}
void handleString(){//輸入串處理
pint=-1;//將搜索指示器置-1
System.out.println("要處理的語句為 : "+instring);
getchar();//讀入一個(gè)字符
while(pintTG
(2)G->+TG|-TG
(3)G->ε
(4)T->FS
(5)S->*FS|/FS
(6)S->ε
(7)F->(E)
(8)F->i
(1)實(shí)驗(yàn)數(shù)據(jù)結(jié)構(gòu)說明
Char數(shù)組-Vn數(shù)組--非終結(jié)符表;char數(shù)組-Vt數(shù)組--終結(jié)符;String數(shù)組-Gr數(shù)組--文法;
Boolean型FIRST[][]二維數(shù)組對應(yīng)每個(gè)非終結(jié)符的first集,初始化均為false;
Boolean型FOLLOW[][]二維數(shù)組對應(yīng)每個(gè)非終結(jié)符的Follow集,初始化均為false;
String型M[][]二維數(shù)組對應(yīng)預(yù)測分析表
(2)實(shí)驗(yàn)算法描述
算法總的來講不是很復(fù)雜,但是細(xì)節(jié)上可能有點(diǎn)復(fù)雜??偟氖且罁?jù)本實(shí)驗(yàn)的數(shù)據(jù)結(jié)構(gòu)FIRST[][]和FOLLOW[][]集,這兩個(gè)數(shù)據(jù)結(jié)構(gòu)雖然浪費(fèi)了不少空間但是確實(shí)讓程序的實(shí)現(xiàn)變得更簡單。
First()總的來求所有的非終結(jié)符的first集,first1()分工為具體求某一個(gè)具體非終結(jié)符的first集;first2()則是求某一個(gè)集體的產(chǎn)生式的first集。通過這三個(gè)函數(shù)的逐級(jí)分工來實(shí)現(xiàn)求所有的非終結(jié)符的first集。Follow集來說相對難求一點(diǎn),但把它放到first集后面求來說相對簡單一點(diǎn)。通過上面的分布設(shè)計(jì)就可以實(shí)現(xiàn)了。
(3)算法流程圖
三、源程序代碼和測試結(jié)果
package exp3;
import javax.swing.*;
import java.awt.*;
import java.awt.GridLayout.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class WinGrid extends JFrame{
GridLayout grid ;
JPanel chessboard;
JTextField text;
JTextArea textShow;
JButton button;
ReaderListen listener;
WinGrid(){
init();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
void init() {
setLayout(new FlowLayout());
text = new JTextField(10);
setBounds(466,166,500,400);
button = new JButton("讀取");
textShow = new JTextArea(9,30);
listener = new ReaderListen();
listener.setJTextField(text);
listener.setJTextArea(textShow);
text.addActionListener(listener);
button.addActionListener(listener);
add(text);
add(button);
add(new JScrollPane(textShow));
}
}
class ReaderListen implements ActionListener {
JTextField text;
JTextArea textShow;
LL one=new LL();
String s;
String temp1[][]= new String[18][6];
public void setJTextField(JTextField text) {
this.text = text;
}
public void setJTextArea(JTextArea textShow) {
this.textShow = textShow;
}
public String S(){
String t = text.getText();
return t;
}
@Override
public void actionPerformed(ActionEvent e) {
try {
String s = text.getText()+"#";
textShow.append(s+"\n");
textShow.append("步驟"+"\t"+"分析棧"+"\t"+"剩余輸入串"+"\t"+"所用產(chǎn)生式"+"\t"+"動(dòng)作"+"\n");
one.right(s,temp1);
for(int i = 0;i<18;i++){
for(int k=0;k<5;k++){
textShow.append(temp1[i][k]+"\t");
}
textShow.append("\n");
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
public class exp3 {
public static void main(String[] args) {
// TODO Auto-generated method stub
new WinGrid();
}
}
package exp3;
import java.util.*;
import java.io.*;
public class LL {
char Vn[]={E,T,G,F,S};//非終結(jié)符
char Vt[]={+,-,*,/,(,),i,#,ε};//終結(jié)符
boolean FIRST[][]=new boolean[Vn.length][Vt.length+1];//bool型數(shù)組,初始化均為flase
boolean FOLLOW[][]=new boolean[Vn.length][Vt.length+1];//bool型
String M[][]=new String[Vn.length][Vt.length-1];//預(yù)測分析表
String Gr[]={"E->TG","G->+TG|-TG","G->ε","T->FS","S->*FS|/FS","S->ε","F->(E)","F->i"};//文法
LL(){
first();//求first集
follow();//求follow集
buildM();//求預(yù)測分析表
}
int or(int i,String s){//返回該文法第i符號(hào)離他最近的在其右邊一個(gè)“|”位置
for(i=i+1;i temp=new Stack();//分析棧
String tempp[][] = t;//保存輸出臨時(shí)數(shù)組
String z;
temp.setSize(20);
temp.push(new Character(#));//初始化將#入棧
temp.push(new Character(E));//初始化將E入棧
char u,v;
int i=0,j,k=0;
String m,action="初始化",rule=" ";
while(i < s.length()){
tempp[k][0] = String.valueOf(k);//整數(shù)型變量賦值給字符串?dāng)?shù)組使用函數(shù)String.valueOF()
u=s.charAt(i);
String temp0_string ="";
for(j=0;j"+m;
if(!m.equals("ε")){//產(chǎn)生式m不是ε
action=action+",push(";
for(j=m.length()-1;j>-1;j--){//將產(chǎn)生式反序入棧
action=action+m.charAt(j);
temp.push(new Character(m.charAt(j)));
}
action=action+")";
}
}
else{//分析表中沒有產(chǎn)生式,提示錯(cuò)誤
rule=" ";
tempp[k+1][1] = "錯(cuò)誤";
//String O = String.valueOf(u);
//String P = String.valueOf(v);
String Q = u+"\t不在"+v+"對應(yīng)的分析表中";
tempp[k+1][2] = Q;
return ;
}
}
else{//棧頂元素為終結(jié)符時(shí)
rule="";
if(v==u){//棧頂元素與輸入符匹配
if(v==#){//棧頂元素為#時(shí),成功
tempp[k+1][1] = "成功";
return ;
}
else {
i++;
action="getnext(I)";
}
}
else{//棧頂元素與輸入符不匹配,提示錯(cuò)誤
tempp[k+1][1] = "錯(cuò)誤";
String Q = u+"\t不在"+v+"不等";
tempp[k+1][2] = Q;
return ;
}
}
k++;
}
return ;
}
}
四、實(shí)驗(yàn)評價(jià)、收獲與體會(huì)
從第一個(gè)實(shí)驗(yàn)越到第二個(gè)實(shí)驗(yàn),難度著實(shí)陡增,時(shí)間有非常短,匆匆忙忙的結(jié)果是現(xiàn)在這一份結(jié)果。試驗(yàn)中的FIRST集FOLLOW集的自動(dòng)化求是非常困難的,實(shí)現(xiàn)這一結(jié)果要密切結(jié)合初始的數(shù)據(jù)結(jié)構(gòu),所以一開始就要有系統(tǒng)的考慮,數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì)與后面的程序功能的實(shí)現(xiàn)有無幫助,最好是能簡化后面的功能實(shí)現(xiàn)。所以程序設(shè)計(jì)要先有一個(gè)總體布局,然后開動(dòng)才能事半功倍。
《編譯原理》課程實(shí)驗(yàn)報(bào)告
實(shí)驗(yàn)名稱
LR(1)分析表
姓 名
趙保飛
系院專業(yè)
計(jì)算機(jī)科學(xué)與技術(shù)
班級(jí)
計(jì)算機(jī)01班
學(xué)號(hào)
2015216768
實(shí)驗(yàn)日期
2017.11.1
指導(dǎo)教師
李芒宏
成績
一、實(shí)驗(yàn)?zāi)康暮鸵?
構(gòu)造 LR(1)分析程序,利用它進(jìn)行語法分析,判斷給出的符號(hào)串是否為該文
法識(shí)別的句子,了解 LR(K)分析方法是嚴(yán)格的從左向右掃描,和自底向上的
語法分析方法。
二、實(shí)驗(yàn)原理
文法:
(1 )E-> E+T
(2 )E->T
(3 )T-> T*F
(4 )T->F
(5 )F-> (E)
(6 )F-> i
(1)實(shí)驗(yàn)數(shù)據(jù)結(jié)構(gòu)說明
(2)實(shí)驗(yàn)算法描述
(1)總控程序,也可以稱為驅(qū)動(dòng)程序。對所有的 LR 分析器總控程序都是相同的。
(2)分析表或分析函數(shù),不同的文法分析表將不同,同一個(gè)文法采用的 LR 分析器
不同時(shí),分析表將不同,分析表又可以分為動(dòng)作表(ACTION)和狀態(tài)轉(zhuǎn)換(GOTO)
表兩個(gè)部分,它們都可用二維數(shù)組表示。
(3)分析棧,包括文法符號(hào)棧和相應(yīng)的狀態(tài)棧,它們均是先進(jìn)后出棧。
分析器的動(dòng)作就是由棧頂狀態(tài)和當(dāng)前輸入符號(hào)所決定。
(3)算法流程圖
三、源程序代碼和測試結(jié)果
#include "stdafx.h"
#include
#include
#pragma warning(disable:4996)//strcpy()函數(shù)
using namespace std;
typedef struct Ge//存儲(chǔ)文法
{
char sleft;//文法左部
char sright[4];//文法右部
}sentence;
typedef struct A
{
int move[6];//移進(jìn)
int change[6];//規(guī)約
}action_grid;
typedef struct G
{
char head[3];
int gt[3];
}goto_grid;
int status[20
鏈接地址:http://www.hcyjhs8.com/p-10248640.html