編譯原理實驗報告
Compilers Principles Experiment Report
所在學院:
所在班級:
學生姓名:
學
號:
指導教師:
教
務
處
2015 年 12 月
詞法分析程序
一、實驗目的:
設計、編制和調試一個具體的詞法分析程序,加深對詞法分析的理解。
二、實驗要求:
1、通過對 PL/0 詞法分析程序(GETSYS)的分析,編制一個具有以下功能的詞法分析程序:
a.輸入為字符串(或待進行詞法分析的源程序),輸出為單詞串,即由(單詞,類別)所組成的二元組序列;
b.有一定的錯誤檢查能力,例如能發現 2a這類
不能作為單詞的字符串。
三、實驗代 碼
#define ID 12//標識符
#define INT 13//常數
#define JF 14//界符
#define YSF 15//運算符
#define N 30//字符讀取的最大長度
char TOKEN[N];
FILE *write;
//查詢一個字符串,看其是否與指定的字符相匹配,如果匹配返回 1 個非零的值,如果不匹配,則返回一個 0 值*/
int looksame(char *a)
{
int i;
char*key[22] = { "begin","end","if","then","else","for","do","while","and","or","not","BEGIN","END","IF","THEN","ELSE","FOR","DO","WHILE","AND","OR","NOT" };
for (i = 0;i < 22;i++)
{
if (strcmp(key[i], a) == 0)//該字符串是否與關鍵字相匹配
return (i % 11 + 1);
}
return 0;
}
//把 a輸入到指定文件中,然后從該文件中讀出字符串,放到一個數組中輸出
void out(int a, char *b)
{
FILE *write;
write = fopen("E:\\b.txt", "a+");
if (write == NULL)
{
printf("文件打開失敗");
exit(0);
}
fprintf(write, "%d\t", a);
fwrite(b, strlen(b), 1, write);
fprintf(write, "\n");
fclose(write);
printf("%d %20s\t\t", a, b);
}
int error()
{
printf("書寫格式錯誤,未被識別\n");
return 0;
}
void function(FILE *fp)
{
char ch = " ";
int i, c;
while (ch != EOF)
{
ch = fgetc(fp);//從文件中讀取字符
while (ch == " " || ch == "\t" || ch == "\n") {
ch = fgetc(fp);
}
if (isalpha(ch)) //isalpha()判斷是否為英文字母,是則返回非
零值,否則返回零
{
TOKEN[0] = ch;
ch = fgetc(fp);
i = 1;
while (isalnum(ch))
//isalnum()判斷字符是否為英文字
母或數字,如果是則返回非零值,如果不是則返回零//
{
TOKEN[i] = ch;
i++;
ch = fgetc(fp);
}
TOKEN[i] = "\0";
fseek(fp, -1, 1);
//用于二進制方式打開的文件,移動文件讀寫指針位置
c = looksame(TOKEN);
if (c == 0)
{
out(ID, TOKEN);printf("標識符\n");
}
else
{
out(c, TOKEN);printf("關鍵字\n");
}
}
else if (isdigit(ch))
//isdigit()判斷是否為0-9 的數字
{
TOKEN[0] = ch;
ch = fgetc(fp);
i = 1;
while (isdigit(ch))
{
TOKEN[i] = ch;
i++;
ch = fgetc(fp);
}
TOKEN[i] = "\0";
fseek(fp, -1, 1);
out(INT, TOKEN);
printf("常數\n");
}
else
{
switch (ch)
{
case"+":out(YSF, "+");printf("運算符\n");
break;
case"-":out(YSF, "-");printf("運算符\n");
break;
case";":out(JF, ";");printf("界符\n");
break;
case",":out(JF, ",");printf("界符\n");
break;
case"|":out(YSF, "|");printf("運算符\n");
break;
case"{":out(JF, "{");printf("界符\n");
break;
case"(":out(JF, "(");printf("界符\n");
break;
case"!":out(JF, "!");printf("界符\n");
break;
case"^":out(JF, "^");printf("界符\n");
break;
case")":out(JF, ")");printf("界符\n");
break;
case"}":out(JF, "}");printf("界符\n");
break;
case"<":ch = fgetc(fp);
if (ch == "=")
{
out(YSF, "<=");
printf("運算符\n");
}
else if (ch == ">")
{
out(YSF, "<>");
printf("運算符\n");
}
else
{
fseek(fp, -1, 1);
out(YSF, "<");
printf("運算符\n");
}
break;
case"=":out(YSF, "=");printf("運算符\n");
break;
case">":ch = fgetc(fp);
if (ch == "=")
{
out(YSF, ">=");
printf("運算符\n");
}
else
{
fseek(fp, -1, 1);
out(YSF, ">");
printf("運算符\n");
}
break;
case":":ch = fgetc(fp);
if (ch == "=")
{
out(YSF, ":=");
printf("運算符\n");
}
else
{
fseek(fp, -1, 1);
out(JF, ":");
printf("界符\n");
}
break;
case"/":ch = fgetc(fp);
if (ch == "*")
{
out(JF, "/*");
printf("界符\n");
while (1)//注釋的內容在詞法分析中不顯示
while (ch != "/")
ch = fgetc(fp);
fseek(fp, -2, 1);
ch = fgetc(fp);
if (ch == "*")
{
fseek(fp, 1, 1);
break;
}
else
{
fseek(fp, 2, 1);
ch = fgetc(fp);
}
fseek(fp, -2, 1);
}
else
{
fseek(fp, -1, 1);
out(JF, "/");
printf("界符\n");
}
break;
case"*":ch = fgetc(fp);
if (ch == "/")
{
out(JF, "*/");
printf("界符\n");
}
else
{
fseek(fp, -1, 1);
out(YSF, "*");
printf("運算符\n");
}
break;
case EOF:break;
default:error();
break;
}
}
}
}
int main()
{
FILE *read;
read = fopen("E:\\a.txt", "r");
write = fopen("E:\\b.txt", "a+");
if (read == NULL)
{
printf("FILE OPEN FAIL!");
exit(0);
}
printf("===========================================================\n");
printf("====================詞法分析程序===========================\n");
printf("===========該分析程序的文件存放在E:\\a.txt 目錄下==========\n");
printf("===========該程序的分析結果存放在E:\\b.txt 目錄下===========\n");
printf("===============================
=============================\n");
function(read);
fclose(read);
system("pause");
return 0;
}
四、實驗截圖
a.txt
b.txt
基于 LL(1)方法的語法分析程序
一、 實驗目的
設計、編制和調試一個典型的語法分析方法,進一步掌握常用的語法分析方法。
二、實驗要求
1、根據 LL(1)分析法編寫一個語法分析程序,可根據自己實際情況,選擇以下一項作為分析算法的輸入:
a.直接輸入根據已知文法構造的分析表 M;
b.輸入文法的 FIRST(α)和 FOLLOW(U)集合,由
程序自動生成文法的分析表 M;
c.輸入已知文法,由程序自動構造文法的分析表M。
2、程序具有通用性
所開發的程序可適用于不同的文法和任意輸入串,且能判斷該文法是否為 LL(1)文法。
3、有運行實例
對于輸入的文法和符號串,所編制的語法分析程序應能正確判斷此串是否為文法的句子,并要求輸出分析過程。
三、實驗代碼
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dos.h>
char A[20];/*分析棧*/
char B[20];/*剩余串*/
char v1[20] = { "i","+","*","(",")","#" };/*終結符
*/
char v2[20] = { "E","G","T","S","F" };/*非終結符
*/
int j = 0, b = 0, top = 0, l;/*L 為輸入串長度 */
typedef struct type
/*產生式類型定義
*/
{
char origin; /*大寫字符
*/
char array[5]; /*產生式右邊字符 */
int length; /*字符個數
*/
}type;
type e, t, g, g1, s, s1, f, f1;/*結構體變量
*/
type C[10][10];/*預測分析表
*/
void print()/*輸出分析棧
*/
{
int a;/*指針*/
for (a = 0;a <= top + 1;a++)
printf("%c", A[a]);
printf("\t\t");
}/*print*/
void print1()/*輸出剩余串*/
{
int j;
for (j = 0;j<b;j++)/*輸出對齊符*/
printf(" ");
for (j = b;j <= l;j++)
printf("%c", B[j]);
printf("\t\t\t");
}
int _tmain(int argc, _TCHAR* argv[])
{
int m, n, k = 0, flag = 0, finish = 0;
char ch, x;
type cha;/*用來接受 C[m][n]*/
/*把文法產生式賦值結構體*/
e.origin = "E";
strcpy(e.array, "TG");
e.length = 2;
t.origin = "T";
strcpy(t.array, "FS");
t.length = 2;
g.origin = "G";
strcpy(g.array, "+TG");
g.length = 3;
g1.origin = "G";
g1.array[0] = "^";
g1.length = 1;
s.origin = "S";
strcpy(s.array, "*FS");
s.length = 3;
s1.origin = "S";
s1.array[0] = "^";
s1.length = 1;
f.origin = "F";
strcpy(f.array, "(E)");
f.length = 3;
f1.origin = "F";
f1.array[0] = "i";
f1.length = 1;
for (m = 0;m <= 4;m++)/*初始化分析表*/
for (n = 0;n <= 5;n++)
C[m][n].origin = "N";/*全部賦為空*/
/*填充分析表*/
C[0][0] = e;C[0][3] = e;
C[1][1] = g;C[1][4] = g1;C[1][5] = g1;
C[2][0] = t;C[2][3] = t;
C[3][1] = s1;C[3][2] = s;C[3][4] = C[3][5] = s1;
C[4][0] = f1;C[4][3] = f;
printf("提示:本程序只能對由"i","+","*","(",")"構成的
以"#"結束的字符串進行分析,\n");
printf("請輸入要分析的字符串:");
do/*讀入分析串*/
{
scanf("%c", &ch);
if ((ch != "i") && (ch != "+") && (ch != "*") && (ch != "(") && (ch != ")") && (ch != "#"))
{
printf("輸入串中有非法字符\n");
exit(1);
}
B[j] = ch;
j++;
} while (ch != "#");
l = j;/*分析串長度*/
ch = B[0];/*當前分析字符*/
A[top] = "#"; A[++top] = "E";/*"#","E"進棧*/
printf("步驟\t\t 分析棧 \t\t 剩余字符 \t\t 所用產生式 \n");
do
{
x = A[top--];/*x 為當前棧頂字符*/
printf("%d", k++);
printf("\t\t");
for (j = 0;j <= 5;j++)/*判斷是否為終結符*/
if (x == v1[j])
{
flag = 1;
break;
}
if (flag == 1)/*如果是終結符*/
{
if (x == "#")
{
finish = 1;/*結束標記*/
printf("acc!\n");/*接受 */
getchar();
getchar();
exit(1);
}/*if*/
if (x == ch)
{
print();
print1();
printf("%c匹配\n", ch);
ch = B[++b];/*下一個輸入字符*/
flag = 0;/*恢復標記*/
}/*if*/
else/*出錯處理*/
{
print();
print1();
printf("%c出錯\n", ch);/*輸出出錯終結符*/
exit(1);
}/*else*/
}/*if*/
else/*非終結符處理*/
{
for (j = 0;j <= 4;j++)
if (x == v2[j])
{
m = j;/*行號*/
break;
}
for (j = 0;j <= 5;j++)
if (ch == v1[j])
{
n = j;/*列號*/
break;
}
cha = C[m][n];
if (cha.origin != "N")/*判斷是否為空*/
{
print();
print1();
printf("%c->", cha.origin);/*輸出產生式*/
for (j = 0;j<cha.length;j++)
printf("%c", cha.array[j]);
printf("\n");
for (j = (cha.length - 1);j >= 0;j--)/*產生式逆序入棧*/
A[++top] = cha.array[j];
if (A[top] == "^")/*為空則不進棧*/
top--;
}/*if*/
else/*出錯處理*/
{
print();
print1();
printf("%c出錯\n", x);/*輸出出錯非終結符*/
exit(1);
}/*else*/
}/*else*/
} while (finish == 0);
return 0;
}
四、 實驗截圖
于 基于 LR(0) 方法的語法分析程序
一、實驗目的
設計、編制和調試一個典型的語法分析方法,進一步掌握常用的語法分析方法。
二、實驗要求
可根據自己實際情況,選擇以下一項作為分析算法的輸入:
(1)直接輸入根據己知文法構造的 LR(0)分析表。
(2)輸入已知文法的項目集規范族和轉換函數,由程序自動生成 LR(0)分析表; (3)輸入已知文法,由程序自動生成 LR(0)分析表。
三、程序代碼
#include "stdafx.h"
#include<iostream>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
using namespace std;
struct stack {
int
top;
int
st[15];
//狀態棧
char sn[15];
//符號棧
}*sign;
struct analysis {
//動作表結構
char act;
int
status;
}action[][6] = {
{
"s",5,"$",0,"$",0, "s",4,"$",0, "$",0
},
{
"$",0,"s",6,"$",0, "$",0,"$",0, "A",0
},
{
"$",0,"r",2,"s",7, "$",0,"r",2, "r",2
},
{
"$",0,"r",4,"r",4, "$",0,"r",4, "r",4
},
{
"s",5,"$",0,"$",0, "s",4,"$",0, "$",0
},
{
"$",0,"r",6,"r",6, "$",0,"r",6, "r",6
},
{
"s",5,"$",0,"$",0, "s",4,"$",0, "$",0
},
{
"s",5,"$",0,"$",0, "s",4,"$",0, "$",0
},
{
"$",0,"s",6,"$",0, "$",0,"s",11,"$",0
},
{
"$",0,"r",1,"s",7, "$",0,"r",1, "r",1
},
{
"$",0,"r",3,"r",3, "$",0,"r",3, "r",3
},
{
"$",0,"r",5,"r",5, "$",0,"r",5, "r",5
}
};
analysis G[] = {
{
"E",3
},{
"E",1
},{
"T",3
},{
"T",1
},{
"F",3
},{
"F",1
}
};
//此文法信息
int go[][3] = {
1,2,3,99,99,99,99,99,99,99,99,99,8,2,3,99,99,99,99,9,3,99,99,10,99,99,99,99,99,99,99,99,99,99,99,99
};
int index(char m) {
int id;
if ((m == "i") || (m == "E"))
id = 0;
else if ((m == "+") || (m == "T"))
id = 1;
else if ((m == "*") || (m == "F"))
id = 2;
else if (m == "(")
id = 3;
else if (m == ")")
id = 4;
else if (m == "#")
id = 5;
else
id = 99;
return id;
}
void main() {
cout << "參照文法為:\n" << "(1)E→E+T\n" << "(2)E→T\n" << "(3)T→T*F"\n"\
<< "(4)T→F\n" << "(5)F→(E)\n" << "(6)F→i\n";
char instr[20], *current, a;
int i = 0, step = 0, ix1, ia, ix2, ig, iG, back;
bool flag = true;
sign = new stack;
cout << "請輸入待分析的字符串(以#結束):\n";
do {
cin >> instr[i++];
} while (instr[i - 1] != "#");
instr[i] = "\0";
current = instr;
sign->st[0] = 0;sign->sn[0] = "#";sign->sn[1] = "\0";sign->top = 0;
cout << "步驟" << setw(20) << "狀
態" << setw(20) << "符
號" << setw(20) << "輸 入 串\n";
cout << "====" << setw(20) << "======" << setw(20) << "======" << setw(20) << "========\n";
cout << step++ << setw(20) << sign->st[0] << setw(21) << sign->sn << setw(21) << instr << endl;
while (flag) {
cout << step++ << setw(20);
a = *current;ia = index(a);
ix1 = sign->st[sign->top]; //cout<<a<<" "<<ia<<" "<<ix1<<" "<<action[ix1][ia].act;
//hhjhj
if (ia == 99) {
cout << "此文法無法識別該輸入串!";
break;
}
if (action[ix1][ia].act == "s") {
sign->top += 1;
sign->sn[sign->top] = a;
sign->sn[(sign->top) + 1] = "\0";
sign->st[sign->top] = action[ix1][ia].status;
current++;
}
else if (action[ix1][ia].act == "r") {
iG = action[ix1][ia].status - 1;
//零下表開始
back = G[iG].status;
sign->top -= back;
ix2 = sign->st[sign->top];
ig = index(G[iG].act);
if (go[ix2][ig] != 99)
sign->top += 1;
sign->st[sign->top] = go[ix2][ig];
sign->sn[sign->top] = G[iG].act;
sign->sn[(sign->top) + 1] = "\0";
}
else {
cout << "此文法無法識別該輸入串!";
break;
}
}
else if (action[ix1][ia].act == "$") {
cout << "此文法無法識別該輸入串!";
break;
}
else if (action[ix1][ia].act == "A") {
flag = false;
}
for (i = 0;i <= sign->top;i++)
cout << sign->st[i] << " ";
cout << setw(20 - (sign->top)) << sign->sn << setw(20 - strlen(sign->sn)) << current << endl;
if (flag == false)
cout << "文法分析成功!" << endl;
}
}
四、實驗截圖
中間代碼生成程序(逆波蘭表示)
一、實驗目的
加深對語義翻譯的理解
二、實驗要求
(1)編制一個中間代碼生成程序,能將算術表達式等翻譯成逆波蘭形式; (2)程序具有通用性,即能接受各種不同的算術表達式等語法成分。
(3)有運行實例.對于語法正確的算術表達式,能生成逆波蘭表示,并輸出結果;對不正確的表達式,能檢測出錯誤。
(4)
提交實習報告,報告內容應包括:
目的、要求,算法描述,程序代碼,運行截圖 三、程序代碼
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
class Transform
{
private:
char s_stack[20];//棧
string s_result;//轉換之后的字符串,也就是后綴表達式
int top;//棧頂
public:
Transform()
{
top=0;
s_stack[0]="#";
s_result="";
}
void pop()
{
top--;
}
void push(char b)
{
top++;
s_stack[top]=b;
}
string TF(string a)
{
bool q=0;
for (int i=0;i<a.length();i++)
{
switch (a[i])
{
case "+":
case "-":
q=1;
if (s_stack[top]!="*"&&s_stack[top]!="/"&&s_stack[top]!="@"&&s_stack[top]!="+"&&s_stack[top]!="-")
{
push(a[i]);
}
else
{
while(s_stack[top]=="*"||s_stack[top]=="/"||s_stack[top]=="@"||s_stack[top]=="+"||s_stack[top]=="-")
{
s_result+=s_stack[top];
pop();
}
push(a[i]);
}
break;
case "*":
case "/":
q=1;
if (s_stack[top]!="@"&&s_stack[top]!="*"&&s_stack[top]!="/")
{
push(a[i]);
}
else
{
while(s_stack[top]=="@"||s_stack[top]=="*"||s_stack[top]=="/")
{
s_result+=s_stack[top];
pop();
}
push(a[i]);
}
break;
case ":=":
q=1;
if (s_stack[top]!="*"&&s_stack[top]!="/"&&s_stack[top]!="@"&&s_stack[top]!="+"&&s_stack[top]!="-")
{
push(a[i]);
}
else
{
while(s_stack[top]=="*"||s_stack[top]=="/"||s_stack[top]=="@"||s_stack[top]=="+"||s_stack[top]=="-")
{
s_result+=s_stack[top];
pop();
}
push(a[i]);
}
break;
case "@"://負號
q=1;
if (s_stack[top]!="@")
{
push(a[i]);
}
else
{
while(s_stack[top]=="@")
{
s_result+=s_stack[top];
pop();
}
push(a[i]);
}
break;
case "(":
q=1;
push(a[i]);
break;
case ")":
q=1;
while(s_stack[top]!="(")
{
s_result+=s_stack[top];
pop();
}
pop();//遇到第一個匹配的(
while(s_stack[top]!="(")//可能有第二、三、四、、、、個(,
如果有,遇到會停
{
if(s_stack[top]=="#")break;
s_result+=s_stack[top];
pop();
}
break;
}
if (q==0)
{
s_result+=a[i];
}
else
{
q=0;
}
}
while(s_stack[top]!="#")//把棧中的字符都出棧
{
s_result+=s_stack[top];
pop();
}
s_result+=s_stack[top];//末尾加上#
return s_result;
}
};
void main()
{
cout<<"請輸入表達式(取反用@表示,以#結束)";
string s_in;
string s_out;
cin>>s_in;
Transform T;
s_out=T.TF(s_in);
cout<<"逆波蘭表達式為:"<<s_out<<endl;
system("pause");
}
四、實驗截圖
封面設計:
賈麗
地 址:中國河北省秦皇島市河北大街 438 號
郵 編:066004
電 話:0335-8057068
傳 真:0335-8057068
網 址:http://jwc.ysu.edu.cn
推薦訪問: 編譯 原理 實驗上一篇:學校資產管理自查報告
下一篇:分支程序設計實驗報告
在偉大祖國73華誕之際,我參加了單位組織的“光影鑄魂”主題黨日活動,集中觀看了抗美援朝題材影片《長津湖》,再一次重溫這段悲壯歷史,再一次深刻感悟偉大抗美援朝精神。1950年10月,新中國剛剛成立一年,
根據省局黨組《關于舉辦習近平談治國理政(第四卷)讀書班的通知》要求,我中心通過專題學習、專題研討以及交流分享等形式,系統的對《習近平談治國理政》(第四卷)進行了深入的學習與交流,下面我就來談一談我個人
《習近平談治國理政》(第四卷)是在百年變局和世紀疫情相互疊加的大背景下,對以習近平同志為核心的黨中央治國理政重大戰略部署、重大理論創造、重大思想引領的系統呈現。它生動記錄了新一代黨中央領導集體統籌兩個
《真抓實干做好新發展階段“三農工作”》是《習近平談治國理政》第四卷中的文章,這是習近平總書記在2020年12月28日中央農村工作會議上的集體學習時的講話。文章指出,我常講,領導干部要胸懷黨和國家工作大
在《習近平談治國理政》第四卷中,習近平總書記強調,江山就是人民,人民就是江山,打江山、守江山,守的是人民的心。從嘉興南湖中駛出的小小紅船,到世界上最大的執政黨,在中國共產黨的字典里,“人民”一詞從來都
黨的十八大以來,習近平總書記以馬克思主義戰略家的博大胸襟和深謀遠慮,在治國理政和推動全球治理中牢固樹立戰略意識,在不同場合多次圍繞戰略策略的重要性,戰略和策略的關系,提高戰略思維、堅定戰略自信、強化戰
《習近平談治國理政》第四卷集中展示了以習近平同志為核心的黨中央在百年變局和世紀疫情相互疊加背景下,如何更好地堅持和發展中國特色社會主義而進行的生動實踐與理論探索;對于新時代堅持和發展什么樣的中國特色社
在黨組織的關懷下,我有幸參加了區委組織部組織的入黨積極分子培訓班。為期一周的學習,學習形式多樣,課程內容豐富,各位專家的講解細致精彩,對于我加深對黨的創新理論的認識、對黨的歷史的深入了解、對中共黨員的
《習近平談治國理政》第四卷《共建網上美好精神家園》一文中指出:網絡玩命是新形勢下社會文明的重要內容,是建設網絡強國的重要領域。截至2021年12月,我國網民規模達10 32億,較2020年12月增長4
剛剛召開的中國共產黨第十九屆中央委員會第七次全體會議上討論并通過了黨的十九屆中央委員會向中國共產黨第二十次全國代表大會的報告、黨的十九屆中央紀律檢查委員會向中國共產黨第二十次全國代表大會的工作報告和《