陈朔鹰版编译原理词法分析实验报告.doc
- 格式:docx
- 大小:201.01 KB
- 文档页数:13
编译原理词法分析实验报告实验名称:词法分析器的设计与实现一、实验目的: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、根据以下的正规式,编制正规文法,画出状态图;ﻩ标识符ﻩﻩﻩ<字母>(<字母>|<数字字符>)*ﻩ十进制整数0 | ((1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*)八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*运算符和界符ﻩ+ -*/ >< = ( ) ;ﻩﻩ关键字ﻩﻩif then elsewhile do2、根据状态图,设计词法分析函数int scan( ),完成以下功能:1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词,2)以二元式形式输出单词<单词种类,单词属性>其中单词种类用整数表示:0:标识符1:十进制整数2:八进制整数3:十六进制整数运算符和界符,关键字采用一字一符,不编码其中单词属性表示如下:标识符,整数由于采用一类一符,属性用单词表示运算符和界符,关键字采用一字一符,属性为空ﻩ3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。
四、实验环境PC微机DOS操作系统或Windows操作系统Turbo C 程序集成环境或Visual C++程序集成环境五、实验步骤1、根据正规式,画出状态转换图;2、根据状态图,设计词法分析算法;观察状态图,其中状态2、4、7、10(右上角打了星号)需要回调一个字符。
声明一些变量和函数:ch:字符变量,存放最新读进的源程序字符。
strToken: 字符串变量,存放构成单词符号的字符串。
GetChar():ﻩ子函数,将下一输入字符读到ch中,搜索指示器前移一字符位置。
编译原理词法分析实验报告词法分析实习报告实习题目设计一个表达式的文法①表达式中的运算按运算符优先级由高到低依次有:+、-、*、/、↑其中+、-是左结合,*、/、↑右结合。
②表达式中的运算对象可以为标识符、无正负号常量。
设计的文法G[<表达式>]=(VN,VT,P,<表达式>)其中,VN={<表达式>,<无正负号常量>,<标志符>,<数字>,<字母>} VT={ a…z,A…Z,0…9}P={<表达式>→DE↑<表达式>∣DE;DE→ME/DE∣ME;ME→SE*ME∣SE;SE→SE-AE∣AE;AE→AE +<表达式>∣<表达式>∣<标识符>∣<无正负号常量>;〈标识符〉→〈字母〉|〈标识符〉〈字母〉|〈标识符〉〈数字〉;〈无正负号常量〉→〈数字〉|〈无正负号常量〉〈数字〉;〈字母〉→a|b|…|x|y|z|A|B|…|X|Y|Z;〈数字〉→1│2│3│4│5│6│7│8│9│0}词法分析程序设计思路词法分析就是逐个读入源程序字符并按照构词规则切分成一系列单词.单词是语言中具有独立意义的最小单位,根据设计的文法可以判断出表达式中的单词种类有标识符,运算符,常量。
字母或数字识别各类单词符号的状态转换图所用数据结构FILE *fp;//用于存放原表达式文件FILE *outp;//用于存放单词输出结果char ch;//用于存储当前读取的字符char *operatornum[5]={"+","-","*","/","|"};//用于存放运算符源码#include#include#include#include#include#include#includeFILE *fp;//用于存放原表达式文件FILE *outp;//用于存放单词输出结果char ch;//用于存储当前读取的字符char *operatornum[5]={"+","-","*","/","|"};//用于存放运算符/////////////////////////////////////////////////////////////////// /////////////////////// bool search(char searchstr[])//匹配运算符{int i;for(i=0;i<=4;i++)if(strcmp(operatornum[i],searchstr)==0)return(true);return(false);}/////////////////////////////////////////////////////////////////// //////////////////////// char letterprocess (char ch)//字母处理函数{int i=-1;char letter[20];while (isalnum(ch)!=0){letter[++i]=ch;ch=fgetc(fp);}letter[i+1]='\0';printf("<标示符,%s>\n",letter);fputs("<标示符,",outp);fputs(">\n",outp);return(ch);}/////////////////////////////////////////////////////////////////// //////////////////////// char numberprocess(char ch)//数字处理程序{int i=-1;char num[20];while (isdigit(ch)!=0)//如果为数字{num[++i]=ch;ch=fgetc(fp);}if(isalpha(ch)!=0)//如果为字母{while(isspace(ch)==0)//如果为空格{num[++i]=ch;ch=fgetc(fp);}num[i+1]='\0';printf("错误!非法标识符:%s\n",num);return(ch);}num[i+1]='\0';printf("<常数,%s>\n",num);fputs("<常数,",outp);fputs(num,outp);return(ch);}/////////////////////////////////////////////////////////////////// /////////////////////////// char otherprocess(char ch)//其它符号(运算符和非法字符)的处理{int i=-1;char other[20];if (isspace(ch)!=0){ch=fgetc(fp);return(ch);}while ((isspace(ch)==0)&&(isalnum(ch)==0)){other[++i]=ch;ch=fgetc(fp);}other[i+1]='\0';if (search(other)){ printf("<运算符,%s>\n",other);fputs("<运算符,",outp);fputs(other,outp);fputs(">\n",outp);}elseprintf("错误!非法字符:%s\n",other);return (ch);}/////////////////////////////////////////////////////////////////////////////////////////////int main (){char str,c;printf("**********************************词法分析器************************************\n");outp=fopen("二元式表.txt","w");if ((fp=fopen("源程序.txt","r"))==NULL)printf("源程序无法打开!\n");else{str =fgetc(fp);while (str!=EOF){if (isalpha(str)!=0)str=letterprocess(str);else{if (isdigit(str)!=0)str=numberprocess(str);elsestr=otherprocess(str);}};printf("词法分析结束,谢谢使用!\n");printf("点任意键退出!\n");}c=getch();}输入从存放源文件的目录下的源程序.txt 中读取表达式输出从将结果存放到源文件的目录下的二元式表.txt 中问题分析词法分析相对而言较为简单,词法分析的目的就是识别出一个个的单词符号,为进一步进行语法分析打下坚实的基础。
编译原理词法分析实验报告一,题目编制C语言子集的词法分析程序二,实验目的通过设计、编制、调试一个具体的词法分析程序,加深对词法分析原理的理解,并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
三,实验要求1.根据具体情况,由同学们自己选取C语言的一个适当大小的子集(可取一类典型单词,也可以尽可能使各种类型的单词都兼顾到),如课本表2.1;在上机前一定要制出相应的表。
2.程序功能输入:字符串。
输出:二元式(种别编码,单词自身)构成的序列。
举例:输入:a=$;#输出:(6,a)(12,=)FOUND ERROR(13,;)四,步骤1.定义单词表2.完善词法分析器程序(1)定义变量、函数(2)增加程序的输入、输出3.程序验证词法分析程序的功能输入:所给文法的源程序字符串。
输出:二元组(syn,token)构成的序列。
其中:typenum为单词种别码;token为单词缓冲区;五,源程序代码:#include<stdio.h>#include<stdlib.h>#include<string.h>#define _KEY_WORD_END "waiting fou your expanding"/*定义关键字的结束标志*/ typedef struct{int typenum; /*种别码*/char *word;}WORD;char input[255]; /*源程序缓字符冲区*/char token[255]=""; /*单词缓冲区*/int p_input; /*源程序字符指针*/int p_token; /*单词缓冲区指针*/char ch;char *rwtab[]={"begin","if","then","while","do","end",_KEY_WORD_END}; WORD *scaner(); /*词法扫描函数,获得一个单词*/void main(){int over=1;int count=0;WORD *oneword = new WORD;printf("Enter Your words(end with #):");scanf("%[^#]s",input); /*输入源程序字符串到缓冲区,以#结束*/p_input=0;printf("词法分析结果是:\n\n");while (over<1000 && over!= -1){oneword=scaner();if(oneword->word=="OVER")break;else if(oneword->typenum==-3)printf(oneword->word);else if(oneword->typenum <1000)printf("(%d,%s) ",oneword->typenum ,oneword->word );over=oneword->typenum ;count++;if(count%6==0) printf("\n");//每六行输出}}char m_getch() /*从输入源读一个字符到CH中*/{ch=input[p_input];p_input=p_input+1;return ch;}void getbc() /*去掉空白字符*/{while (ch == ' '|| ch== 10){ch = input[p_input];p_input=p_input+1;}}void concat() /*拼接单词*/{token[p_token]=ch;p_token=p_token+1;token[p_token]='\0';}int letter()/*判断是否是字母*/{if(ch>='a' && ch<='z'|| ch >='A'&& ch <='Z') return 1;else return 0;}int digit()/*判断是否是数字*/{if(ch>='0'&& ch<='9')return 1;else return 0;}int reserve()/*检索关键字表格*/{int i=0;while(strcmp(rwtab[i],_KEY_WORD_END)){if(!strcmp(rwtab[i],token)){return i+1;}i=i+1;}return 6;}void retract()/*回退一个字符*/{p_input=p_input-1;}char *dtb(){return NULL;}WORD *scaner()/*词法扫描程序*/{WORD *myword =new WORD;myword->typenum=10;myword->word=" ";p_token=0;m_getch();getbc();if(letter()){while(letter()||digit()){concat();m_getch();}retract();myword->typenum=reserve();myword->word=token;return myword;}else if(digit()){while(digit()){concat();m_getch();}retract();myword->typenum =11;myword->word =token;return myword;}else switch(ch){case'=' : m_getch();if(ch=='='){myword->typenum =11;myword->word ="==";return myword;}retract();myword->typenum =12;myword->word ="=";return myword;break;case'+':myword->typenum =8;myword->word ="+";return myword;break;case'-':myword->typenum =9;myword->word ="-";return myword;break;case'*':myword->typenum =10;myword->word ="*";return myword;break;case'/':myword->typenum =16;myword->word ="/";return myword;break;case'(':myword->typenum =27;myword->word ="(";return myword;break;case')':myword->typenum =28;myword->word =")";return myword;break;case'[':myword->typenum =30;myword->word ="[";return myword;break;case']':myword->typenum =31;myword->word ="]";return myword;break;case'{':myword->typenum =32;myword->word ="{";return myword;break;case'}':myword->typenum =33;myword->word ="}";return myword;break;case',':myword->typenum =34;myword->word =",";return myword;break;case':':if(input[p_input]=='='){myword->typenum =18;myword->word =":=";return myword;}elsemyword->typenum =17;myword->word =":";return myword;break;case';':myword->typenum =13;myword->word =";";return myword;break;case'>':m_getch();if(ch=='='){myword->typenum =24;myword->word =">=";return myword;}retract();myword->typenum =23;myword->word =">";return myword;break;case'<':m_getch();if(ch=='='){myword->typenum =11;myword->word ="<=";return myword;}retract();myword->typenum =20;myword->word ="<";return myword;break;case'!':m_getch();if(ch=='='){myword->typenum =40;myword->word ="!=";return myword;}retract();myword->typenum =-1;myword->word ="ERROR";return myword;break;case'\0':myword->typenum=100;myword->word="OVER";return myword;break;case'#':myword->typenum=-1;myword->word="FOUND ERROR";return myword;break;default:myword->typenum=-3 ;myword->word="FOUND ERROR";return myword;}}六,结果验证a)给定源程序a=s;#输出结果b)给定源程序x<=s;#输出结果。
编译原理实验词法分析实验报告一、实验目的词法分析是编译过程的第一个阶段,其主要任务是从左到右逐个字符地对源程序进行扫描,产生一个个单词符号。
本次实验的目的在于通过实践,深入理解词法分析的原理和方法,掌握如何使用程序设计语言实现词法分析器,提高对编译原理的综合应用能力。
二、实验环境本次实验使用的编程语言为_____,开发工具为_____。
三、实验原理词法分析的基本原理是根据编程语言的词法规则,将输入的字符流转换为单词符号序列。
单词符号通常包括关键字、标识符、常量、运算符和界符等。
词法分析器的实现方法有多种,常见的有状态转换图法和正则表达式法。
在本次实验中,我们采用了状态转换图法。
状态转换图是一种有向图,其中节点表示状态,有向边表示在当前状态下输入字符的可能转移。
通过定义不同的状态和转移规则,可以实现对各种单词符号的识别。
四、实验步骤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;}```通过对多个测试用例的分析,词法分析器能够正确识别出各种单词符号,实验结果符合预期。
编译原理词法分析一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求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数组中存放的字符,判断分离出关键字、标示符、数字、运算符、标示符。
一. 实验序号:《编译原理》第一次实验二. 实验题目:词法分析三. 实验日期:2010.10四. 实验环境(操作系统,开发语言)操作系统:Windows开发语言:C五. 实验内容(实验要求)a)将标识符的词法改为“以大写字母或小写字母开头,后面可以跟大写字母或小写字母或数字或下划线”。
b)将<条件>中的表示相等关系的单词“=”改为“= =”c)将原来的无小数的数改为可以有小数的数六. 实验步骤a)打开VC++,找到getsym()项目。
int getsym(){...}在getsym()函数中设置断点,F10逐过程调试根据要求a修改为if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')往后面看,修改while(ch>='a' && ch<='z' || ch>='0' && ch<='9' || ch>='A' && ch<='Z' || ch=='_');b)在检测赋值符号的程序段中找到等号 = 的判断代码,改变成为 = = 即可。
c)在获取整数数字的值的程序段后面添加判断小数点的代码。
如果是,即读取符号并且按照小数的要求将其缩小并且累加到总的符号串中。
七. 实验体会(包括收获、心得体会、存在的问题及解决问题的方法、建议等)通过实验,如果要修改代码的话,首先应该读懂源码,在修改之前了解到程序段的功能是什么,然后再在相应的行进行修改添加,再进行合理的调试。
如果问题太过困难可以查询资料或与同学进行讨论八. 实验结果(关键源程序)a)int getsym(){int i,j,k;while(ch==' '||ch==10||ch==9) /*忽略空格,换行和TAB*/{getchdo;}if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')/*名字或保留字以a..z A。
(完整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>+”,当前字符为’>’,此时,分析器到底是将其分析为大于关系运算符还是大于等于关系运算符呢?显然,只有知道下一个字符是什么才能下结论。
于是分析器读入下一个字符’+’,这时可知应将’>’解释为大于运算符。
但此时,超前读了一个字符’+’,所以要回退一个字符,词法分析器才能正常运行。
在分析标识符,无符号整数等时也有类似情况。
日期:2013年5月9日一.实验目的1.理解并掌握正规文法、正规式、有限自动机之间的内在联系及相互转换原理;2.学会如何使用Visual C++等高级语言编程实现上述转换关系;3.以四则混合运算表达式为例,编写词法分析程序;4.通过实验,理解模块化程序设计思想,从全局角度领会一个完整软件的设计精髓,为后续实验的顺利完成奠定坚实的基础。
二.实验仪器与设备微型电子计算机(PC机)配置Windows XP及以上版本操作系统安装Visual C++6.0或Visual C#2002010或Delphi6.0等以上版本的开发环境二.实验内容与步骤1. 已知正整数的四则运算的表达式的状态转换图如右图所示,要求编写相应词法分析程序,以识别符号串:((23+12)*9-200)/5最终输出单词流。
、注:能识别0、5、13、342等形式的整数,但可以将形如067的数据识别为2个数值:0、67。
流程图:一. 正则文法设 a:0-9b:1-9 c: |其他文法G=( Vn , Yt , S , P );其中:Vn={⓪,①};Vt={②,③,④,⑤,⑥,⑦,⑧,⑨};S=0;P:⓪→0②;⓪→b①; ①→a①;①→c②;⓪→'('③;⓪→')'④;⓪→'+'⑤;⓪→'-'⑥;⓪→'*'⑦;⓪→'/'⑧;⓪→'c'⑨二.正则表达式设a:0-9b:0c:1-9d: |其他e:{‘(’,’)’,’+’,’-’,’*’,’/’}三.词法分析程序类定义// StringLEX.h: interface for the CLEXExpression class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_STRINGLEX_H__1AB7E0B1_0076_4937_B0C2_8DCE5160DB82__INCLUDED_) #define AFX_STRINGLEX_H__1AB7E0B1_0076_4937_B0C2_8DCE5160DB82__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#pragma warning(disable:4786)//屏蔽“由于string和vector等STL模版产生很长的标识符而引起的警告信息”#include<iostream>#include<iomanip>#include<string>//#include<vector>using namespace std;struct SignProperty {// 属性字int SignKind; // 单词种别/* 设置单词种别:(可根据需要自行规定)1:分隔符2:操作数3:运算符*/ string SignValue; // 单词值};class CLEXExpression {public:CLEXExpression();virtual ~CLEXExpression();public:void SetSourceString(string str);// 设置源串SignProperty GetToken(); // 识别单词,返回属性字string GetRestString(); // 返回剩余串private:char nextchar(); // 读取下一个字符void untread(); // 回退一个字符private:int pos; // 指针string proBuffer; // 待分析的源串string restString; // 分析后的剩余串};#endif// !defined(AFX_STRINGLEX_H__1AB7E0B1_0076_4937_B0C2_8DCE5160DB82__INCLUDED_) 类实现// StringLEX.cpp: implementation of the CLEXExpression class.////////////////////////////////////////////////////////////////////////#include "LEXExpression.h"//////////////////////////////////////////////////////////////////////// Construction/Destruction////////////////////////////////////////////////////////////////////// CLEXExpression::CLEXExpression(){proBuffer = "";restString = "";}CLEXExpression::~CLEXExpression(){}// 读一个字符:char CLEXExpression::nextchar(){if(pos+1<proBuffer.length()) // 若符号尚未读完return proBuffer[++pos];else // 若已读完return '\0';}// 回退一个字符:void CLEXExpression::untread(){--pos;}// 返回剩余串:string CLEXExpression::GetRestString(){return restString;}// 词法分析,返回一个单词属性字:SignProperty CLEXExpression::GetToken(){SignProperty Token; // 属性字变量Token.SignKind = -1;Token.SignValue = "";if(proBuffer.empty()) // 若待分析串为空,则直接返回:return Token;//(1)初始化pos=-1;int state=0;char char1;bool Flag1=true;//(2)while(Flag1){switch(state){case 0:char1 = nextchar(); // 读入一个字符if(char1>='1'&&char1<='9')state = 1;else if(char1=='0')state = 2;else{switch (char1){case '(':state = 3; break;case ')':state = 4; break;case '+':state = 5; break;case '-':state = 6; break;case '*':state = 7; break;case '/':state = 8; break;default:state = 9;}}break;case 1:do{char1 = nextchar(); // 读入一个字符}while(char1>='0'&&char1<='9'); // 输入字符为数字:0 ~ 9state = 2; // 若为其他字符,则转到状态2 break;case 2:if(char1!='\0'&&char1!='0') // 如果读入其他符号,则untread(); // 回退一个已读进的字符Token.SignKind = 2; // 2:操作数Token.SignValue = proBuffer.substr(0,pos+1);Flag1=false;break;case 3:Token.SignKind = 1; // 1:分隔符Token.SignValue = proBuffer.substr(0,pos+1);Flag1=false;break;case 4:Token.SignKind = 1; // 1:分隔符Token.SignValue = proBuffer.substr(0,pos+1);Flag1=false;break;case 5:Token.SignKind = 3; // 3:运算符Token.SignValue = proBuffer.substr(0,pos+1);Flag1=false;break;case 6:Token.SignKind = 3; // 3:运算符Token.SignValue = proBuffer.substr(0,pos+1);Flag1=false;break;case 7:Token.SignKind = 3; // 3:运算符Token.SignValue = proBuffer.substr(0,pos+1);Flag1=false;break;case 8 :Token.SignKind = 3; // 3:运算符Token.SignValue = proBuffer.substr(0,pos+1);Flag1=false;break;case 9:untread();cout<<"警告:读入了非法符号!"<<endl;Flag1=false;break;}}// 保留剩余串:if(proBuffer.length()-pos-1>=0)restString= proBuffer.substr(pos+1,proBuffer.length()-pos-1);elserestString="";return Token;}void CLEXExpression::SetSourceString(string str){proBuffer = str;restString = str;}主函数#include "LEXExpression.h"// 显示单词(属性字格式)void DisplayToken(SignProperty token){if(token.SignKind!=-1) {// 若无错误,则显示:string temp;cout<<"("<<setw(6)<<left<<token.SignValue<<",";if(token.SignKind==1)temp="分隔符";else if(token.SignKind==2)temp="操作数";else if(token.SignKind==3)temp="运算符";else if(token.SignKind==4)temp="界符";elsetemp="";cout<<setw(8)<<left<<temp<<")"<<endl;}}// 主函数:void main(){CLEXExpression CSL1;string temp1="((23+12)*9-200)/5";// string temp1="01";do{CSL1.SetSourceString(temp1);SignProperty temp2=CSL1.GetToken();if(temp2.SignKind==-1) // 若有错误,则退出:break ;DisplayToken(temp2);temp1=CSL1.GetRestString(); // 返回剩余串,以继续识别}while(!temp1.empty());}运行结果:四.思考题上面考察的是无符号整数。