编译原理_词法分析 实验报告
编译原理词法分析实验报告
编译原理词法分析实验报告实验名称:词法分析器的设计与实现一、实验目的: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对象。
五、实验总结:通过本次实验,我熟悉了编译原理中词法分析的基本概念和原理,并掌握了正则表达式的使用方法。
我成功完成了一个简单的词法分析器的设计与实现,实现了源代码中每个词法单元的识别与输出。
这次实验对我深化了对编译原理中词法分析的理解,并提高了我的编程能力。
编译原理-词法语法分析实验报告
编译原理词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求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)……如图所示:五、总结:词法分析的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
编译原理词法分析实验报告
编译原理词法分析实验报告实验一词法分析一、实验目的通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
二、实验内容(1)功能描述:该程序是实现一个词法分析器,词法分析器的功能是输入源程序,输出单词符号。
词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。
本实验中,采用的是将单词分为五种的方法。
识别关键字:main、if、int、for、while、do、return、break、continue;单词种别码为1。
标识符:单词种别码为2。
常数:为无符号整形数;单词种别码为3。
运算符:包括:+、-、*、/、=、>、<、>=、<=、!= ;单词种别码为4。
分隔符:包括:,、;、{、}、(、);单词种别码为5。
(2)程序结构描述:输入:从控制台输入一段源程序代码,对输入的代码进行词法分析,处理:分离出关键字、标识符、数值、运算符和界符。
输出:在词法分析结果表中输出每个单词所在行号、类型以及它所对应的编码。
其中,编码是自定义的,一种类型对应一个编码。
词法分析结果显示在控制台上。
(3)程序设计思路1、定义编码表,用ArrayList集合存放单词,如:关键字、运算符、分界符。
这三种单词是固定的,标示符和数字这两种单词不存放在集合中。
编码表是固定的,只需要初始化一次就够了,所以将集合定义为static类型,使其在类加载时,进行一次初始化。
2、static char allstr[] = new char[100000];该数组用于存储用户从控制台输入的所有字符。
3、//从键盘获取一个一个的字符public char Getchar() {try {ch = (char) System.in.read();} catch (Exception e) {e.printStackTrace();}return ch;}4、用while循环遍历allstr数组中存放的字符,判断分离出关键字、标示符、数字、运算符、标示符。
编译原理实验报告——词法分析器(内含源代码)
编译原理实验(一)——词法分析器一.实验描述运行环境:vc++2008对某特定语言A ,构造其词法规则。
该语言的单词符号包括:12状态转换图3程序流程:词法分析作成一个子程序,由另一个主程序调用,每次调用返回一个单词对应的二元组,输出标识符表、常数表由主程序来完成。
二.实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
三.实验任务编制程序实现要求的功能,并能完成对测试样例程序的分析。
四.实验原理char set[1000],str[500],strtaken[20];//set[]存储代码,strtaken[]存储当前字符char sign[50][10],constant[50][10];//存储标识符和常量定义了一个Analyzer类class Analyzer{public:Analyzer(); //构造函数 ~Analyzer(); //析构函数int IsLetter(char ch); //判断是否是字母,是则返回 1,否则返回 0。
int IsDigit(char ch); //判断是否为数字,是则返回 1,否则返回 0。
void GetChar(char *ch); //将下一个输入字符读到ch中。
void GetBC(char *ch); //检查ch中的字符是否为空白,若是,则调用GetChar直至ch进入一个非空白字符。
void Concat(char *strTaken, char *ch); //将ch中的字符连接到strToken之后。
int Reserve(char *strTaken); //对strTaken中的字符串查找保留字表,若是一个保留字返回它的数码,否则返回0。
void Retract(char *ch) ; //将搜索指针器回调一个字符位置,将ch置为空白字符。
编译原理词法分析实验
编译原理词法分析实验一、实验目的本实验旨在通过编写一个简单的词法分析器,了解编译原理中词法分析的基本原理和实现方法。
二、实验材料1. 计算机编程环境2. 编程语言三、实验步骤1. 了解词法分析的概念和作用。
词法分析是编译器中的第一个阶段,它的主要任务是将源代码中的字符序列转化为有意义的标识符,如关键字、操作符、常量和标识符等。
2. 设计词法分析器的流程和算法。
词法分析器的主要原理是通过有限状态自动机来识别和提取标识符。
在设计过程中,需考虑各种可能出现的字符序列,并定义相应的状态转移规则。
3. 根据设计的流程和算法,使用编程语言编写词法分析器的代码。
4. 编译并运行词法分析器程序,输入待分析的源代码文件,观察程序的输出结果。
5. 分析输出结果,检查程序是否正确地提取了源代码中的标识符。
四、实验结果经过词法分析器的处理,源代码将被成功地转化为有意义的标识符。
结果可以通过以下几个方面来验证:1. 关键字和操作符是否被正确识别和提取。
2. 常量和标识符是否被正确识别和提取。
3. 检查程序的错误处理能力,如能否发现非法字符或非法标识符。
4. 输出结果是否符合预期,可与自己编写的语法规则进行对比。
5. 对于特殊情况,如转义字符等是否正确处理。
五、实验总结通过本次实验,我深入了解了编译原理中词法分析的重要性和基本原理。
编写词法分析器的过程中,我学会了使用有限状态自动机来识别和提取标识符,并通过实践巩固了相关知识。
此外,我还对源代码的结构有了更深入的了解,并且掌握了如何运用编程语言来实现词法分析器。
通过本次实验,我不仅提升了自己的编程技术,也对编译原理有了更深入的认识和理解。
六、实验心得通过实验,我深刻体会到了词法分析在编译过程中的重要性。
合理设计和实现词法分析器,可以大大提高编译器的效率和准确性。
同时,通过编写词法分析器的代码,我不仅锻炼了自己的编程能力,还提升了对编译原理的理解和掌握。
这次实验让我更加深入地了解了编译原理中的词法分析,也为我今后在编程领域的发展打下了坚实的基础。
(完整word版)编译原理词法分析程序实现实验报告
(完整word版)编译原理词法分析程序实现实验报告实验一词法分析程序实现一、实验内容选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来。
输入:由无符号数和+,-,*,/, ( , ) 构成的算术表达式,如1.5E+2-100。
输出:对识别出的每一单词均单行输出其类别码(无符号数的值暂不要求计算)。
二、设计部分因为需要选取无符号数的算术四则运算中的各类单词为识别对象,要求将其中的各个单词识别出来,而其中的关键则为无符号数的识别,它不仅包括了一般情况下的整数和小数,还有以E为底数的指数运算,其中关于词法分析的无符号数的识别过程流程图如下:GOTO 1:(完整word版)编译原理词法分析程序实现实验报告GOTO 2:三、源程序代码部分#include <stdio.h>#include<stdlib.h>#include <math.h>#define MAX 100#define UNSIGNEDNUMBER 1#define PLUS 2#define SUBTRACT 3#define MULTIPLY 4#define DIVIDE 5#define LEFTBRACKET 6#define RIGHTBRACKET 7#define INEFFICACIOUSLABEL 8#define FINISH 111int count=0;int Class;void StoreType();int Type[100];char Store[20]={'\0'};void ShowStrFile();//已经将要识别的字符串存在文件a中void Output(int a,char *p1,char *p2);//字符的输出过程int Sign(char *p);//'+''-''*''/'整体识别过程int UnsignedNum(char *p);//是否适合合法的正整数0~9int LegalCharacter(char *p);//是否是合法的字符:Sign(p)||UnsignedNum(p)||'E'||'.' void DistinguishSign(char *p);//'+''-''*''/'具体识别过程void TypyDistinguish();//字符的识别过程void ShowType();//将类别码存储在Type[100]中,为语法分析做准备void ShowStrFile()//已经将要识别的字符串存在文件a中{FILE *fp_s;char ch;if((fp_s=fopen("a.txt","r"))==NULL){printf("The FILE cannot open!");exit(0);}elsech=fgetc(fp_s);while(ch!=EOF){putchar(ch);ch=fgetc(fp_s);}printf("\n");}void StoreStr()//将文件中的字符串存储到数组Store[i] {FILE *fp=fopen("a.txt","r");char str;int i=0;while(!feof(fp)){fscanf(fp,"%c",&str);if(str=='?'){Store[i]='\0';break;}Store[i]=str;i++;}Store[i]='\0';}void ShowStore(){int i;for (i=0;Store[i]!='\0';i++)printf("%c",Store[i]);printf("\n");}void Output(int a,char *p1,char *p2){printf("%3s\t%d\t%s\t","CLASS",a,"VALUE");while(p1<=p2){printf("%c",*p1);p1++;}printf("\n");}int Sign(char *p){char ch=*p;if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')') return 1;elsereturn 0;}int UnsignedNum(char *p){char ch=*p;if('0'<=ch&&ch<='9')return 1;elsereturn 0;}int LegalCharacter(char *p){char ch=*p;if(Sign(p)||UnsignedNum(p)||ch=='E'||ch=='.')。
编译原理词法分析报告
实验一:词法分析一、实验目的:1、通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
2、编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本关键字、标识符、常数、运算符、分隔符五大类。
并依次输出各个单词的内部编码及单词符号自身值。
(遇到错误时可显示“Error”,然后跳过错误部分继续显示)二、实验预习提示1、词法分析器的功能和输出格式词法分析器的功能是输入源程序,输出单词符号。
词法分析器的单词符号常常表示成以下的二元式(单词种别码,单词符号的属性值)。
本实验中,采用的是一类符号一种别码的方式。
2、单词的BNF表示<标识符>-> <字母><字母数字串><字母数字串>-><字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε<无符号整数>-> <数字><数字串><数字串>-> <数字><数字串> |ε<加法运算符>-> +<减法运算符>->-<大于关系运算符>->><大于等于关系运算符>-> >=3、“超前搜索”方法词法分析时,常常会用到超前搜索方法。
如当前待分析字符串为“a>+”,当前字符为’>’,此时,分析器到底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。
于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。
但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。
在分析标识符,无符号整数等时也有类似情况。
编译原理实验词法分析实验报告
编译技术实验报告实验题目:词法分析学院:信息学院专业:计算机科学与技术学号:姓名:一、实验目的(1)理解词法分析的功能;(2)理解词法分析的实现方法;二、实验内容PL0的文法如下‘< >’为非终结符。
‘::=’ 该符号的左部由右部定义,可读作“定义为”。
‘|’ 表示‘或’,为左部可由多个右部定义。
‘{ }’ 表示花括号内的语法成分可以重复。
在不加上下界时可重复0到任意次数,有上下界时可重复次数的限制。
‘[ ]’ 表示方括号内的成分为任选项。
‘( )’ 表示圆括号内的成分优先。
上述符号为“元符号”,文法用上述符号作为文法符号时需要用引号‘’括起。
〈程序〉∷=〈分程序〉.〈分程序〉∷= [〈变量说明部分〉][〈过程说明部分〉]〈语句〉〈变量说明部分〉∷=VAR〈标识符〉{,〈标识符〉}:INTEGER;〈无符号整数〉∷=〈数字〉{〈数字〉}〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}〈过程说明部分〉∷=〈过程首部〉〈分程序〉{;〈过程说明部分〉};〈过程首部〉∷=PROCEDURE〈标识符〉;〈语句〉∷=〈赋值语句〉|〈条件语句〉|〈过程调用语句〉|〈读语句〉|〈写语句〉|〈复合语句〉|〈空〉〈赋值语句〉∷=〈标识符〉∶=〈表达式〉〈复合语句〉∷=BEGIN〈语句〉{;〈语句〉}END〈条件〉∷=〈表达式〉〈关系运算符〉〈表达式〉〈表达式〉∷=〈项〉{〈加法运算符〉〈项〉}〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}〈因子〉∷=〈标识符〉|〈无符号整数〉|'('〈表达式〉')'〈加法运算符〉∷=+|-〈乘法运算符〉∷=*〈关系运算符〉∷=<>|=|<|<=|>|>=〈条件语句〉∷=IF〈条件〉THEN〈语句〉〈字母〉∷=a|b|…|X|Y|Z〈数字〉∷=0|1|2|…|8|9实现PL0的词法分析三、实验分析与设计PL0词法分析程序是一个独立的过程,其功能是为语法语义分析提供单词,把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析。
编译原理词法分析程序设计实验报告
编译原理词法分析程序设计实验报告【实验目的】1.了解词法分析的主要任务。
2.熟悉编译程序的编制。
【实验内容】根据某文法,构造一基本词法分析程序。
找出该语言的关键字、标识符、整数以及其他一些特殊符号,给出单词的种类和值。
【实验要求】1.构造一个小语言的文法类C小语言文法(以EBNF表示)<程序>::=<分程序>{<分程序>} . <分程序>::=<标识符>’(’<变量说明部分>{,<变量说明部分>}’)’<函数体> <变量说明部分>::=int<标识符>{,<标识符>} <函数体>::=’{’[<变量说明部分>;]<语句序列>’}’ <语句序列>::=<语句序列>;<语句>|<语句> <语句>::=<赋值语句> |<条件语句>|<循环语句>|<函数调用语句> <赋值语句>::=<标识符>=<表达式> <表达式>::=[+|-]<项>{<加法运算符><项>} <项>::=<因子>{<乘法运算符><因子>} <因子>:=<标识符>|<无符号整数> <加法运算符>::= +|- <乘法运算符>::= *|/ <条件语句>::=if<条件>’{’<语句序列>’}’[else’{’<语句序列>’}’] <条件>::=<表达式><关系运算符><表达式> <关系运算符>::= ==|!=|>|<|>=|<= <循环语句>::=for’(’<表达式>;<条件>;<表达式>’)’ ’{’<语句序列>’}’ <函数调用语句>::=<标识符>’(’<标识符>{,<标识符>}|<空>’)’<标识符>::=<字母>{<字母>|<数字>} <无符号整数>::=<数字>{<数字>} <字母>::=a|b|c|…|X|Y|Z <数字>::=0|1|2|…|8|9单词分类情况关键字:int if else for标识符:以字母开头的字母和数字的组合关系运算符:==|!=|>|<|>=|<=加法运算符:+|- 乘法运算符:*|/界符:,;{ } ( )2.设计单词的输出形式,单词的种类和值的表示方法种别码单词值如:1 int3. 编写词法分析程序cffx.c实现基本的词法分析器,能够分析关键字、标识符、数字、运算符(需要有“==”或“:=”之类需要超前搜索的运算符)以及其他一些符号。
编译原理词法分析,语法分析实验报告
编译原理实验报告一.LL(1)文法分析1.设计要求(1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止;(2)输入已知文法,由程序自动生成它的LL(1)分析表;(3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。
2.分析该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;(5)由总控算法判断输入符号串是否为该文法的句型。
3.流程图开始读入文法有效?是是LL(1)文法?是判断句型报错结束4.源程序/*******************************************语法分析程序作者:xxx学号:xxx********************************************/#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘|’后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果‘|’后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/ char grammer(char *t,char *n,char *left,char right[50][50]) {char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的‘^ ’一并并入目串;type=2,源串中的‘^ ’不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由‘^ ’推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出‘^ ’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/ printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为‘^ ’,报错*/ printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/ void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/ temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("\nS:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();}}}5.执行结果(1)输入一个文法(2)输入一个符号串(3)再次输入一个符号串,然后退出程序二.词法分析一、问题描述识别简单语言的单词符号识别简单语言的基本字、标识符、无符号整数、运算符和界符。
《编译原理》课程实验报告(词法分析)完整版
《编译原理》课程实验报告题目词法分析专业计算机指导教师签名华东理工大学信息学院计算机系2013年4月10日一.实验序号:《编译原理》第一次实验二.实验题目:词法分析三.实验日期:2013.3.27-2013.4.10四.实验环境(操作系统,开发语言)操作系统:Windows开发语言:C五.实验要求●修改词法:1)将标识符的词法改为“以大写字母或小写字母开头,后面可以跟大写字母或小写字母或数字或下划线”。
把while ((isalpha(buffer))||(isdigit(buffer)))改成while ((isalpha(buffer))||(isdigit(buffer))||buffer==’_’)2)将<条件>中的表示相等关系的单词“=”改为“= =”char *relation[6]={"<","<=","=",">",">=","<>"};把其中的=改成==即可3)将原来无小数的数改为可以有小数的数把while (isdigit(buffer))改成while (isdigit(buffer)||buffer==’.’)●用C语言开发词法分析程序。
读入用PL/0语言编写的测试用例源程序,将识别出的一个个单词组成单词流依序同时输出到屏幕和文件中。
六.实验步骤1)根据修改词法后的PL/0语言编写测试用例源程序。
2)用C语言编写词法分析程序。
读入PL/0语言的测试用例源程序,进行词法分析,将识别出的一个个单词组成单词流依序同时输出到屏幕和文件中。
3)设立断点,单步运行词法分析程序,依次单个输出单词。
分析和理解词法分析程序,解释词法分析程序中的数据和变量变化的原因和输出结果。
七.实验结果(测试用例源程序,运行结果部分截图,词法分析函数主要部分源程序PL0程序:const a=6,b=81;var x,y;procEdure p;procedure q;x:=2;beginx:=1;write(x);end;begincall p;end.C程序:#include <stdio.h>#include <ctype.h>#include <malloc.h>#include <stdlib.h>#include <string.h>#define NULL 0FILE *fp;char cbuffer;char*key[19]={"auto","break","case","char","const","continue","default","do"," double","else","enum","extern","float","for","goto","if","int","long","register"};char *border[6]={",",";","{","}","(",")"};char *arithmetic[4]={"+","-","*","/"};char *relation[6]={"<","<=","=",">",">=","<>"};char *consts[11]={"0","1","2","3","4","5","6","7","8","9","."};char *label[20];int labelnum=0;int search(char searchchar[],int wordtype){ int i=0;switch (wordtype) {case 1:for (i=0;i<=18;i++){ if (strcmp(key[i],searchchar)==0){return(1);}}return(0);break;case 2:{for (i=0;i<=5;i++){ if (strcmp(border[i],searchchar)==0)return(i+1);} return(0);}break;case 3:{for (i=0;i<=3;i++){ if (strcmp(arithmetic[i],searchchar)==0){ return(1);}}return(0);}break;case 4:{for (i=0;i<=5;i++){ if (strcmp(relation[i],searchchar)==0){ return(1);}}return(0);}break;case 5:{for (i=0;i<=10;i++){ if (strcmp(consts[i],searchchar)==0){return;}}return(0);}break;}}char alphaprocess(char buffer){ int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))){ alphatp[++i]=buffer;buffer=fgetc(fp);}alphatp[i+1]='\0';atype=search(alphatp,1);if(atype==1){printf("%s \t 保留字\n",alphatp);}//结束if(atype==0){printf("%s \t 标示符\n",alphatp);}return(buffer);}char digitprocess(char buffer){ int i=-1;char digittp[20];int dtype;while (isdigit(buffer)){ digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';dtype=search(digittp,5);if(dtype==1)printf("%s \t 数字\t %s\n",digittp,digittp);return(buffer);}char otherprocess(char buffer){ int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';otype=search(othertp,3);if (otype==1){ printf("%s \t 运算符\n",othertp);buffer=fgetc(fp);goto out;}otype=search(othertp,4);if (otype==1){ buffer=fgetc(fp);othertp[1]=buffer;othertp[2]='\0';otypetp=search(othertp,4);if (otypetp==1){ printf("%s \t 运算符\n",othertp);goto out;}elseothertp[1]='\0';printf("%s \t 运算符\n",othertp);goto out;}if (buffer==':'){ buffer=fgetc(fp);if (buffer=='=')printf(":= \t 运算符\n");buffer=fgetc(fp);goto out;}else{ if (otype=search(othertp,2)){ printf("%s \t 界符\n",othertp);buffer=fgetc(fp);goto out;}}if ((buffer!='\n')&&(buffer!=' '))printf("%c error,not a word\n",buffer);buffer=fgetc(fp);out: return(buffer);}void main(){if ((fp=fopen("example.txt","r"))==NULL)printf("error");else{cbuffer = fgetc(fp);while (cbuffer!=EOF){if (isalpha(cbuffer))cbuffer=alphaprocess(cbuffer);else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer);elsecbuffer=otherprocess(cbuffer);}printf("over\n");getchar();}}八.实验体会(词法分析程序修改的地方,解决问题的方法、心得体会等)通过本次试验,了解了词法分析的主要步骤,就是把标识符,保留字区分,并且能识别出空格,并把数据能从文件中读出来,主要识别标识符和保留字,主要通过比较参照一个事先建好的数组,里面包含了所有的保留字,不在其中的便是标识符。
《编译原理》课程实验报告(词法分析)
信息科学与工程学院__《编译原理》_实验报告系别计算机科学与工程专业计算机科学与应用班级_____计122_______学号_____10123544_____姓名_____ 陈柏君_________指导教师金登男2014学年第二学期1.实验题目:词法分析2.实验日期:2015.4.9-2015.4.163.实验环境(操作系统,开发语言)操作系统:Windows开发语言:C4.实验要求4.1.用C语言开发词法分析程序PL0Compiler。
4.2.修改PL/0词法,将其定义为一种新的语言,例如称其为PL/1语言,并完成PL/1语言的词法分析程序。
5.实验步骤5.1.用PL/0语言编写PL/0测试用例源程序,将其命名为Test0.pl。
5.2.用C语言开发PL/0词法分析程序PL0Compiler。
PL0Compiler读入Test0.pl,识别出一个个单词,并将这些单词流依序同时输出到屏幕和文件中。
被输出的每个单词应包括(1)单词序号(2)单词字符串(3)单词类型(4)单词值(如果是标识符,其值是字符串;如果是数,其值是数值;如果是符号,其值是ASCII代码…)在程序开发过程中,应设立断点,单步运行词法分析程序,依次输出一个个单词。
分析和理解词法分析程序,解释词法分析程序中的数据和变量变化的原因和输出结果。
5.3.研究其他程序设计语言,找出与PL/0词法不同的构词法则(例如C语言的标识符的组成规则与PL/0标识符的组成规则有所不同)。
据此修改PL/0的某些词法(例如,将PL/0标识符组成规则修改为C语言的标识符的组成规则),将其定义为一种新的语言,例如称其为PL/1语言。
5.4.用PL/1语言编写PL/1测试用例源程序,将其命名为Test1.pl。
5.5.开发PL/1词法分析程序PL1Compiler。
(可通过修改原PL0Compiler,实现PL/1语言的词法分析功能)。
5.6.PL1Compiler读入Test1.pl,识别出一个个单词,并将这些单词流依序同时输出到屏幕和文件中。
编译原理词法分析器实验报告
编译原理词法分析器实验报告1. 引言编译原理是计算机科学中的重要概念,它涉及将高级语言程序转换为计算机可执行的低级指令。
词法分析是编译过程中的第一个阶段,它负责将源代码分解为词法单元,为后续的语法分析做准备。
本实验旨在设计和实现一个基本的词法分析器,以了解词法分析的原理和实际应用。
2. 实验目标本实验的主要目标是实现一个基本的词法分析器,能够识别并提取源代码中的各种词法单元。
具体而言,我们将设计一个针对某种编程语言的词法分析器,能够识别关键字、标识符、算术运算符、括号、常量等。
3. 实验环境为了完成本实验,我们需要使用以下工具和环境:•一种编程语言,例如Python、Java或C++•一个文本编辑器,例如Visual Studio Code或Sublime Text•一个命令行终端4. 实验步骤4.1 定义词法规则首先,我们需要定义词法分析器的词法规则。
这些规则描述了编程语言中各种词法单元的模式。
例如,关键字可以被定义为由特定字符组成的字符串,标识符可以被定义为以字母开头并由字母和数字组成的字符串。
4.2 实现词法分析器接下来,我们将根据定义的词法规则,使用编程语言实现一个词法分析器。
在实现过程中,我们可以使用正则表达式来匹配和提取各种词法单元。
4.3 编写测试用例完成词法分析器的实现后,我们需要编写一些测试用例来验证其正确性。
测试用例应该包含各种可能的输入情况,以确保词法分析器能够正确地识别和提取词法单元。
4.4 运行测试用例最后,我们将使用编写的测试用例来运行词法分析器,并检查输出是否符合预期。
如果测试通过,说明词法分析器能够正常工作;否则,我们需要检查代码并进行调试。
5. 实验结果经过实验,我们成功地设计并实现了一个基本的词法分析器。
该词法分析器能够按照预定义的词法规则,正确地识别和提取源代码中的各种词法单元。
在运行测试用例时,词法分析器能够产生符合预期的输出,表明其具有良好的准确性和可靠性。
编译原理_词法分析器实验报告
编译原理_词法分析器实验报告一.实验题目和要求。
题目:设计PL / 0语言的词法分析器。
要求:单词(关键字);begin end if then else while write read docall const var procedure repeat until运算符:+ - * / := = <>(#) < <= > >=界符:, . ; ( )标识符:字母打头的字母数字串,长度不超过10.常数:整数,所含数字的个数不超过14.返回单词形式:二元式(种别,属性值)二.实验平台。
PC机: Windows XP操作系统编程环境: Turbo C 2.0编程语言: C语言三.实验算法说明。
定义2个全局变量char ch和char strtoken分别用来存放最新读入的源程序字符和构成单词符号的字符串。
然后用各个子函数的功能和读文件内容的操作,实现对源程序的词法分析,分别进行关键字,标识符,常数,运算符和界符的分析确认,然后将对应的二元式结果输出。
首先用户输入要读文件的名称,然后程序会把文件的内容读到定义的够大的字符数组str(相当于词法分析的一个缓冲区)里,然后开始从str里一个一个的读出字符并放在专门用来暂时存放单词数组strtoken里进行词法分析,若符合语言的规则,则打印出相关的说明信息,即该字符或字符串的二元式信息,可以清楚的明白该字符的种别和属性值。
如果读入的字符或字符串是非法的,即不是语法规定或是没有意义的字符或字符串,程序会提示相关的错误信息并进行一定四.程序子函数功能说明。
1.void getChar( ) 将下一个输入字符读到ch中,搜索指示器前移一个字符的位置。
2. void getBc( ) 检查ch中的字符是否为空白,若是,则调用getChar( ),直到ch中进入一个非空的字符。
3.void retract( ) 将搜索指示器回调一个字符位置,将ch置为空白字符。
编译词法分析实验报告
一、实验目的1. 理解词法分析的基本概念和原理。
2. 掌握词法分析器的实现方法。
3. 熟悉C语言在词法分析中的应用。
4. 提高编程能力和问题解决能力。
二、实验环境1. 操作系统:Windows 102. 编程语言:C3. 开发环境:Visual Studio 2019三、实验内容1. 设计词法分析器,实现对源代码的词法分析。
2. 将源代码分解为单词序列。
3. 输出单词序列及对应的词法类型。
四、实验步骤1. 分析源代码中的词法单位,确定词法类型。
2. 设计词法分析器的状态转换表。
3. 编写词法分析器代码。
4. 测试词法分析器,验证其正确性。
五、实验过程1. 分析源代码中的词法单位在C语言中,词法单位包括标识符、关键字、运算符、分隔符、常量等。
本实验以C语言为例,分析源代码中的词法单位,确定词法类型。
2. 设计词法分析器的状态转换表根据词法单位,设计词法分析器的状态转换表。
状态转换表包括当前状态、输入字符、下一状态、输出词法类型和对应动作。
3. 编写词法分析器代码根据状态转换表,编写词法分析器代码。
以下为词法分析器的主要功能模块:(1)初始化:设置初始状态、词法类型和单词长度。
(2)读取字符:从源代码中读取字符,并判断字符类型。
(3)状态转换:根据状态转换表,更新当前状态、输出词法类型和单词长度。
(4)输出结果:将单词序列及对应的词法类型输出到屏幕。
4. 测试词法分析器编写测试用例,验证词法分析器的正确性。
测试用例包括以下几种情况:(1)包含各种词法单位的源代码。
(2)包含注释的源代码。
(3)包含错误标识符的源代码。
六、实验结果与分析1. 实验结果通过测试,词法分析器能够正确识别源代码中的各种词法单位,并将单词序列及对应的词法类型输出到屏幕。
以下为部分测试结果:```int a = 10; // 输出:int, 标识符if (a > 0) // 输出:if, 关键字{// 输出:{, 分隔符// ...// 输出:}, 分隔符}// 输出://, 注释开始注释内容// 输出://, 注释结束```2. 实验分析(1)实验过程中,通过对词法分析原理的学习,加深了对编译原理的理解。
编译原理实验报告 词法分析
编译原理实验一·词法分析一、实验目的通过动手实践,使学生对构造编译系统的基本理论、编译程序的基本结构有更为深入的理解和掌握;使学生掌握编译程序设计的基本方法和步骤;能够设计实现编译系统的重要环节。
同时增强编写和调试程序的能力。
二、实验内容及要求对某特定语言A ,构造其词法规则。
该语言的单词符号包括:保留字(见左下表)、标识符(字母大小写不敏感)、整型常数、界符及运算符(见右下表) 。
功能要求如下所示:·按单词符号出现的顺序,返回二元组序列,并输出。
·出现的标识符存放在标识符表,整型常数存放在常数表,并输出这两个表格。
·如果出现词法错误,报出:错误类型,位置(行,列)。
·处理段注释(/* */),行注释(//)。
·有段注释时仍可以正确指出词法错误位置(行,列)。
三、实验过程1、词法形式化描述使用正则文法进行描述,则可以得到如下的正规式:其中ID表示标识符,NUM表示整型常量,RES表示保留字,DEL表示界符,OPR表示运算符。
A→(ID | NUM | RES | DEL | OPR) *ID→letter(letter | didit)*NUM→digit digit*letter→a | …| z | A | …| Zdigit→0 | …| 9RES→program | begin | end | var | int | and | or | not | if | then | else | while | doDEL→( | ) | . | ; | ,OPR→+ | * | := | > | < | = | >= | <= | <>如果关键字、标识符和常数之间没有确定的算符或界符作间隔,则至少用一个空格作间隔。
空格由空白、制表符和换行符组成。
2、单词种别定义;3、状态转换图;语言A的词法分析的状态转换图如下所示:空格符,制表符或回车符字母或数字4、运行环境介绍;本次实验采用win-tc进行代码的编写和编译及运行程序的运行环境为windows5、关键算法的流程图及文字解释;程序中用到的函数列表:变量ch储存当前最新读进的字符的地址strToken存放当前字符串voidmain() //主函数struct binary *lexicalAnalyze(); //词法分析的主函数,返回一个二元组的指针void GetBC(); //检查ch指向的字符是否为空格、制表或回车符,如果是则调用GetChar()直至不是上述字符void GetChar(); //ch前移一个地址单元int ConCat(); //将ch指向的字符连接到strToken之后int isLetter(); //判断ch指向的字符是否字母int isDigit(); //判断ch指向的字符是否数字int insertId(); //向标识符表中插入当前strToken的字符串int insertConst(); //将strToken的常数插入常数表中int Reserved(); //检测当前strToken中的字符串是否保留字,若是,则返回编码,否则返回0int isId(); //检测当前strToken中的字符串是否在标识符表中已存在,若是,则返回其编号,否则返回0int isConst(); //检测当前strToken中的字符串是否在常数表中已存在,若是,则返回其编号,否则返回0void errProc(int errType); //出错处理过程,errType是错误类型,将错误信息加入错误表中main()函数的流程图如下:lexicalAnalyze()函数的流程图如下所示:Reserved()、isId()和isConst()函数均采用了对链表的遍历算法,errProc()函数通过识别不同的错误编号,向错误链表中添加相应的错误信息。
编译原理词法分析器实验报告
编译原理词法分析器实验报告篇一:编译原理词法分析器实验报告曲阜师范大学实验报告计算机系2008年级软件工程一班组日期2010年10月17日星期日姓名陈金金同组者姓名课程编译原理成绩实验名称:教师签章词法分析器一、实验目的:1·掌握词法分析的原理。
2·熟悉保留字表等相关的数据结构与单词的分类方法。
3·掌握词法分析器的设计与调试。
二、实验内容:根据编译中的分词原理,编写一个词法分析程序:1. 输入:任意一个C 语言程序的源代码。
2. 处理:对输入进行分析,分离出保留字、标识符、常量、算符和界符。
3. 输出:对应的二元式(种别编码自定,可暂编为一类对应一个编码)。
三、实验要求:1. 任选C/C++/Java 中的一种高级程序语言编程完成词法分析器。
2. 词法分析器应以教材所述分词原理为依据,使用恰当的数据结构和方法,结构清晰、高效。
四、实验环境:WindowsXp操作系统,J2SE,Eclipse 集成开发环境五、实验分析:将源代码作为长字符串进行读入,之后通过switch语句,及状态转换图进行词素识别,并对识别的词素进行分类整理以二元式的形式输出。
六、实验过程:1、建立词法分析器界面,很简单:输入框,输出框,执行分析按钮,清空按钮,退出程序按钮。
主要的地方是,考虑mvc开发模式,为model及controller 提供接口。
实现界面如下所示:2、核心代码的编写,考虑到需要进行词素的匹配,创建符号表类SymTable。
提供两个变量,分别存放如下内容:并提供方法insert,lookUp,分别负责标志符的插入和查找。
3.、根据语法规则书写状态转换图,并用switch语句实现:需要注意的地方是,begin和forward 两个指针的移动:通过swith语句识别词素,并在符号表中进行匹配,匹配成功,则返回相应的记号,否则返回id。
七、实验结论:实验过程还算顺利,遇到的一系列问题都得到比较好的解决,当然分析器还有很大的改进空间,这里只是简单的实现了词素的识别及简单的判断。
(完整)编译原理实验报告(词法分析器 语法分析器)
编译原理实验报告实验一一、实验名称:词法分析器的设计二、实验目的:1,词法分析器能够识别简单语言的单词符号2,识别出并输出简单语言的基本字。
标示符。
无符号整数.运算符.和界符。
三、实验要求:给出一个简单语言单词符号的种别编码词法分析器四、实验原理:1、词法分析程序的算法思想算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号.2、程序流程图(1)主程序(2)扫描子程序3、各种单词符号对应的种别码五、实验内容:1、实验分析编写程序时,先定义几个全局变量a[]、token[](均为字符串数组),c,s( char型),i,j,k(int型),a[]用来存放输入的字符串,token[]另一个则用来帮助识别单词符号,s用来表示正在分析的字符.字符串输入之后,逐个分析输入字符,判断其是否‘#’,若是表示字符串输入分析完毕,结束分析程序,若否则通过int digit(char c)、int letter(char c)判断其是数字,字符还是算术符,分别为用以判断数字或字符的情况,算术符的判断可以在switch语句中进行,还要通过函数int lookup(char token[])来判断标识符和保留字。
2 实验词法分析器源程序:#include 〈stdio.h〉#include <math.h>#include <string。
h>int i,j,k;char c,s,a[20],token[20]={’0’};int letter(char s){if((s〉=97)&&(s〈=122)) return(1);else return(0);}int digit(char s){if((s〉=48)&&(s<=57)) return(1);else return(0);}void get(){s=a[i];i=i+1;}void retract(){i=i-1;}int lookup(char token[20]){if(strcmp(token,"while")==0) return(1);else if(strcmp(token,"if")==0) return(2);else if(strcmp(token,"else”)==0) return(3);else if(strcmp(token,"switch”)==0) return(4);else if(strcmp(token,"case")==0) return(5);else return(0);}void main(){printf(”please input string :\n");i=0;do{i=i+1;scanf("%c",&a[i]);}while(a[i]!=’#’);i=1;j=0;get();while(s!=’#'){ memset(token,0,20);switch(s){case 'a':case ’b':case ’c':case ’d':case ’e’:case ’f’:case 'g’:case ’h':case 'i':case ’j':case 'k’:case ’l':case 'm’:case 'n':case ’o':case ’p':case ’q’:case 'r’:case 's’:case 't’:case ’u’:case ’v’:case ’w’:case ’x':case ’y':case ’z’:while(letter(s)||digit(s)){token[j]=s;j=j+1;get();}retract();k=lookup(token);if(k==0)printf("(%d,%s)”,6,token);else printf("(%d,—)",k);break;case ’0':case ’1’:case ’2':case ’3':case '4’:case '5’:case ’6':case ’7’:case ’8’:case '9’:while(digit(s)){token[j]=s;j=j+1;get();}retract();printf(”%d,%s",7,token);break;case '+':printf(”(’+',NULL)”);break;case ’-':printf("(’-',null)");break;case ’*':printf(”('*’,null)");break;case '<':get();if(s=='=’) printf(”(relop,LE)”);else{retract();printf("(relop,LT)");}break;case ’=':get();if(s=='=’)printf("(relop,EQ)");else{retract();printf(”('=',null)”);}break;case ’;':printf(”(;,null)");break;case ' ’:break;default:printf("!\n”);}j=0;get();} }六:实验结果:实验二一、实验名称:语法分析器的设计二、实验目的:用C语言编写对一个算术表达式实现语法分析的语法分析程序,并以四元式的形式输出,以加深对语法语义分析原理的理解,掌握语法分析程序的实现方法和技术.三、实验原理:1、算术表达式语法分析程序的算法思想首先通过关系图法构造出终结符间的左右优先函数f(a),g(a)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理实验报告09010422 何博伟东南大学计算机科学与工程学院School of Computer Science & EngineeringSoutheast University二〇一三年 1月实验一词法分析器设计实现实验目的与要求通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。
并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
实验内容编制一个程序读入程序文件,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符等。
并依次分解输出各行包含的内容。
输入:aaa.txt输入格式:每行一个待检测的字串,如“typedef”,“/*test*/”输出:ccc.txt输出格式:输出文件以“Start scanning...”作为第一行,之后的每一行input :后面是输入的字串实现约定我们用下面正则表达式来描述程序语言的词法规则:标识符ID = (_ | letter)(letter | digit | _)*数字NUM =digit*(ε|.) digit*字母letter = a|..|z|A|..|Z|数字digit = 0|..|9专用符号sym = + |-| * |/ |< |<=| >| >= |==| !=| =| ;| ,| .| '| "| (| ) |[ |] |{ |} |/*| */| //关键字(所有的关键字都是保留字,并且必须是小写):res=auto const dynamic_cast for mutable register static_cast try virtual bool const_cast else friend namespace reinterpret_cast struct typedef void break continue enum goto new return switch typeid volatile case default explicit if operator short template typename while catch delete extern inline private signed this union char do false int protected sizeof throw unsigned class double float long public static true using规定所有字母都是大小写区分的。
空格由空白、换行符和制表符组成。
空格通常被忽略,除了它必须分开ID、NUM 关键字。
注释允许使用/* */以及//形式。
实验实现具体见手写附录 总状态图如下:实验源程序及实验结果分析实验源程序 ://MyLex.h #pragma once/////////////////////////////////////////////// //// A little lexical analyzer //// powered by Bowei He /////////////////////////////////////////////// #define MAXRESERVED 60 #define MAXWORDSIZE 100#include <iostream> #include <fstream> #include <sstream> using namespace std;K4K0K5K6K7K8K2K3K1K9K10K11//任意字符*除*外任意字符除/外任意字符//digitdigit .Letter 或_letter _digit< > = !=其他特殊字符typedef enum{////Type of tokens//Reserved wordsAUTO,BOOL,BREAK,CASE,CA TCH,CHAR,CLASS,CONST,CONST_CAST,CONTINUE,DEFAULT,DELETE,DO,DOUBLE,DYNAMIC_CAST,ELSE,ENUM,EXPLICIT,EXTERN,FALSE1,FLOAT,FOR,FRIEND,GOTO,IF,INLINE,INT,LONG,MUTABLE,NAMESPACE,NEW,OPERA TOR,PRIV ATE,PROTECTED,PUBLIC,REGISTER,REINTERPRET_CAST,RETURN,SHORT,SIGNED,SIZEOF,STATIC,STATIC_CAST,STRUCT,SWITCH,TEMPLA TE,THIS,THROW,TRUE1,TYPEDEF,TYPEID,TYPENAME,UNION,UNSIGNED,USING,VIRTUAL,VOID,VOLATILE,WHILE,_TRY,//SymbolsPLUS,MINUS,MTPLUS,DEVIDE,EQ,ASSIGN,LT,MT,TIMES,DOT,SQ,DQ,LXKH,RXKH,LZKH,RZKH,LDKH,RDKH,SEMI,LE,ME,NOTEQ,FH,LZS, RZS,ZS,//StatesUNKNOWN,COMMENT,SPECIALSYM,NUM,ID,ERROR//Here ID maybe a reserved word which will be identified in later process.}TypeOfToken;typedef enum{_ERR,_COMM,_SPCSYM,_NUM,_ID,_RESWORD,_UNKNOWN}FinalType;//define the reservedWords' map table between Tokenstr and TokenTypestruct{char* str;TypeOfToken tt;}reservedWords[MAXRESERVED] = {{"auto",AUTO},{"bool",BOOL},{"break",BREAK},{"case",CASE},{"catch",CA TCH},{"char",CHAR},{"class",CLASS},{"const",CONST},{"const_cast",CONST_CAST},{"continue",CONTINUE},{"default",DEFAULT},{"delete",DELETE},{"do",DO},{"double",DOUBLE} ,{"dynamic_cast",DYNAMIC_CAST},{"else",ELSE},{"enum",ENUM},{"explicit",EXPLICIT},{"extern",EXTERN},{"false",FALSE1},{"float",FLOAT}, {"for",FOR},{"friend",FRIEND},{"goto",GOTO},{"if",IF},{"inline",INLINE},{"int",INT},{"long",LONG},{"mutable",MUTABLE},{"namespace",NAMESPACE},{"new",NEW},{"operator",OPERA TOR},{"private",PRIV ATE},{"protected",PROTECTED},{"pu blic",PUBLIC},{"register",REGISTER},{"reinterpret_cast",REINTERPRET_CAST},{"return",RETURN},{"short",SHORT},{"signed",SIGNED},{"sizeof",SIZEOF},{"st atic",STA TIC},{"static_cast",STA TIC_CAST},{"struct",STRUCT},{"switch",SWITCH},{"template",TEMPLATE},{"this",THIS},{"throw",THROW},{"true",TRUE1}, {"try",_TRY},{"typedef",TYPEDEF},{"typeid",TYPEID},{"typename",TYPENAME},{"union",UNION},{"unsigned",UNSIGNED},{"using",USING}, {"virtual",VIRTUAL},{"void",VOID},{"volatile",VOLATILE},{"while",WHILE}typedef enum{//States of tokenDFAK0,K1,K2,K3,K4,K5,K6,K7,K8,K9,K10,K11,ERR}DFAState;class MyLex{private:ifstream inputFile; //input fileofstream outputFile; //output filepublic:MyLex(string inputFileName, string outputFileName){inputFile.open(inputFileName.c_str(),ios::in);outputFile.open(outputFileName.c_str(),ios::out);}~MyLex(){inputFile.close();outputFile.close();}inline bool isDigit(char a){if(int(a) < 0x3A && int(a) > 0x2F)return true;return false;}inline bool isLetter(char a){int m = (int)a;if(m > 0x40 && m < 0x5b)return true;else if(m > 0x60 && m < 0x7b)return true;return false;}inline bool isSpecialSym(char a){switch (a){case '+': case '-': case '*': case '/': case '<': case '=': case '>': case '!': case ';': case ',': case '.': case 0x27:// 'case 0x22:// "case '(': case ')': case '[': case ']': case '{': case '}':return true;default:return false;}}inline bool isReservedWord(string word){//Judge if the input word is a reserved word.for(int i=0; i<MAXRESERVED; i++){string temp(reservedWords[i].str);if(temp == word)return true;}return false;}TypeOfToken dealWithToken(string tokenIn){//This is a function to deal with token//input: string of token (eg. 'iorange')//output: TypeOfToken (eg. ID)string::iterator it;DFAState state = K0;for(it=tokenIn.begin(); it<tokenIn.end(); it++){char chrNow = (char)(*it);if(state == ERR)// If it went to ERR before, we can immediately stop looping..break;if(state == K0){//From initial stateif(chrNow == '/')else if(isLetter(chrNow) || chrNow == '_')state = K1;else if(isDigit(chrNow))state = K2;else if(chrNow == '<' || chrNow == '>' || chrNow == '=' || chrNow == '!') state = K9;else if(isSpecialSym(chrNow))state = K11;elsestate = ERR;}else if(state == K1){if('_' == chrNow)state = K1;else if(isDigit(chrNow))state = K1;else if(isLetter(chrNow))state = K1;elsestate = ERR;}else if(state == K2){if(isDigit(chrNow))state = K2;else if('.' == chrNow)state = K3;elsestate = ERR;}else if(state == K3){if (isDigit(chrNow))state = K3;elsestate = ERR;}else if(state == K4){if('/' == chrNow)state = K5;else if('*' == chrNow)state = K6;else}else if(state == K5){//this is a commentstate = K5;}else if(state == K6){if('*' == chrNow)state = K7;elsestate = K6;}else if(state == K7){if ('/' == chrNow)state = K8;elsestate = K6;}else if(state == K8){if('/' == chrNow)state = K4;elsestate = ERR;}else if(state == K9){if ('=' == chrNow)state = K10;elsestate = ERR;}else if(state == K10)state = ERR;else if(state == K11)state = ERR;elsestate = ERR;}switch(state){return ERROR;case K8: case K5:return COMMENT;case K4: case K9: case K11:return SPECIALSYM;case K10:return SPECIALSYM;case K1:return ID;case K2: case K3:return NUM;default:cerr << "Shouldn't be here!" << endl;return ERROR;}}void scanFile()//Scan the whole input file and export to another file specified {outputFile << "Start scanning..." << endl;char* chr = new char[MAXWORDSIZE];while(!inputFile.eof()){inputFile >> chr;string s(chr);cout << "input: " << s << endl;outputFile << "input : " << s << endl;if(isReservedWord(s)){cout << " >> Reserved word." << endl;outputFile << " >> Reserved word." << endl;}else{TypeOfToken tot = dealWithToken(s);switch (tot){case UNKNOWN:cout << " >> Unknown." << endl;outputFile << " >> Unknown." << endl;break;case ERROR:cout << " >> Error." << endl;outputFile << " >> Error." << endl;case COMMENT:cout << " >> Comment." << endl;outputFile << " >> Comment." << endl;break;case SPECIALSYM:cout << " >> Special symbol." << endl;outputFile << " >> Special symbol." << endl;break;case NUM:cout << " >> Number." << endl;outputFile << " >> Number." << endl;break;case ID:cout << " >> ID." << endl;outputFile << " >> ID." << endl;break;default:cout << " >> SHOULD NOT BE HERE!." << endl;outputFile << " >> SHOULD NOT BE HERE!." << endl;break;}}}}};//main.cpp#include "myLex.h"#include <iostream>using namespace std;void main(){MyLex ml("aaa.txt","ccc.txt");ml.scanFile();system("pause");}测试输入:typedef auto.;/ /*abcde*//*dadwq*/wqd /**///dwqd//andkwqhdowqd *.- 10 -.测试输出 :Start scanning... input : typedef >> Reserved word. input : auto >> Reserved word. input : .>> Special symbol. input : ;>> Special symbol. input : />> Special symbol. input : /= >> Error. input : /*abcde*/ >> Comment. input : /*dadwq*/wqd >> Error. input : /**///dwqd >> Comment. input : //andkwqhdowqd >> Comment. input : *>> Special symbol. input : !>> Special symbol. input : !=>> Special symbol. input : ==>> Special symbol. input : <=>> Special symbol. input : '>> Special symbol. input : ">> Special symbol. input : 1234>> Number. input : 12.445 >> Number. input : 0.877 >> Number. input : iorange >> ID. input : _iorange >> ID. input : _dqw99 >> ID. input : 9912ed >> Error. input : ddd989 >> ID.。