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

编译原理词法分析实验报告实验名称:词法分析器的设计与实现一、实验目的:1.熟悉编译原理中词法分析的基本概念和原理;2.掌握正则表达式的使用方法;3.实现一个简单的词法分析器。
二、实验内容:1.设计一个简单的编程语言,包含如下几种类型的词法单元:关键字、标识符、常量、运算符和界符。
2.使用正则表达式定义每种词法单元的模式。
3.设计一个词法分析器,将源代码中的每个词法单元识别出来并输出。
三、实验步骤:1. 确定编程语言的词法单元类型和正则表达式模式,定义相应的单词类型(如 TokenType)和模式(如 regex)。
2. 实现一个词法分析器的类 Lexer,包含以下方法:(1)一个构造方法,用于初始化词法分析器的输入源代码。
(2) 一个getNextToken方法,用于获取源代码中的下一个词法单元。
3. 在getNextToken方法中,使用正则表达式逐个识别源代码中的词法单元,并返回相应的Token对象。
4. 设计一个Token类,包含以下属性:词法单元类型、词法单元的值和位置信息等。
5.在主程序中使用词法分析器,将源代码中的每个词法单元识别出来并输出。
四、实验结果:1.设计一个简单的编程语言,包含如下词法单元类型(示例):(1) 关键字:if、else、while、for等;(2)标识符:变量名等;(3)常量:整数、浮点数、字符串等;(4)运算符:+、-、*、/、=等;(5)界符:(、)、{、}、;等。
2. 实现一个词法分析器,识别出源代码中的每个词法单元,并输出相应的Token对象。
五、实验总结:通过本次实验,我熟悉了编译原理中词法分析的基本概念和原理,并掌握了正则表达式的使用方法。
我成功完成了一个简单的词法分析器的设计与实现,实现了源代码中每个词法单元的识别与输出。
这次实验对我深化了对编译原理中词法分析的理解,并提高了我的编程能力。
编译原理实验报告

编译原理实验报告一、实验目的本次编译原理实验的主要目的是通过实践加深对编译原理中词法分析、语法分析、语义分析和代码生成等关键环节的理解,并提高实际动手能力和问题解决能力。
二、实验环境本次实验使用的编程语言为 C/C++,开发工具为 Visual Studio 2019,操作系统为 Windows 10。
三、实验内容(一)词法分析器的设计与实现词法分析是编译过程的第一个阶段,其任务是从输入的源程序中识别出一个个具有独立意义的单词符号。
在本次实验中,我们使用有限自动机的理论来设计词法分析器。
首先,我们定义了单词的种类,包括关键字、标识符、常量、运算符和分隔符等。
然后,根据这些定义,构建了相应的状态转换图,并将其转换为程序代码。
在实现过程中,我们使用了字符扫描和状态转移的方法,逐步读取输入的字符,判断其所属的单词类型,并将其输出。
(二)语法分析器的设计与实现语法分析是编译过程的核心环节之一,其任务是在词法分析的基础上,根据给定的语法规则,判断输入的单词序列是否构成一个合法的句子。
在本次实验中,我们采用了自顶向下的递归下降分析法来实现语法分析器。
首先,我们根据给定的语法规则,编写了相应的递归函数。
每个函数对应一种语法结构,通过对输入单词的判断和递归调用,来确定语法的正确性。
在实现过程中,我们遇到了一些语法歧义的问题,通过仔细分析语法规则和调整函数的实现逻辑,最终解决了这些问题。
(三)语义分析与中间代码生成语义分析的任务是对语法分析所产生的语法树进行语义检查,并生成中间代码。
在本次实验中,我们使用了四元式作为中间代码的表示形式。
在语义分析过程中,我们检查了变量的定义和使用是否合法,类型是否匹配等问题。
同时,根据语法树的结构,生成相应的四元式中间代码。
(四)代码优化代码优化的目的是提高生成代码的质量和效率。
在本次实验中,我们实现了一些基本的代码优化算法,如常量折叠、公共子表达式消除等。
通过对中间代码进行分析和转换,减少了代码的冗余和计算量,提高了代码的执行效率。
编译原理实验词法分析实验报告

