一、实验内容:
【问题描述】
请根据给定的文法设计并实现词法分析程序,从源程序中识别出单词,记录其单词类别和单词值,输入输出及处理要求如下:
(1)数据结构和与语法分析程序的接口请自行定义;类别码需按下表格式统一定义;
(2)为了方便进行自动评测,输入的被编译源文件统一命名为testfile.txt;输出的结果文件统一命名为output.txt,结果文件中每行按如下方式组织:
单词类别码 单词的字符/字符串形式(中间仅用一个空格间隔)
单词的类别码请统一按如下形式定义:
| 单词名称 | 类别码 | 单词名称 | 类别码 | 单词名称 | 类别码 | 单词名称 | 类别码 |
| 标识符 | IDENFR | if | IFTK | - | MINU | = | ASSIGN |
| 整型常量 | INTCON | else | ELSETK | * | MULT | ; | SEMICN |
| 字符常量 | CHARCON | do | DOTK | / | DIV | , | COMMA |
| 字符串 | STRCON | while | WHILETK | < | LSS | ( | LPARENT |
| const | CONSTTK | for | FORTK | <= | LEQ | ) | RPARENT |
| int | INTTK | scanf | SCANFTK | > | GRE | [ | LBRACK |
| char | CHARTK | printf | PRINTFTK | >= | GEQ | ] | RBRACK |
| void | VOIDTK | return | RETURNTK | == | EQL | { | LBRACE |
| main | MAINTK | + | PLUS | != | NEQ | } | RBRACE |
【输入形式】testfile.txt中的符合文法要求的测试程序。
【输出形式】要求将词法分析结果输出至output.txt中。
【样例输入】
const int const1 = 1, const2 = -100;
const char const3 = '_';
int change1;
char change3;
int gets1(int var1,int var2){
change1 = var1 + var2;
return (change1);
}
void main(){
printf("Hello World");
printf(gets1(10, 20));
}
【样例输出】
CONSTTK const
INTTK int
IDENFR const1
ASSIGN =
INTCON 1
COMMA ,
IDENFR const2
ASSIGN =
MINU -
INTCON 100
SEMICN ;
CONSTTK const
CHARTK char
IDENFR const3
ASSIGN =
CHARCON _
SEMICN ;
INTTK int
IDENFR change1
SEMICN ;
CHARTK char
IDENFR change3
SEMICN ;
INTTK int
IDENFR gets1
LPARENT (
INTTK int
IDENFR var1
COMMA ,
INTTK int
IDENFR var2
RPARENT )
LBRACE {
IDENFR change1
ASSIGN =
IDENFR var1
PLUS +
IDENFR var2
SEMICN ;
RETURNTK return
LPARENT (
IDENFR change1
RPARENT )
SEMICN ;
RBRACE }
VOIDTK void
MAINTK main
LPARENT (
RPARENT )
LBRACE {
PRINTFTK printf
LPARENT (
STRCON Hello World
RPARENT )
SEMICN ;
PRINTFTK printf
LPARENT (
IDENFR gets1
LPARENT (
INTCON 10
COMMA ,
INTCON 20
RPARENT )
RPARENT )
SEMICN ;
RBRACE }
【评分标准】 按与预期结果不一致的项数(每一行单词信息算一项)扣分,每项扣5%。
二、实验过程
1、根据DFA构造词法分析程序
直接编程的词法分析程序
(1)、适合词法比较简单的、手工实现、比较精简,分析速度快。
(2)、与要识别的语言单词密切相关,一旦词法规则发生变化,则要重新编写程序。
(3)、通过程序的控制流转移来完成对输入字符的响应,程序中的每一条语句都要与识别的单词符号有关。
2、表驱动的词法分析程序
(1)、一种典型的数据与操作的分离的工作模式,控制程序不变;不同的词法分 析器实质上是构造不同的分析表。
(2)、为词法分析程序的自动生成提供了极大的方便
(3)、程序比较复杂,分析速度慢一些
3、实验步骤
:
(1)、输入:源文件字符序列testfile.txt
任务:识别单词符号;滤过空格、注释等
依据:TEST语言的词法规则
输出:字符流(单词)
(2)、本实验我设计的词法分析器:
①能够识别出保留字、标识符、单分符、双分符、常量
②利用表驱动法识别注释并且滤过注释
三 实验代码
#include#include #include #include #define MAX 22 #define RES_MAX 13 #define MAXBUF 255 char ch =' '; int Line_NO; struct keywords { char lexptr[MAXBUF]; int token; }; struct keywords symtable[MAX]; char in[MAX] [10]= { "const","int","main","void","char","if","else","do","while","for","scanf","printf","return" }; char out[MAX] [10] = { "CONSTTK","INTTK","MAINTK","VOIDTK","CHARTK","IFTK","ELSETK","DOTK","WHILETK","FORTK","SCANFTK","PRINTFTK","RETURNTK" }; void init() { int j; for(j=0; j ='a'))||((c<='Z')&&(c>='A'))|| (ch == '_')) return 1; else return 0; } int IsDigit(char c){ if(c>='0'&&c<='9') return 1; else return 0; } void analyse(FILE *fpin,FILE *fpout){ char arr[MAXBUF]; int j=0; while((ch=fgetc(fpin))!=EOF) { if(ch==' '||ch=='t'){} else if(ch=='n') {Line_NO++;} else if(IsLetter(ch)){ while(IsLetter(ch)||IsDigit(ch)){ arr[j]=ch; j++; ch=fgetc(fpin); } fseek(fpin,-1L,SEEK_CUR); arr[j]=' '; j=0; if (Iskeyword(arr)) { int a; a=Iskeyword(arr); fprintf(fpout,"%s %sn",out[a],arr); } else if(!strcmp(arr,"const")) fprintf(fpout,"CONSTTK %sn",arr); else fprintf(fpout,"IDENFR %sn",arr); } else if(int(ch)==34||int(ch)==39) { ch=fgetc(fpin); char ar[MAXBUF];int i,j=0; while(int(ch)!=34&&int(ch)!=39) { ar[j]=ch; j++; ch=fgetc(fpin); } int length = strlen(ar); if(length ==1) { fprintf(fpout,"CHARCON %sn",ar); } else{ fprintf(fpout,"STRCON %sn",ar); } for(i=0;i


