一. 实验目的
- 理解词法分析器的工作原理。
- 掌握利用状态转换图设计词法分析器的基本方法。
- 实现Micro语言的词法分析程序
二. 实验内容
根据给出的Micro语言的定义,设计并实现它的的词法分析器,实现源程序的输入、 预处理和词法分析,最后以编译程序需要的内部表示形式(二元组)将识别的 单词符号输出。 利用状态转换图设计Micro语言的词法规则。 用C语言实现该语言词法分析程序
三. 实验步骤
- Micro语言的定义
仅有的数据类型是整型INT。
所有的标识符采用显式声明,且长度不超过32个字符。标识符必须以字母开头并由字母、数字和下划线组成。
整型常量由一串数字组成。
注释由“–”开始,并在当前行尾结束。
语句类型为:
赋值语句:
ID := Expression;
Expression是由标识符、文字常量、+ - * / 运算符组成的中缀表达式结构,其中允许含有括号。
输入输出语句:
read( List of IDs);
write(List of Expressions);
begin、end、read、write、INT都是保留字。
每条语句以分号(;)结束。程序体由begin和end界定。
词法记号不能跨行。
四、代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *key_word[5] = { "int", "begin", "end", "read", "write" };
int i = 0, j = 0, k = 0, t = 0; // 搜索指示器
#define BUFFERSIZE 1000
char ch; // 存放最新读入的源程序字符
char str_token[33]; // 存放构成单词符号的字符
char *char_form[100]; // 字符表
char *int_form[100]; // 常数表
char form[BUFFERSIZE];
int q = 0;
int temp;
FILE *fp;
// 常用语句的宏定义
#define GET_CHAR ch = form[k]; k++; // 将下一个字符读到ch,搜索指示器 前移一个字符位置
#define GET_BC while(ch == ""){ GET_CHAR;} // 检查ch字符是否为空白。是的话调用get_char
#define CONCAT str_token[i] = ch; i++; // 链接字符
//判断是否为字母
int isLetter()
{
if (((ch <= 'z') && (ch >= 'a')) || ((ch <= 'Z') && (ch >= 'A')))
return (1);
else
return (0);
}
//判断是否为数字
int isDigit()
{
if ((ch >= '0') && (ch <= '9'))
return (1);
else
return (0);
}
//判断是否为关键字
int reserve()
{
int q = 0;
for (q = 0; q<5; q++){
if (strcmp(str_token, key_word[q]) == 0)
return q;
}
return -1;
}
//函数回调
void retract() //将搜索指示器回调一个字符位置,将ch置为空白字符
{
k--;
ch = NULL;
}
//将strToken中的标识符插入符号表,返回符号表指针
char *insertId()
{
char_form[j] = str_token;
j++;
return char_form[0];
}
//将strToken中的常数插入常数表,返回常数表指针
char *inserConst()
{
int_form[t] = str_token;
t++;
return int_form[0];
}
//词法分析器的构造
int code;
void scanner()
{
for (i = 0; i<32; i++)
str_token[i] = NULL;
i = 0;
GET_CHAR;
GET_BC;
printf("这是一个 ");
if (isLetter()){
while (isLetter() || isDigit()){
concat();
GET_CHAR;
}
retract();
code = reserve();
switch (code){
case -1:
printf("字符串 %s\n", &str_token);
break;
default:
printf("关键字 %s\n", &str_token);
break;
}
}
else if (isDigit()){
while (isDigit()){
concat();
GET_CHAR;
}
retract();
printf("运算符 %s\n", &str_token);
}
else if (ch == '='){
printf("运算符 =%s\n", &str_token);
}
else if (ch == '+'){
printf("运算符 +%s\n", &str_token);
}
else if (ch == '-'){
printf("运算符 -%s\n", &str_token);
}
else if (ch == ';'){
printf("界符 ;%s\n", &str_token);
}
else if (ch == '('){
printf("界符 (%s\n", &str_token);
}
else if (ch == ')'){
printf("界符 )%s\n", &str_token);
}
}
void main() {
int n = 0;
fp = fopen("C:\\Users\\MySHworks\\Desktop\\test.txt", "r");
while(fgets(form, 48, fp) != NULL){
k = 0;
while (form[k] != '\0')
scanner();
}
system("pause");
fclose(fp);
}
五、心得
词法分析的主要任 务是:根据构造的状态转换图,从左到右逐个字符地対源程序进行扫描,识别的最小语法单位——符号或单词,如变量标识符,关键字,常量,运算符,界符等。然后将提取出的标识符以内码的形式表示,即用int类型的数字来表示其类型和在display表中的位置,而无须保留原来标识符本身的字符串,这不仅节省了内存空间,也有利于下一阶段的分析工作。通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。另外,也让我重新熟悉了C++语言的相关内容,加深了对C++语言的用途的理解。