编译原理实验词法分析实验报告一、实验目的词法分析是编译过程的第一个阶段,其主要任务是从左到右逐个字符地对源程序进行扫描,产生一个个单词符号。
本次实验的目的在于通过实践,深入理解词法分析的原理和方法,掌握如何使用程序设计语言实现词法分析器,提高对编译原理的综合应用能力。
二、实验环境本次实验使用的编程语言为_____,开发工具为_____。
三、实验原理词法分析的基本原理是根据编程语言的词法规则,将输入的字符流转换为单词符号序列。
单词符号通常包括关键字、标识符、常量、运算符和界符等。
词法分析器的实现方法有多种,常见的有状态转换图法和正则表达式法。
在本次实验中,我们采用了状态转换图法。
状态转换图是一种有向图,其中节点表示状态,有向边表示在当前状态下输入字符的可能转移。
通过定义不同的状态和转移规则,可以实现对各种单词符号的识别。
四、实验步骤1、定义单词符号的类别和编码首先,确定实验中要识别的单词符号种类,如关键字(if、else、while 等)、标识符、整数常量、浮点数常量、运算符(+、、、/等)和界符(括号、逗号等)。
为每个单词符号类别分配一个唯一的编码,以便后续处理。
2、设计状态转换图根据单词符号的词法规则,绘制状态转换图。
例如,对于标识符的识别,起始状态为“起始状态”,当输入为字母时进入“标识符中间状态”,在“标识符中间状态”中,若输入为字母或数字则继续保持该状态,直到遇到非字母数字字符时结束识别,确定为一个标识符。
3、编写词法分析程序根据状态转换图,使用所选编程语言实现词法分析器。
在程序中,通过不断读取输入字符,根据当前状态进行转移,并在适当的时候输出识别到的单词符号。
4、测试词法分析程序准备一组包含各种单词符号的测试用例。
将测试用例输入到词法分析程序中,检查输出的单词符号是否正确。
五、实验代码以下是本次实验中实现词法分析器的核心代码部分:```include <stdioh>include <ctypeh>//单词符号类别定义typedef enum {KEYWORD,IDENTIFIER,INTEGER_CONSTANT,FLOAT_CONSTANT,OPERATOR,DELIMITER} TokenType;//关键字列表char keywords ={"if","else","while","for","int","float","void"};//状态定义typedef enum {START,IN_IDENTIFIER,IN_INTEGER,IN_FLOAT,IN_OPERATOR} State;//词法分析函数TokenType getToken(char token, int tokenLength) {State state = START;int i = 0;while (1) {char c = getchar();switch (state) {case START:if (isalpha(c)){state = IN_IDENTIFIER;tokeni++= c;} else if (isdigit(c)){state = IN_INTEGER;tokeni++= c;} else if (c =='+'|| c ==''|| c ==''|| c =='/'|| c =='('|| c ==')'|| c ==';'|| c ==','){state = IN_OPERATOR;tokeni++= c;} else if (c ==''){state = IN_FLOAT;tokeni++= c;} else if (c == EOF) {tokeni ='\0';tokenLength = i;return -1;} else {tokeni ='\0';tokenLength = i;return -2;}break;case IN_IDENTIFIER:if (isalpha(c) || isdigit(c)){tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;//检查是否为关键字for (int j = 0; j < sizeof(keywords) / sizeof(keywords0); j++){if (strcmp(token, keywordsj) == 0) {return KEYWORD;}}return IDENTIFIER;}break;case IN_INTEGER:if (isdigit(c)){tokeni++= c;} else if (c ==''){state = IN_FLOAT;tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;return INTEGER_CONSTANT;}break;case IN_FLOAT:if (isdigit(c)){tokeni++= c;} else {ungetc(c, stdin);tokeni ='\0';tokenLength = i;return FLOAT_CONSTANT;}break;case IN_OPERATOR: tokeni ='\0';tokenLength = i;return OPERATOR; break;}}}int main(){char token100;int tokenLength;TokenType tokenType;while ((tokenType = getToken(token, &tokenLength))!=-1) {switch (tokenType) {case KEYWORD:printf("Keyword: %s\n", token);break;case IDENTIFIER:printf("Identifier: %s\n", token);break;case INTEGER_CONSTANT:printf("Integer Constant: %s\n", token);break;case FLOAT_CONSTANT:printf("Float Constant: %s\n", token);break;case OPERATOR:printf("Operator: %s\n", token);break;case DELIMITER:printf("Delimiter: %s\n", token);break;}}return 0;}```六、实验结果对准备的测试用例进行输入,得到的词法分析结果如下:测试用例 1:```int main(){int num = 10;float pi = 314;if (num > 5) {printf("Hello, World!\n");}}```词法分析结果:```Keyword: int Identifier: main Delimiter: (Delimiter: ){Identifier: num Operator: =Integer Constant: 10;Identifier: float Identifier: pi Operator: =Float Constant: 314;Keyword: ifDelimiter: (Identifier: numOperator: >Integer Constant: 5){Identifier: printfDelimiter: (String: "Hello, World!\n" Delimiter: );}```测试用例 2:```for (int i = 0; i < 10; i++){double result = i 25;```词法分析结果:```Keyword: for Delimiter: (Keyword: int Identifier: i Operator: =Integer Constant: 0;Identifier: i Operator: <Integer Constant: 10;Identifier: i Operator: ++)Identifier: doubleIdentifier: resultOperator: =Identifier: iOperator:Float Constant: 25;}```通过对多个测试用例的分析,词法分析器能够正确识别出各种单词符号,实验结果符合预期。
编译原理实验报告

