燕山大学编译原理实验报告
Posted 流楚丶格念
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了燕山大学编译原理实验报告相关的知识,希望对你有一定的参考价值。
(我学校作业做的一向垃圾的一批,仅供各位燕大学弟学妹参考,有错勿喷,运行截图我都放到下载里面了,懒得粘了)
报告下载
https://download.csdn.net/download/weixin_45525272/72095664
实验1 词法分析
1.1 实验目的
(1)理解有穷自动机及其应用。
(2)掌握 NFA 到 DFA 的等价变换方法、DFA 最小化的方法。
(3)掌握设计、编码、调试词法分析程序的技术和方法。
1.2 实验任务
编写一个程序对输入的源代码进行词法分析,并打印分析结果。自己编写一个 PL/0 词法分析程序,使用的语言为C++。
1.3 算法描述
算法描述: 首先把常用关键字放在一个数组变量里,逐个判断输入的一个字符串是否为关键字,然后根据正则表达式来判断数字,字母以及各种标识符,同时对错误的语法做出判断输出
1.4 程序结构:
Main:读入字符串
analyze:词法分析
isLetter:判断是否是字母
isKey:判断是否是关键字
主函数调用analysis,analysis中调用了剩余函数。
1.5 程序清单
#include<iostream>
using namespace std;
#define MAX 21
/*
保留字|关键字:1
操作符|运算符:2
分界符:3
标识符:4
常数:5
无识别:6
*/
char ch = ' ';
char* keyWord[21] = "iostream","void","int","char","string","bool","return","using","namespace","main","break","include","begin","end","if","else","while","switch","for","else if","std" ;
char takes[20];//定义获取的字符
//判断是否是关键字
bool isKey(char* takes)
for (int i = 0; i < MAX; i++)
if (strcmp(takes, keyWord[i]) == 0)
return true;
return false;
//判断是否是字母
bool isLetter(char letter)
if ((letter >= 'a' && letter <= 'z') || (letter >= 'A' && letter <= 'Z'))
return true;
else
return false;
//判断是否是数字
bool isDigit(char digit)
if (digit >= '0' && digit <= '9')
return true;
else
return false;
//词法分析
void analyze(FILE* fpin)
while ((ch = fgetc(fpin)) != EOF)
if (ch == ' ' || ch == '\\t' || ch == '\\n') //空格 回车
else if (isLetter(ch)) //首是字母
char takes[30] = '\\0' ;
int i = 0;
while (isLetter(ch) || isDigit(ch)) //后面是字母或者数字
takes[i] = ch;
i++;
ch = fgetc(fpin);
//回退一个指针
fseek(fpin, -1L, SEEK_CUR);
if (isKey(takes))
//关键字
cout << takes << "\\t\\t1" << "\\t关键字" << endl;
else
//标识符
cout << takes << "\\t\\t4" << "\\t标识符" << endl;
else if (isDigit(ch) || (ch == '.')) //首是数字或者点
bool mark = true;
int i = 0;
char takes[20] = '\\0' ;
while (isDigit(ch) || isLetter(ch) || (ch == '.' && isDigit(fgetc(fpin))))
if (isLetter(ch))
mark = false;
if (ch == '.')fseek(fpin, -1L, SEEK_CUR);
takes[i] = ch;
i++;
ch = fgetc(fpin);
else
if (ch == '.')fseek(fpin, -1L, SEEK_CUR);
takes[i] = ch;
i++;
ch = fgetc(fpin);
fseek(fpin, -1L, SEEK_CUR);
//属于无符号常数
if (mark)
cout << takes << "\\t\\t5" << "\\t常数" << endl;
else
cout << takes << "\\t\\t7" << "\\t错误的标识符" << endl;
else switch (ch)
//运算符
case '+':
ch = fgetc(fpin);
if (ch == '+')cout << "++" << "\\t\\t2" << "\\t运算符" << endl;
else
cout << "+" << "\\t\\t2" << "\\t运算符" << endl;
fseek(fpin, -1L, SEEK_CUR);
break;
case '-':
ch = fgetc(fpin);
if (ch == '-')cout << "--" << "\\t\\t2" << "\\t运算符" << endl;
else
cout << "-" << "\\t\\t2" << "\\t运算符" << endl;
fseek(fpin, -1L, SEEK_CUR);
break;
case '*':cout << ch << "\\t\\t2" << "\\t运算符" << endl; break;
case '/':cout << ch << "\\t\\t2" << "\\t运算符" << endl; break;
//分界符
case '\\"':cout << ch << "\\t\\t2" << "\\t分界符" << endl; break;
case '(':cout << ch << "\\t\\t3" << "\\t分界符" << endl; break;
case ')':cout << ch << "\\t\\t3" << "\\t分界符" << endl; break;
case '[':cout << ch << "\\t\\t3" << "\\t分界符" << endl; break;
case ']':cout << ch << "\\t\\t3" << "\\t分界符" << endl; break;
case ';':cout << ch << "\\t\\t3" << "\\t分界符" << endl; break;
case '':cout << ch << "\\t\\t3" << "\\t分界符" << endl; break;
case '':cout << ch << "\\t\\t3" << "\\t分界符" << endl; break;
//运算符
case '=':
ch = fgetc(fpin);
if (ch == '=')cout << "==" << "\\t\\t2" << "\\t运算符" << endl;
else
cout << "=" << "\\t\\t2" << "\\t运算符" << endl;
fseek(fpin, -1L, SEEK_CUR);
break;
case '#':
ch = fgetc(fpin);
if (ch == '=')cout << "#=" << "\\t\\t2" << "\\t运算符" << endl;
else
cout << "#" << "\\t\\t2" << "\\t运算符" << endl;
fseek(fpin, -1L, SEEK_CUR);
break;
case ':':
ch = fgetc(fpin);
if (ch == '=')cout << ":=" << "\\t\\t2" << "\\t运算符" << endl;
else
cout << ":" << "\\t\\t2" << "\\t运算符" << endl;
fseek(fpin, -1L, SEEK_CUR);
break;
case '>':
ch = fgetc(fpin);
if (ch == '=')cout << ">=" << "\\t\\t2" << "\\t运算符" << endl;
else
cout << ">" << "\\t\\t2" << "\\t运算符" << endl;
fseek(fpin, -1L, SEEK_CUR);
break;
case '<':
ch = fgetc(fpin);
if (ch == '=')cout << "<=" << "\\t\\t2" << "\\t运算符" << endl;
else
cout << "<" << "\\t\\t2" << "\\t运算符" << endl;
fseek(fpin, -1L, SEEK_CUR);
break;
//无识别
default: cout << ch << "\\t\\t6" << "\\t无识别符" << endl;
int main()
char input[30];
FILE* fpin;
cout << "请输入源文件名:\\n" << endl;
for (;;)
cin >> input;
if ((fpin = fopen(input, "r")) != NULL)
break;
else
cout << "路径输入错误" << endl;
cout << "词法分析结果: " << endl;
analyze(fpin);
fclose(fpin);
1.6 主要变量说明:
#define MAX 21 //定义关键字数量
char takes[20];//定义获取的字符
char*keyWord[21]="iostream","void","int","char","string","bool","return","using","namespace","main","break","include","begin","end","if","else","while","switch","for","else if","std";//保存关键字
1.7 调试情况
一个含C++源码的文本文件
调试情况及运行结果截图:
顺利执行,同时错误的语法也可以进行正确的判断
1.8 心得体会
通过完成词法分析程序的过程,更加深入的了解和复习了C++的使用方法,某些函数的运用,以及字符串的提取判别,文件流读取操作等等,也在调用函数过程中出现了许多的问题,通过请教同学和查阅资料都得到了解决.学习了新的函数,对C++有了更加充实的认知.
实验2 基于LL(1)方法的语法分析程序
2.1 实验目的
设计、编制和调试一个典型的语法分析方法,进一步掌握常用的语法分析方法。
2.2 实验要求
根据LL(1)分析法编写一个语法分析程序,直接输入根据已知文法构造的分析表M;
(1)程序具有通用性
所开发的程序可适用于任意输入串,且能判断该文法是否为LL(1)文法。
(2)有运行实例
对于输入符号串,所编制的语法分析程序应能正确判断此串是否为文法的句子,并要求输出分析过程。
2.3 算法描述
给定文法G[S]:
表
示
空
串
S
−
>
A
T
A
−
>
B
U
T
−
>
+
A
T
∣
表示空串 S->AT A->BU T->+AT|
表示空串S−>ATA−>BUT−>+AT∣
U->*BU|$
B->(S)|m
计算First集与Follow集合,先建立分析表,读入字符串,初始化分析栈,进入分析函数。
从左到右扫描输入串,采用最左推导,且每次直接推导只向前看一个输入符号,确定选择的规则。用一个变量记录步骤数量,及时输出。用一个变量记录输入字符串下标,作为指针的作用,控制String输出。
从分析栈中取栈顶,判断是否为非终结符号 。若是,找到栈顶在分析表中对应的规则。若为null,报错。存在,则执行输出;若不是,则判断其与输入式子头字符是否相同,相同,则输出匹配。继续读取栈顶,循环直至到底。
2.4 程序结构
Main:读入字符串
Analysis:分析函数
findH:寻找非终结符下标
findL:寻找终结符下标
Error:报错函数
主函数调用analysis,analysis中调用了剩余函数。
2.5 主要变量说明
LL1:LL1文法分析表
H:非终结符
L:终结符
Cmp:分析栈
Str:输入式
2.6 程序清单
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <stack>
using namespace std;
//表格数组
char LL1[50][50][100] = "->AT", "->AT", "null", "null", "null", "null",
"->BU", "->BU", "null", "null", "null", "null",
"null", "null", "->$", "->+AT", "null", "->$",
"null", "null", "->$", "->$", "->*BU", "->$",
"->m", "->(S)", "null", "null", "null", "null" ;
char H[200] = "SATUB";
char L[200] = "m()+*#";
stack<char> cmp;
int findH(char a)
//在H中找规则左部
for (int i = 0; i < 5; i++) //找到对应行
if (a == H[i])
return i;
return -1;
int findL(char b)
//在L中找 找到对应列
for (int i = 0; i < 6; i++) //找到对应列
if (b == L[i])
return i;
return -1;
int error(int i, int cnt, int len, char p[], char str[])
//输入的第i个符号 执行第cnt步 输入len长 第一列p列内容 str输入表达式
printf("%d\\t%s\\t", cnt, p);
for (int q = i; q < len; q++)
cout << str[q];
printf("\\t报错\\n");
return len;
void analyze(char str[], int len)
//pindex记录stack长度,p为分析栈状态
int cnt = 1; //输出Step专用
int i = 0;
char p[200] = "#S"; //输出stack专用
int pindex = 2;
printf("Step\\tStack\\tString\\tRule\\n"); //输出制表
while (i < len)
int x, y;
char ch = cmp.top(); //是规则右部分 出栈
以上是关于燕山大学编译原理实验报告的主要内容,如果未能解决你的问题,请参考以下文章
南京大学编译实验 Lab 3 自动测试脚本(适用于编译原理课程 C-- 语言实验的 irsim.pyc 虚拟机小程序自动化执行)
编译原理--词法分析--实验报告(此文章在管理-发表文章 里也有)