词法分析器、语法分析器试验报告
语法分析器实验报告

语法分析器的设计实验报告一、实验内容语法分析程序用LL(1) 语法分析方法。
首先输入定义好的文法书写文件(所用的文法可以用LL(1) 分析),先求出所输入的文法的每个非终结符是否能推出空,再分别计算非终结符号的FIRST 集合,每个非终结符号的 FOLLOW 集合,以及每个规则的 SELECT 集合,并判断任意一个非终结符号的任意两个规则的 SELECT 集的交集是不是都为空,如果是,则输入文法符合 LL(1) 文法,可以进行分析。
对于文法:G[E]:E->E+T|TT->T*F|FF->i|(E)分析句子 i+i*i 是否符合文法。
二、基本思想1、语法分析器实现语法分析是编译过程的核心部分,它的主要任务是按照程序的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行词法检查,为语义分析和代码生成作准备。
这里采用自顶向下的 LL(1) 分析方法。
语法分析程序的流程图如图5-4 所示。
开始读入文法有效?是 LL(1) 文法?判断句型结束报错语法分析程序流程图该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1) 文法(4)若是,构造分析表;(5)由句型判别算法判断输入符号串是为该文法的句型。
三、核心思想该分析程序有 15 部分组成:(1)首先定义各种需要用到的常量和变量;(2)判断一个字符是否在指定字符串中;(3)读入一个文法;(4)将单个符号或符号串并入另一符号串;(5)求所有能直接推出 & 的符号;(6)求某一符号能否推出‘& ’;(7)判断读入的文法是否正确;(8)求单个符号的 FIRST;(9)求各产生式右部的FIRST;(10)求各产生式左部的FOLLOW ;(11)判断读入文法是否为一个LL(1) 文法;(12)构造分析表 M ;(13)句型判别算法;(14)一个用户调用函数;(15)主函数;下面是其中几部分程序段的算法思想:1、求能推出空的非终结符集Ⅰ、实例中求直接推出空的empty 集的算法描述如下:void emp(char c){ 参数 c 为空符号char temp[10]; 定义临时数组int i;for(i=0;i<=count-1;i++) 从文法的第一个产生式开始查找{i f 产生式右部第一个符号是空符号并且右部长度为then 将该条产生式左部符号保存在临时数组将临时数组中的元素合并到记录可推出1,temp 中& 符号的数组empty中。
语法法分析实验报告

一、实验目的1. 理解语法分析的基本概念和原理。
2. 掌握语法分析器的构建方法。
3. 培养实际操作能力,提高编程水平。
二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.83. 开发工具:PyCharm三、实验内容1. 语法分析概述2. 词法分析3. 语法分析4. 实验实现四、实验步骤1. 语法分析概述(1)了解语法分析的定义、作用和意义。
(2)掌握语法分析的基本原理和流程。
2. 词法分析(1)编写词法分析器代码,将源代码分解成单词序列。
(2)实现词法分析器的各个功能,如:识别标识符、关键字、运算符等。
3. 语法分析(1)设计语法分析器,将单词序列转换为抽象语法树(AST)。
(2)实现语法分析器的各个功能,如:识别表达式、语句、函数等。
4. 实验实现(1)创建Python项目,导入相关库。
(2)编写词法分析器代码,实现单词序列的分解。
(3)编写语法分析器代码,实现抽象语法树的构建。
(4)测试语法分析器,验证其正确性。
五、实验结果与分析1. 词法分析结果实验中,我们成功地将源代码分解成单词序列,包括标识符、关键字、运算符等。
词法分析器的输出结果如下:```identifier: akeyword: intoperator: +identifier: boperator: =integer: 5```2. 语法分析结果通过语法分析器,我们将单词序列转换成抽象语法树。
以下是一个示例的抽象语法树:```Program├── Declaration│ ├── Type│ │ ├── Identifier│ │ └── Integer│ └── Identifier│ └── a└── Statement├── Expression│ ├── Identifier│ └── a└── Operator└── =└── Expression├── Identifier└── b└── Integer└── 5```从实验结果可以看出,我们的语法分析器能够正确地将源代码转换为抽象语法树。
词法分析器实验报告

词法分析器实验报告引言:词法分析器(Lexical Analyzer)是编译器的重要组成部分,其主要任务是将源代码转化为一个个独立的词法单元,为语法分析器提供输入。
在本次实验中,我们设计并实现了一个简单的词法分析器,通过对其功能和性能的测试,评估其在不同场景下的表现。
实验目的:1. 确定词法分析器的输入和输出要求;2. 通过构建适当的正则表达式规则,匹配不同类型的词法单元;3. 实现一个高效的词法分析器,确保在处理大型源代码时性能不受影响;4. 对词法分析器的功能和性能进行测试和评估。
实验过程:1. 设计词法分析器的接口:1.1 确定输入:源代码字符串。
1.2 确定输出:词法单元流,每个词法单元包含类型和对应的字符串值。
2. 构建正则表达式规则:2.1 识别关键字:根据编程语言的关键字列表构建正则表达式规则,将关键字与标识符区分开。
2.2 识别标识符:一般由字母、下划线和数字组成,且以字母或下划线开头。
2.3 识别数字:整数和浮点数可以使用不同的规则来识别。
2.4 识别字符串:使用引号(单引号或双引号)包裹的字符序列。
2.5 识别特殊符号:各类操作符、括号、分号等特殊符号需要单独进行规则设计。
3. 实现词法分析器:3.1 读取源代码字符串:逐个字符读取源代码字符串,并根据正则表达式规则进行匹配。
3.2 保存词法单元:将匹配到的词法单元保存到一个词法单元流中。
3.3 返回词法单元流:将词法单元流返回给调用者。
4. 功能测试:4.1 编写测试用例:针对不同类型的词法单元编写测试用例,包括关键字、标识符、数字、字符串和特殊符号。
4.2 执行测试用例:将测试用例作为输入传递给词法分析器,并检查输出是否和预期一致。
4.3 处理错误情况:测试词法分析器对于错误输入的处理情况,如非法字符等。
5. 性能测试:5.1 构建大型源代码文件:生成包含大量代码行数的源代码文件。
5.2 执行词法分析:使用大型源代码文件作为输入,测试词法分析器的性能。
词法分析器实验报告

词法分析器实验报告词法分析器设计一、二、实验目的:对C语言的一个子集设计并实现一个简单的词法分析器,掌握利用状态转换图设计词法分析器的基本方法。
利用该词法分析器完成对源程序字符串的词法分析。
输出形式是源程序的单词符号二元式的代码,并保存到文件中。
二、实验内容:1. 设计原理词法分析的任务:从左至右逐个字符地对源程序进行扫描,产生一个个单词符号。
理论基础:有限自动机、正规文法、正规式词法分析器(Lexical Analyzer) 又称扫描器(Scanner):执行词法分析的程序2. 词法分析器的功能和输出形式功能:输入源程序、输出单词符号程序语言的单词符号一般分为以下五种:关键字、标识符、常数、运算符,界符3. 输出的单词符号的表示形式:单词种别用整数编码,关键字一字一种,标识符统归为一种,常数一种,各种符号各一种。
4. 词法分析器的结构5. 状态转换图实现三、程序设计1.总体模块设计/*用来存储目标文件名*/string file_name;/*提取文本文件中的信息。
*/string GetText();/*获得一个单词符号,从位置i开始查找。
并且有一个引用参数j,用来返回这个单词最后一个字符在str的位置。
*/string GetWord(string str,int i,int& j);/*这个函数用来除去字符串中连续的空格和换行int DeleteNull(string str,int i);/*判断i当前所指的字符是否为一个分界符,是的话返回真,反之假*/bool IsBoundary(string str,int i);/*判断i当前所指的字符是否为一个运算符,是的话返回真,反之假*/bool IsOperation(string str,int i);/*此函数将一个pair数组输出到一个文件中*/void OutFile(vector<pair<int,string> > v);/*此函数接受一个字符串数组,对它进行词法分析,返回一个pair型数组*/vector<pair<int,string> > analyst(vector<string> vec);/*此函数判断传递的参数是否为关键字,是的话,返回真,反之返回假*/bool IsKey(string str);2.各模块设计(1).首先根据上面单词符号表及ID和NUM的正规定义式,构造出状态转换图;(2).定义相关的变量和数据结构。
词法分析器实验报告

词法分析器实验报告⼀、实验⽬的通过设计⼀个词法分析程序,对词法进⾏分析,加强对词法的理解,掌握对程序设计语⾔的分解和理解。
⼆、实验内容和要求在原程序中输⼊源代码对字符串表⽰的源程序从左到右进⾏扫描和分解根据词法规则识别出⼀个⼀个具有独⽴意义的单词符号以供语法分析之⽤发现词法错误,则返回出错信息在源程序中,⾃动识别单词,把单词分为五种,并输出对应的单词种别码。
1. 识别关键字:main if int for while do return break continue,该类的单词码为1.2. 识别标识符:表⽰各种名字,如变量名、数组名、函数名等,如char ch, int syn, token,sum,该类的单词码为2.3. 运算符:+、-、*、/、=、>、<、>=、<=、!=4. 分隔符:,、;、{、}、(、)5. 常数,例:123各种单词符号对应的种别码。
输出形式:⼆元式– (单词种别,单词⾃⾝的值)单词种别,表明单词的种类,语法分析需要的重要信息– 整数码关键字、运算符、界符:⼀符⼀码标识符:10, 常数:11单词⾃⾝的值– 标识符token、常数sum– 关键字、运算符、界符token三、实验⽅法、步骤及结果测试1.源程序#include <stdio.h>#include <string.h>char string[80],simbol[8],ch;int wordID,index,m,n,sum;char *rwtab[6]={"begin","if","then","while","do","end"};void scaner(void);main(){int index=0;printf("请输⼊代码,并以串#号键结束:\n");do{scanf("%c",&ch);string[index++]=ch;}while(ch!='#');index=0;do{scaner();switch(wordID)case11:printf("( %-10d%5d )\n",sum,wordID);break;case -1:printf("错误\n");return0;break;default:printf("( %-10s%5d )\n",simbol,wordID);break;}}while(wordID!=0);return0;}void scaner(void){sum=0;for(m=0;m<8;m++)simbol[m++]= NULL;ch=string[index++];m=0;while((ch=='')||(ch=='\n'))ch=string[index++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))//判断输⼊的字符是否为英⽂字母 {while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))){simbol[m++]=ch;ch=string[index++];}index--;wordID=10;for(n=0;n<6;n++)if(strcmp(simbol,rwtab[n])==0){wordID=n+1;break;}}else if((ch>='0')&&(ch<='9'))//判断输⼊的字符是否为数字{while((ch>='0')&&(ch<='9')){sum=sum*10+ch-'0';ch=string[index++];}index--;wordID=11;}else{switch(ch)//通过循环判断输⼊的字符是否为运算符{case'<':simbol[m++]=ch;ch=string[index++];if(ch=='='){wordID=22;simbol[m++]=ch;}else{wordID=20;index--;}break;case'>':simbol[m++]=ch;ch=string[index++];if(ch=='='){wordID=24;simbol[m++]=ch;else{wordID=23;index--;}break;case'+':simbol[m++]=ch;ch=string[index++];if(ch=='+'){wordID=17;simbol[m++]=ch;}else{wordID=13;index--;}break;case'-':simbol[m++]=ch;ch=string[index++];if(ch=='-'){wordID=29;simbol[m++]=ch;}else{wordID=14;index--;}break;case'!':ch=string[index++];if(ch=='='){wordID=21;simbol[m++]=ch;}else{wordID=31;index--;}break;case'=':simbol[m++]=ch;ch=string[index++];if(ch=='='){wordID=25;simbol[m++]=ch;}else{wordID=18;index--;}break;case'*':wordID=15;simbol[m++]=ch;break;case'/':wordID=16;simbol[m++]=ch;break;case'('://判断输⼊的字符是否为分隔符 wordID=27;simbol[m++]=ch;break;case')':wordID=28;simbol[m++]=ch;break;case'{':wordID=5;simbol[m++]=ch;break;case'}':wordID=6;simbol[m++]=ch;break;case';':wordID=26;simbol[m++]=ch;break;case'\"':wordID=30;simbol[m++]=ch;break;case'#':wordID=0;simbol[m++]=ch;break;case':':wordID=17;simbol[m++]=ch;break;default:wordID=-1;break;}}simbol[m++]='\0'; }四.运⾏结果及分析。
词法分析器实验报告

词法分析器实验报告词法分析器实验报告一、引言词法分析器是编译器中的重要组成部分,它负责将源代码分解成一个个的词法单元,为之后的语法分析提供基础。
本实验旨在设计和实现一个简单的词法分析器,以深入理解其工作原理和实现过程。
二、实验目标本实验的目标是设计和实现一个能够对C语言代码进行词法分析的程序。
该程序能够将源代码分解成关键字、标识符、常量、运算符等各种词法单元,并输出其对应的词法类别。
三、实验方法1. 设计词法规则:根据C语言的词法规则,设计相应的正则表达式来描述各种词法单元的模式。
2. 实现词法分析器:利用编程语言(如Python)实现词法分析器,将源代码作为输入,根据词法规则将其分解成各种词法单元,并输出其类别。
3. 测试和调试:编写测试用例,对词法分析器进行测试和调试,确保其能够正确地识别和输出各种词法单元。
四、实验过程1. 设计词法规则:根据C语言的词法规则,我们需要设计正则表达式来描述各种词法单元的模式。
例如,关键字可以使用'|'操作符将所有关键字列举出来,标识符可以使用[a-zA-Z_][a-zA-Z0-9_]*的模式来匹配,常量可以使用[0-9]+的模式来匹配等等。
2. 实现词法分析器:我们选择使用Python来实现词法分析器。
首先,我们需要读取源代码文件,并将其按行分解。
然后,针对每一行的代码,我们使用正则表达式进行匹配,以识别各种词法单元。
最后,我们将识别出的词法单元输出到一个结果文件中。
3. 测试和调试:我们编写了一系列的测试用例,包括各种不同的C语言代码片段,以测试词法分析器的正确性和鲁棒性。
通过逐个测试用例的运行结果,我们可以发现和解决词法分析器中的问题,并进行相应的调试。
五、实验结果经过多次测试和调试,我们的词法分析器能够正确地将C语言代码分解成各种词法单元,并输出其对应的类别。
例如,对于输入的代码片段:```cint main() {int a = 10;printf("Hello, world!\n");return 0;}```我们的词法分析器将输出以下结果:```关键字:int标识符:main运算符:(运算符:)运算符:{关键字:int标识符:a运算符:=常量:10运算符:;标识符:printf运算符:(常量:"Hello, world!\n"运算符:)运算符:;关键字:return常量:0运算符:;```可以看到,词法分析器能够正确地将代码分解成各种词法单元,并输出其对应的类别。
词法分析器的实验报告

词法分析器的实验报告词法分析器的实验报告引言:词法分析器是编译原理中的重要组成部分,它负责将源代码中的字符序列转换为有意义的词法单元,为后续的语法分析提供基础。
本实验旨在设计和实现一个简单的词法分析器,并对其进行测试和评估。
实验设计:1. 词法规则设计:在开始实验之前,我们首先需要设计词法规则,即定义源代码中的合法词法单元。
例如,对于一门类C的语言,我们可以定义关键字(如if、while、int等)、标识符、运算符(如+、-、*等)、分隔符(如()、{}等)等。
2. 有限自动机(DFA)的设计:基于词法规则,我们可以设计一个有限自动机,用于识别和分析源代码中的词法单元。
有限自动机是一个状态转换图,其中每个状态代表一种词法单元,而边表示输入字符的转换关系。
3. 实现代码:根据有限自动机的设计,我们可以使用编程语言(如Python、C++等)实现词法分析器的代码。
代码的主要功能包括读取源代码文件、逐个字符进行词法分析、识别和输出词法单元。
实验过程:1. 词法规则设计:我们以一门简单的算术表达式语言为例,设计了以下词法规则:- 数字:由0-9组成的整数或浮点数。
- 运算符:包括+、-、*、/等。
- 分隔符:包括括号()和逗号,。
- 标识符:以字母开头,由字母和数字组成的字符串。
2. 有限自动机(DFA)的设计:我们基于词法规则,设计了一个简单的有限自动机。
该自动机包含以下状态:- 初始状态:用于读取和识别源代码中的字符。
- 数字状态:用于识别和输出数字。
- 运算符状态:用于识别和输出运算符。
- 分隔符状态:用于识别和输出分隔符。
- 标识符状态:用于识别和输出标识符。
3. 实现代码:我们使用Python编程语言实现了词法分析器的代码。
代码主要包括以下功能:- 读取源代码文件。
- 逐个字符进行词法分析,根据有限自动机的设计进行状态转换。
- 识别和输出词法单元。
实验结果:我们对几个测试样例进行了词法分析,并对结果进行了评估。
语法分析器实验报告

词法分析器实验报告实验名称:语法分析器实验内容:利用LL(1)或LR(1)分析语句语法,判断其是否符合可识别语法。
学会根据状态变化、first、follow或归约转移思想构造状态分析表,利用堆栈对当前内容进行有效判断实验设计:1.实现功能可对一段包含加减乘除括号的赋值语句进行语法分析,其必须以$为终结符,语句间以;隔离,判断其是否符合语法规则,依次输出判断过程中所用到的产生式,并输出最终结论,若有错误可以报错并提示错误所在行数及原因2.实验步骤3.算法与数据结构a)LLtable:left记录产生式左端字符;right记录产生式右端字符;ln记录产生式右端字符长度Status:记录token分析情况Token:category,类型;value,具体内容b)根据LL(1)算法,手工构造分析表,并将内容用数组存储,便于查找c)先将当前语句的各token按序存储,当前处理语句最后一个token以#标记,作为输入流与产生式比较,堆栈中初始放入#,x,a为处理输入流中当前读头内容✓若top=a=‘#‘表示识别成功,退出分析程序✓若top=a!=‘#‘表示匹配,弹出栈顶符号,读头前进一个✓若top为i或n,但top!=a,出错,输出当前语句所在行,出错具体字符✓若top不为i或n,查预测分析表,若其中存放关于top产生式,则弹出top,将产生式右部自右向左压入栈内,输出该产生式,若其中没有产生式,出错,输出当前语句所在行,出错具体字符d)以;作为语句终结,每次遇到分号则处理之前语句并清空后预备下语句处理,当遇到$表示该段程序结束,停止继续处理4.分析表构造过程a)x->i=ee->e+t|e-t|tt->t*f|t/f|ff->(e)|i|nnote: i表示变量,n表示数字,!表示空串b)提取左公因子x->i=ee->ea|ta->+t|-tt->tb|fb->*f|/ff->(e)|i|nc)消除左递归x->i=ee->tcc->ac|!a->+t|-tt->fdd->bd|!b->*e|/ff->(e)|i|n5.类class parser{public:LLtable table[100][100]; //LL(1)表void scanner(); //扫描输入流中内容并分析parser(istream& in); //初始化,得到输入文件地址int getLine() const; //得到当前行数private:int match(); //分析语法stack <char> proStack; //分析堆栈void constructTable(); //建立LL(1)表int getRow(char ch); //取字符所在表中行int getCol(char ch); //取字符所在表中列istream* pstream; //输入流void insertToken(token& t); //插入当前tokenstatus getToken(token& t); //找到tokenint getChar(); //得到当前字符int peekChar(); //下一个字符void putBackChar(char ch); //将字符放回void skipChar(); //跳过当前字符void initialization(); //初始化堆栈等int line; //当前行数token tokens[1000]; //字符表int counter; //记录当前字符表使用范围}6.主要代码void parser::constructTable() //建立LL(1)表{for (int i=0;i<8;i++){for (int j=0;j<9;j++){table[i][j].left=' ';for (int k=0;k<3;k++)table[i][j].right[k]=' ';}}table[0][6].left='x';table[0][6].ln=3;table[0][6].right[0]='i';table[0][6].right[1]='=';table[0][6].right[2]='e';table[1][4].left='e';table[1][4].ln=2;table[1][4].right[0]='t';table[1][4].right[1]='c';table[1][6].left='e';table[1][6].ln=2;table[1][6].right[0]='t';table[1][6].right[1]='c';table[1][7].left='e';table[1][7].ln=2;table[1][7].right[0]='t';table[1][7].right[1]='c';table[2][0].left='c';table[2][0].ln=2;table[2][0].right[0]='a';table[2][0].right[1]='c';table[2][1].left='c';table[2][1].ln=2;table[2][1].right[0]='a';table[2][1].right[1]='c';table[2][5].left='c';table[2][5].ln=0;table[2][5].right[0]='!';table[2][8].left='c';table[2][8].ln=0;table[2][8].right[0]='!';table[3][0].left='a';table[3][0].ln=2;table[3][0].right[0]='+'; table[3][0].right[1]='t'; table[3][1].left='a';table[3][1].ln=2;table[3][1].right[0]='-'; table[3][1].right[1]='t'; table[4][4].left='t';table[4][4].ln=2;table[4][4].right[0]='f'; table[4][4].right[1]='d'; table[4][6].left='t';table[4][6].ln=2;table[4][6].right[0]='f'; table[4][6].right[1]='d'; table[4][7].left='t';table[4][7].ln=2;table[4][7].right[0]='f'; table[4][7].right[1]='d'; table[5][0].left='d';table[5][0].ln=0;table[5][0].right[0]='!'; table[5][1].left='d';table[5][1].ln=0;table[5][1].right[0]='!'; table[5][2].left='d';table[5][2].ln=2;table[5][2].right[0]='b'; table[5][2].right[1]='d'; table[5][3].left='d';table[5][3].ln=2;table[5][3].right[0]='b'; table[5][3].right[1]='d'; table[5][5].left='d';table[5][5].ln=0;table[5][5].right[0]='!'; table[5][8].left='d';table[5][8].ln=0;table[5][8].right[0]='!'; table[6][2].left='b';table[6][2].ln=2;table[6][2].right[0]='*'; table[6][2].right[1]='f'; table[6][3].left='b';table[6][3].ln=2;table[6][3].right[0]='/'; table[6][3].right[1]='f'; table[7][4].left='f';table[7][4].ln=3;table[7][4].right[0]='(';table[7][4].right[1]='e';table[7][4].right[2]=')';table[7][6].left='f';table[7][6].ln=1;table[7][6].right[0]='i';table[7][7].left='f';table[7][7].ln=1;table[7][7].right[0]='n';}int parser::match() //分析语法{ofstream ofs("out.txt",ios::app);char a;int i=0;for (int p=0;p<counter;p++){cout<<tokens[p].value;ofs<<tokens[p].value;}cout<<endl;ofs<<endl<<"ANALYSIS:"<<endl;while(1){if(tokens[i].category=='n' || tokens[i].category=='i')a=tokens[i].category;elsea=(tokens[i].value)[0];if(a==proStack.top()){if(a=='#'){cout<<"This is valid!"<<endl<<endl;ofs<<"This is valid!"<<endl<<endl;return 0;}else{proStack.pop();i++;}}else{if(proStack.top() =='n'|| proStack.top() =='i'){if(a!='#'){cout<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;}else{cout<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;}cout<<"This is invalid!"<<endl<<endl;ofs<<"This is invalid!"<<endl<<endl;return 0;}else{if((table[getRow(proStack.top())][getCol(a)]).left!=' '){char pst=proStack.top();int n=table[getRow(pst)][getCol(a)].ln;int k=0;ofs<<table[getRow(pst)][getCol(a)].left<<"->"<<table[getRow(pst)][getCol(a)].right[0]<<table[getRow(pst)][g etCol(a)].right[1]<<table[getRow(pst)][getCol(a)].right[2]<<endl;proStack.pop();while (n>0){//cout<<n<<" "<<table[getRow(pst)][getCol(a)].right[n-1]<<endl;proStack.push(table[getRow(pst)][getCol(a)].right[n-1]);n--;}}else{if(a!='#'){cout<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): "<<a<<" cannot be matched"<<endl;}else{cout<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;ofs<<"ERROR(LINE "<<getLine()<<" ): Unexpected ending"<<endl;}cout<<"This is invalid!"<<endl<<endl;ofs<<"This is invalid!"<<endl<<endl;return 0;}}}}}实验结果:●输入(in.txt)●输出1输出2(out.txt)实验总结:原本以为处理四则运算赋值将会很困难,但在使用LL(1)后发现,思路还是挺清晰简单的,但在实验过程中,由于LL(1)不能出现左递归和左公因子,不得不将其消除,原本简单的产生式一下变多了,而在产生式理解上也没有原来直观,不过其状态复杂度没有LR高,故仍选择该方法。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
词法分析器、语法分析器试验报告一.程序思路1.词法分析器对输入的程序进行分析,将关键字,保留字与系统标识符分开,并对其属性进行说明。
建立数组,将单词读入,对单词的ASCII码进行判断,将在ASCII码值在一定区间进行区分(使用if语句来判断),分开来后,对其所在ASCII值区间的不同,给予以不同的属性(比如:系统保留字…),词法分析器完成后要能识别+,-,=等字符。
2.语法分析器对输入的程序语句进行分析。
对每个非终结点定义单个函数,定义了它的后继节点。
然后用一个构造来的函数,使定义的后继节点符合语法,否则报错。
二.源程序cifafenxi:#include"string.h"#include"iostream.h"#include"stdio.h"#include"conio.h"#define OK 1#define……#define……class word{ int ch;char code[50][50];public://word();int scan();int letter(int ch);int digit(int ch);int flag(int ch);int keyword(char * ch);int alpha(char * ch);int judge(char * ch);};int word::letter(int ch) //字符判断int word::alpha(char * ch) //字符属性设定int word::digit(int ch) //数字判断int word::flag(int ch){if(((ch>='0')&&(ch<='9'))||((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||(ch=='+')||(ch=='-')||(ch=='*')||(ch=='/')||(ch=='=')||(ch=='==')||(ch=='%')||(ch=='<')||(ch=='>')||(ch=='(')||(ch==')'))return(1);else return(0);}int word::keyword(char * ch) //关键字判断{if((ch[0]=='i')&&(ch[1]=='n')&&(ch[2]=='t')&&(ch[3]==0)){ cout<<"\n"<<"The [int] is a keyword !"<<"\n"; return(INT); }if((ch[0]=='c')&&(ch[1]=='h')&&(ch[2]=='a')&&(ch[3]=='r')&&(ch[4]==0)){ cout<<"\n"<<"The [char] is a keyword !"<<"\n"; return(CHAR); }……………………………………………………{ cout<<"\n"<<"It is a keyword [if] !"<<"\n"; return(SWITCH); }return(0);}int word::judge(char * ch) //数字进位制判断if((ch[0]=='0')&&((ch[1]>='0')&&(ch[1]<='7'))){ cout<<"\n"<<"This is a OTC number, OTC value is"<<"["<<ch<<"] !"<<"\n";return(OTC); }……………………………………………………return(1);}int word::scan(){ int i=0,j=0,x=1;cout<<"Please input !"<<"\n"; ch=getc(stdin);while((ch==' ')||(ch==10))ch=getc(stdin);if((flag(ch)==NO)){ cout<<"\n"<<"ERROR"<<"\n"; return(ERROR); }ungetc(ch,stdin);while(x) { ch=getc(stdin); if((letter(ch)==YES)){ i=0; while (letter(ch)||digit(ch)) {code[j][i]=ch;ch=getc(stdin);i++; }code[j][i]=0;if(keyword(code[j])==0) {if(alpha(code[j]))cout<<"The identifier's ID is ["<<j<<"] !"<<"\n";} j++;if(ch==10)x=0; }if((digit(ch)==YES)){ i=0;while(digit(ch)||(ch=='x')||((ch>='a')&&(ch<='f'))){code[j][i]=ch;ch=getc(stdin);i++;}code[j][i]=0;judge(code[j]);cout<<"The number's ID is ["<<j<<"] !"<<"\n";j++;if(ch==10)x=0; }if(ch==':'){ i=0; code[j][i]=ch; ch=getc(stdin); if(ch=='='){ code[j][i++]=ch;cout<<"The ["<<"code[j]"<<" is (ASSIGN-OP, -) ."; j++; ch=getc(stdin); if(ch==10)x=0; }} switch(ch){case'+':{ i=0; code[j][i]=ch; code[j][i++]=0; cout<<"\n"<<"The ["<<char(ch)<<"] is a identifier (PLUS-OP, AND) ."<<"\n"; } //ch=getc(stdin); if(ch==59)ungetc(ch,stdin); }break;case'-':{ i=0; code[j][i]=ch; code[j][i++]=0; cout<<"\n"<<"The ["<<char(ch)<<"] is a identifier (MINUS-OP, SUB) ."<<"\n"; } //ch=getc(stdin);if(ch==59)ungetc(ch,stdin); }break;……………………………………………………break;case')':{ i=0; code[j][i]=ch; code[j][i++]=0; cout<<"\n"<<"The ["<<char(ch)<<"] is a identifier (RELATION-OP, RP) ."<<"\n";}// ch=getc(stdin); if(ch==59)ungetc(ch,stdin); }break;}if(ch==10)x=0;}return(OK);}int main(){char ch1;word word;while(ch1!='q'){word.scan();ch1=getch();}return(OK);}yufafenxi:#include"string.h"#include"iostream.h"#include"stdio.h"#include"conio.h"class word{ int ch;char code[MAX][MAX];public:// word ();int scan();int letter(int ch);int digit(int ch);int right(int ch);int keyword(char * ch);int alpha(char * ch);int judge(char * ch);int yufa(int ch);int match(int ch);int word _e();int word _t();int word _f();int word _s();int word _c();};int word::letter(int ch)……int word::alpha(char * ch)……int word::digit(int ch)……int word::right(int ch)……int word::match(int ch){ int i=0;int j=0;int x=1;ch=getc(stdin);while((ch==' ')||(ch==10))ch=getc(stdin);if((isright(ch)==NO)){ cout<<"\n"<<"ERROR"<<"\n"; return(ERROR); }ungetc(ch,stdin);while(x){ ch=getc(stdin); if((isletter(ch)==YES)) { i=0; while (isletter(ch)||isdigit(ch)){ code[j][i]=ch; ch=getc(stdin);i++; }code[j][i]=0;ungetc(ch,stdin);if(ch==10)x=0;j++;return(iskeyword(code[j-1]));}if((isdigit(ch)==YES)){ i=0; while(isdigit(ch)||(ch=='x')||((ch>='a')&&(ch<='f'))){code[j][i]=ch;ch=getc(stdin);i++; }code[j][i]=0;ungetc(ch,stdin); j++;if(ch==10)x=0;return(judge(code[j-1])); } if(ch==':'){ i=0; code[j][i]=ch; ch=getc(stdin); if(ch=='='){ code[j][i++]=ch; code[j][i++]=0; j++; return(ASSIGN);} }switch(ch){ case'+':{ i=0; code[j][i]=ch; code[j][i++]=0; return(AND); }case'-':{ i=0; code[j][i]=ch; code[j][i++]=0; return(SUB); } ……………………………………………………} i f(ch==10)x=0;}return(OK);}int word:: word _t()……int word:: word _f()……int word::word_s()……int main(){char ch1;word word;while(ch1!='q'){clrscr();cout<<"Please Input !"<<"\n";lookhead=word.scan();word.fun_s();ch1=getch();}return(OK);}三.小节——心得体会这次小程序的编写让我对编译程序的工作有了个大概的了解,让我的编译程序的原理及设计有了长足的进步,使我明白和更好的体会到了编译程序的作用。