编译原理实验报告一、实验目的编译原理是计算机科学中的重要学科,它涉及到将高级编程语言转换为计算机能够理解和执行的机器语言。
本次实验的目的是通过实际操作和编程实践,深入理解编译原理中的词法分析、语法分析、语义分析以及中间代码生成等关键环节,提高我们对编译过程的认识和编程能力。
二、实验环境本次实验使用的编程语言为C++,开发环境为Visual Studio 2019。
此外,还使用了一些相关的编译工具和调试工具,如 GDB 等。
三、实验内容(一)词法分析器的实现词法分析是编译过程的第一步,其任务是将输入的源程序分解为一个个单词符号。
在本次实验中,我们使用有限自动机的理论来设计和实现词法分析器。
首先,定义了各种单词符号的类别,如标识符、关键字、常量、运算符等。
然后,根据这些类别设计了相应的状态转换图,并将其转换为代码实现。
在实现过程中,使用了正则表达式来匹配输入字符串中的单词符号。
对于标识符和常量等需要进一步处理的单词符号,使用了相应的规则进行解析和转换。
(二)语法分析器的实现语法分析是编译过程的核心环节之一,其任务是根据给定的语法规则,分析输入的单词符号序列是否符合语法结构。
在本次实验中,我们使用了递归下降的语法分析方法。
首先,根据实验要求定义了语法规则,并将其转换为相应的递归函数。
在递归函数中,通过对输入单词符号的判断和处理,逐步分析语法结构。
为了处理语法错误,在分析过程中添加了错误检测和处理机制。
当遇到不符合语法规则的输入时,能够输出相应的错误信息,并尝试进行恢复。
(三)语义分析及中间代码生成语义分析的目的是对语法分析得到的语法树进行语义检查和语义处理,生成中间代码。
在本次实验中,我们使用了三地址码作为中间代码的表示形式。
在语义分析过程中,对变量的定义和使用、表达式的计算、控制流语句等进行了语义检查和处理。
对于符合语义规则的语法结构,生成相应的三地址码指令。
四、实验步骤(一)词法分析器的实现步骤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.2 各种单词符号对应的种别码:2.3 词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……三、词法分析程序的C语言程序源代码:#include <stdio.h>#include <string.h>char prog[80],token[8],ch;int syn,p,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};scaner();void scanner_example (FILE *fp);main(){FILE *fp;fp=fopen("D:\\1.txt","r");//打开文件scanner_example (fp);scaner();}void scanner_example (FILE *fp){do{ch=fgetc (fp);prog[p++]=ch;}while (ch!='#');p=0;do{scaner();switch(syn){case 11:printf("( %-10d%5d )\n",sum,syn);break;case -1:printf("you have input a wrong string\n");default: printf("( %-10s%5d )\n",token,syn);break;}}while(syn!=0);}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;ch=prog[p++];m=0;while((ch==' ')||(ch=='\n'))ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch;ch=prog[p++];}p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){ syn=n+1;break;}}else if((ch>='0')&&(ch<='9')){ while((ch>='0')&&(ch<='9')){ sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=22;token[m++]=ch;}else{ syn=20;p--;}break;case '>':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=24;token[m++]=ch;}else{ syn=23;p--;}break;case '+': token[m++]=ch;ch=prog[p++];if(ch=='+'){ syn=17;token[m++]=ch;}else{ syn=13;p--;}break;case '-':token[m++]=ch;ch=prog[p++];if(ch=='-'){ syn=29;token[m++]=ch;}else{ syn=14;p--;}break;case '!':ch=prog[p++];if(ch=='='){ syn=21;token[m++]=ch;}else{ syn=31;p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=25;token[m++]=ch;}else{ syn=18;p--;}break;case '*': syn=15;token[m++]=ch;break;case '/': syn=16;token[m++]=ch;break;case '(': syn=27;token[m++]=ch;break;case ')': syn=28;token[m++]=ch;break;case '{': syn=5;token[m++]=ch;break;case '}': syn=6;token[m++]=ch;break;case ';': syn=26;token[m++]=ch;break;case '\"': syn=30;token[m++]=ch;break;case '#': syn=0;token[m++]=ch;break;case ':':syn=17;token[m++]=ch;break;default: syn=-1;break;}token[m++]='\0';}四、结果分析:输入begin x:=9: if x>9 then x:=2*x+1/3; end # 后经词法分析输出如下序列:(begin 1)(x 10)(:17)(= 18)(9 11)(;26)(if 2)……如图所示:五、总结:词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
编译原理词法分析器语法分析器实验报告

printf("请输入各终结符(#号表示结束)Vt[i]:\n");
for(i=0;i<100;i++)
{
scanf("%c",&Vt[i]);
if(Vt[i]=='#')
{
r=i;
break;
}
}
printf("请输入非终结符个数:\n");
scanf("%d",&n);
getchar();
p=s->next;
while(p!=NULL)
{
st[i++]=p->data;
p=p->next;
}
for(j=i-1;j>=0;j--)
printf("%c",st[j]);
for(j=0;j<16-i;j++) //打印对齐格式
printf("%c",' ');
}
char gettop(stackk *s) //返回栈顶元素值
{
stackk *p;
p=(stackk *)malloc(sizeof(stackk));
p->data=x;
p->next=s->next;
s->next=p;
}
void display(stackk *s) //打印现实显示栈内元素
{
stackk *p;
int i=0,j;
char st[100];
#include<string.h>
#include<malloc.h>
编译原理的实验报告

一、实验目的1. 理解编译原理的基本概念和原理。
2. 掌握编译器的各个阶段及其实现方法。
3. 能够运用编译原理的知识解决实际问题。
二、实验环境1. 操作系统:Windows 102. 编程语言:C++3. 开发工具:Visual Studio 20194. 实验内容:词法分析、语法分析、语义分析、中间代码生成、代码优化、目标代码生成三、实验内容1. 词法分析(1)实验目的:实现一个简单的词法分析器,将源代码中的字符序列转换为词法符号序列。
(2)实验步骤:1)定义词法符号类型,包括标识符、关键字、运算符、常量等。
2)设计词法分析器算法,对源代码进行遍历,将字符序列转换为词法符号序列。
3)实现词法分析器程序,输出词法符号序列。
(3)实验结果:输入源代码:int a = 10;输出词法符号序列:{<int, int>, <a, a>, <=, =>, <10, 10>, <;, ;>}2. 语法分析(1)实验目的:实现一个简单的语法分析器,将词法符号序列转换为抽象语法树(AST)。
(2)实验步骤:1)定义语法规则,包括产生式、非终结符、终结符等。
2)设计语法分析算法,根据语法规则对词法符号序列进行解析,生成AST。
3)实现语法分析器程序,输出AST。
(3)实验结果:输入词法符号序列:{<int, int>, <a, a>, <=, =>, <10, 10>, <;, ;>}输出AST:```AST:- ExpressionStatement- Expression- BinaryExpression- Identifier: a- Operator: =- Constant: 10```3. 语义分析(1)实验目的:实现语义分析器,对AST进行语义检查,确保程序的正确性。
(2)实验步骤:1)定义语义规则,包括类型检查、作用域检查等。
编译原理词法分析器实验报告

一、实验目的设计一个简单的词法分析器,从而进一步加深对词法分析器工作原理的明白得。
二、实验要求一、该个词法分析器要求至少能够识别以下几类单词:(1)关键字:else if int return void while共6个,所有的关键字都是保留字,而且必需是小写;(2)标识符:识别与C语言词法规定相一致的标识符,通过以下正那么表达式概念:ID = letter (letter | digit)*;(3)常数:NUM = digit digit*(.digit digit* |ε)(e(+ | - |ε) digit digit* |ε),letter = a|..|z|A|..|Z|,digit = 0|..|9,包括整数,如123等;小数,如123.45等;科学计数法表示的常数,如1.23e3,2.3e-9等;(4)专用符号:+ - * / < <= > >= == != = ; , ( ) [ ] { } /* */;二、分析器的输入为由上述几类单词组成的程序,输出为该段程序的机内表示形式,即关键字、运算符、界限符变成其对应的机内符,常数利用二进制形式,标识符利用相应的标识符表指针表示。
3、词法分析器应当能够指出源程序中的词法错误,如不可识别的符号、错误的词法等。
三、实验环境实验环境为win7系统、vs2005。
四、实验内容1、词法分析程序的功能:输入:所给文法的源程序字符串。
输出:二元组(syn,token)或(sum或fsum,对应二进制)组成的序列。
其中:syn为单词类别码;token为寄存的单词自身字符串;sum为整型常数;fsum为浮点型常数。
二、各类单词符号类别码如下表:五、要紧函数说明一、程序全局变量char inputstr[300],token[8];//别离寄存程序段、组成单词符号的字符串char ch;//输入字符int syn;//单词字符的类别码int p;//缓冲区inputstr的指针int sum;//整型常量float fsum;//浮点型常量char *rwtab[6]={"else","if","int","return","void","while"};//关键字数组二、语法分析函数void scaner()该函数完成所有的语法分析,关于输入的程序片段,第一去掉空格和换行,然后逐字符分析,找出各个单词(存入token[8]),判别它们的类型(确信syn 值,若是是整数那么是sum值,若是是浮点数那么是fsum)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(此文档为word格式,下载后您可任意编辑修改!)编译技术班级网络0802学号姓名叶晨舟指导老师朱玉全2011年 7 月 4 日一、目的编译技术是理论与实践并重的课程,而其实验课要综合运用一、二年级所学的多门课程的内容,用来完成一个小型编译程序。
从而巩固和加强对词法分析、语法分析、语义分析、代码生成和报错处理等理论的认识和理解;培养学生对完整系统的独立分析和设计的能力,进一步培养学生的独立编程能力。
二、任务及要求基本要求:1.词法分析器产生下述小语言的单词序列这个小语言的所有的单词符号,以及它们的种别编码和内部值如下表:对于这个小语言,有几点重要的限制:首先,所有的关键字(如IF﹑WHILE等)都是“保留字”。
所谓的保留字的意思是,用户不得使用它们作为自己定义的标示符。
例如,下面的写法是绝对禁止的:IF(5)=x其次,由于把关键字作为保留字,故可以把关键字作为一类特殊标示符来处理。
也就是说,对于关键字不专设对应的转换图。
但把它们(及其种别编码)预先安排在一张表格中(此表叫作保留字表)。
当转换图识别出一个标识符时,就去查对这张表,确定它是否为一个关键字。
再次,如果关键字、标识符和常数之间没有确定的运算符或界符作间隔,则必须至少用一个空白符作间隔(此时,空白符不再是完全没有意义的了)。
例如,一个条件语句应写为IF i>0 i= 1;而绝对不要写成IFi>0 i=1;因为对于后者,我们的分析器将无条件地将IFI看成一个标识符。
这个小语言的单词符号的状态转换图,如下图:2.语法分析器能识别由加+ 减- 乘* 除乘方^ 括号()操作数所组成的算术表达式,其文法如下:E→E+T|E-T|TT→T*F|TF|FF→P^F|Pp→(E)|i使用的算法可以是:预测分析法;递归下降分析法;算符优先分析法;LR分析法等。
3.中间代码生成器产生上述算术表达式的中间代码(四元式序列)三、实现过程给出各题目的详细算法描述,数据结构和函数说明,流程图。
1、词法分析器的流程图2、语法分析器主程序图3、中间代码生成器流程图:四、源程序词法分析器:#include<string. 0;elsereturn s->next->data;}int find(char c,char array[]) 查找函数,{int i;int flag=0;for(i=0;i<100;i++){if(c==array[i])flag=1;}return flag;}int location(char c,char array[]) 定位函数,指出字符所在位置{int i;for(i=0;i<100;i++){if(c==array[i])return i;}}void error() 出错函数定义{printf("%15c出错!\n",' ');}void analyse(char Vn[],char Vt[]){int i,j,m,p,q,length,t,(str);i++){if(!find(str[i],Vt)){printf("输入字符串有误!请重新输入!");goto opt0;break;}}stackk *st;initlink(st);pushlink(st,'#');pushlink(st,Vn[0]); #与识别符号入栈j=0;",' ',' ',' ');opt1:printf("%-16d",(str);t++){printf("%c",str[t]); 显示剩余字符串}if(find(X,Vt)&& X!='#') 分析栈的栈顶元素和剩余输入串的第一个元素相比较{if(X==w){printf("%15c匹配\n",X);j++;w=str[j];goto opt1;}elseerror();}else{if(X=='#'){if(X==w){printf("%8c是该文法的句子!\n",' ');}elseerror();}else{p=location(X,Vn);q=location(w,Vt);char *S1="null",*S2="NULL";if(strcmp(M[p][q].m,S1)==0||strcmp(M[p][q].m,S2)==0) 查找产生式error();else{char str0[100];strcpy(str0,M[p][q].m);printf("%15c-->%s\n",X,str0); 显示对应的产生式if(strcmp(str0,"$")==0)goto opt1;else{length=strlen(str0); 逆序进栈for(m=length-1;m>=0;m--){pushlink(st,str0[m]);}goto opt1;}}}}}int main(){int i,k,n,r;char Vn[100],Vt[100],select;printf("******************************************************************\n");printf("对任意输入LL(1)文法的分析表,判断验证字符串是否为该文法的句子\n");printf("并能给出分析和演示过程。
\n");printf("******************************************************************\n"); opt2:printf("请输入各终结符(#号表示结束)Vt[i]:\n");for(i=0;i<100;i++){scanf("%c",&Vt[i]);if(Vt[i]=='#'){r=i;break;}}printf("请输入非终结符个数:\n");scanf("%d",&n);getchar();for (i=0;i<n;i++){printf("请输入非终结符Vn[%d]:\n",i);scanf("%c",&Vn[i]);getchar();printf("请输入此非终结符对应各终结符的产生式右部(null或NULL表示出错;$表示空串):\n");for(k=0;k<=r;k++){scanf("%s",M[i][k].m);getchar();}}opt3:printf("请输入要分析的字符串,且以#结束:\n");analyse(Vn, Vt);printf("********************请选择***********************\n");printf(" 1: 输入字符串\n");printf(" 2: 输入新分析表\n");printf(" 0: 退出\n");printf("*************************************************\n"); opt4:cin>>select;switch(select){case '1': {goto opt3;break;}case '2': {goto opt2;}case '0': {break;}default: {printf("输入错误!请重新选择:");goto opt4;break;}}return 0;}运行结果:语法分析器源程序:#include<string.[10];char ch;int syn,p,m=0,n,row,sum=0;char *rwtab[20]={"dim","if","do","stop","end" ,"and","begin","bool","case","char", "false","for","int","not","or","set","then","true","until","while"};void scaner(){for(n=0;n<9;n++) token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=21;for(n=0;n<20;n++){if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}}else if((ch>='0'&&ch<='9')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=7+15;if(sum>32767)syn=-1;}else switch(ch){case'=':syn=8+15;token[0]=ch;break; case'+':syn=9+15;token[0]=ch;break; case'*':m=0;token[m++]=ch;ch=prog[p++];if(ch=='*'){syn=11+15;token[m++]=ch;}else{syn=10+15;p--;break;case',':syn=12+15;token[0]=ch;break; case'(':syn=13+15;token[0]=ch;break; case')':syn=14+15;token[0]=ch;break; case'#':syn=0;token[0]=ch;break; case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=17+15;token[m++]=ch;}else if(ch=='='){syn=16+15;token[m++]=ch;}else{syn=15+15;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=19+15;token[m++]=ch;}else{syn=18+15;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=21+15;token[m++]=ch;}{syn=20+15;p--;}break;case'':syn=22+15;token[0]=ch;break;case'-':syn=23+15;token[0]=ch;break;case';':syn=24+15;token[0]=ch;break;default: syn=-1;break;}}void main(){p=0;row=1;cout<<endl<<endl<<endl;cout<<"***************************小型词法分析器**********************************"<<endl<<endl;cout<<"请输入一段程序(以#结束):";do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;cout<<endl<<"**************************词法分析结果如下*********************************"<<endl;cout<<" 种别编码自身值"<<endl;do{scaner();switch(syn){case 22 : cout<<" ("<<syn<<" , "<<sum<<")"<<endl; break;case -1: cout<< " Error in row"<<row<<"!"<<endl; break;default: cout<<" ("<<syn<<" , "<<token<<")"<<endl;break;}}while (syn!=0);运行结果:}中间代码生成器源程序:表达式生成四元式递归子程序法#include<string>#include <iostream>using namespace std;#define DEFAULT_SIZE 100char EMachine(char w); 表达式E的自动机char TMachine(char w); 表达式T的自动机char FMachine(char w); 表达式F的自动机bool ZMachine(); 表达式Z的自动机string intToString(int a); 整形变成字符串形函数class stack 栈类定义{private:int top;string *stacka;int maxsize;public:stack(int size=DEFAULT_SIZE);~stack(){ delete [] stacka; }void push(const string &item);string pop(void);string gettop(void) const ;bool empty(void) const { return (top==-1); }bool full(void) const { return (top==maxsize-1); }void clear(void) { top=-1; }stack::stack(int size) 栈类的构造函数{top=-1;maxsize=size;stacka=new string[maxsize];if(!stacka){cerr<<"allocate memory failed."<<endl;exit(1);}}void stack::push(const string &item) 压栈操作{if(full()){cerr<<"stack full, cannot push."<<endl;return;}top++;stacka[top]=item;}string stack::pop(void) 出栈操作{if(empty()){cerr<<"stack empty, cannot pop."<<endl;exit(1) ;}string item=stacka[top];top--;return item;}string stack::gettop(void) const 取栈顶操作{if(empty()){cerr<<"stack empty, cannot gettop."<<endl;exit(1) ;}return stacka[top];}static stack wordStack; 符号栈static int noOfQuet=0; 静态四元式个数记录static int noOfT = 1; 静态状态个数记录void main(){ 主函数char yesOrNo; 进行一个循环操作控制do{cout<<"请输入算术表达式:"<<endl;noOfT = 1; 每次结束询问ZMachine();cout<<endl<<"Continue?Y es or Not:";cin>>yesOrNo; 输入“Y”则继续}while(yesOrNo=='y'); 否则程序结束}bool ZMachine(){ Z自动机char w;cin>>w;w = EMachine(w); 调用E自动机if(w=='#'){ 遇到“#”则结束return true;}else{return false;}}char EMachine(char w){ E自动机string operate,a,b,c;string state[5];w = TMachine(w); 调用T自动机while(w=='+'||w=='-'){ 是加或减符号operate = w;cin>>w; 读入下一字符w = TMachine(w); 调用T自动机b = wordStack.pop(); 字符栈弹出a = wordStack.pop(); 两个操作字符cout<<"(\""<<operate<<"\","<<a<<","<<b<<",t"<<noOfT<<")"<<endl;c = "t"+intToString(noOfT); 输出四元式wordStack.push(c); 新状态压栈noOfT++; 状态计数加一}return w;}char TMachine(char w){string operate,a,b,c;string state[5];w = FMachine(w); 调用F自动机while(w=='*'||w==''){ 是乘除号operate = w;cin>>w; 读取下一字符w = FMachine(w); 调用F自动机b = wordStack.pop(); 符号栈弹出a = wordStack.pop(); 两个操作字符cout<<"(\""<<operate<<"\","<<a<<","<<b<<",t"<<noOfT<<")"<<endl;c = "t"+intToString(noOfT); 输出四元式wordStack.push(c); 新状态压栈noOfT++; 状态计数加1}return w;}char FMachine(char w){ F自动机string theWord;if(w>='a'&&w<='z'||w>='A'&&w<='Z'){theWord = w; 当前字符是字母wordStack.push(theWord); 则压栈}else if(w == '('){ 是左括号cin>>w; 则读取下一字符w = EMachine(w); 调用E自动机if(w!=')'){ 不是右括号则输入有误,报错cerr<<"the input is wrong!"<<endl;exit(0);}}else{ 否则有误,报错cerr<<"the input is wrong!"<<endl;exit(0);}cin>>w; 读取下一字符return w;}string intToString(int a){ 整形变字符串形函数string d;char b='0',c;int i;while(a!=0){i = a%10;a = a10;c = (int)b + i;d = c + d;}return d;}Y=a+b*(c+(-d)*(e+f))Y=(a+b*(c-d*ef+g*(h-i*x*(j+k*(-l)*(j+k)))+w))H=(d+a-(c+b-q)*a)+c-(a+b*(c+d))六、总结通过这次实验,我对编译原理这门专业必修课有了进一步的深层次了解,把理论知识应用于实验中,也让我重新熟悉了C++语言的相关内容,加深了对C++语言知识的深化和用途的理解。