词法分析:
实验目的:设计编制并调制一个词法分析程序
实验要求:
1.待分析的简单词法
(1)关键字:begin,if,then,while,do,then
(2)运算符和界限符: := , +,-,*,/,<, <=, <>, >, >=, = ;,,(,),#
(3)其他单词是标识符(ID)和整形常量(NUM),以下是正规是定义
ID = letter(letter|digital)*
NUM = digital digital*
(4)空格由空白,制表符和换行符组成,空格一般用来分割ID,NUM,运算符,界限符,保留字,词法分析阶段一般被忽略
2.各种单词符号对应的特种码
3.词法分析器程序的功能
输入:所给文法的源程序字符串
输出:二元组序列
核心代码介绍:
保留字查询
int searchReserve(char reserveWord[][20], char s[])
{
for (int i = 0; i < 6; i++)
if (strcmp(reserveWord[i], s) == 0) return i + 1;
return -1;//否则返回-1,代表查找不成功,即为标识符
}
保留字检索函数,由于只有6个保留字,没有在关键字查找里面使用自动机,而是采用的暴力破解直接匹配
两个简单的函数判断是否是字母或者数字,内联函数
bool IsLetter(char letter); //字母
bool IsDigital(char digital); //数字
修饰函数:除去源代码中的注释多余空格
int CodeProcessing(char str[], int iProjectLong); //修饰
两个输出函数,错误输出和一般输出
void PrintData(const char str[], int pFlag); //输出
void PrintData(const char str[], int pFlag,const char ErrorStr[]); //输出错误
pFlag为特种码,str传入字符串,ErrorStr错误代码
关键函数:词法分析函数ScanfProject(char str[], const int strLength);
确定自动机,使用switch实现
附一张测试结果图
最后源代码奉上
欢迎大佬打赏
#include<stdio.h>
#include"base.h"
#include<string.h>
static char reserveWord[6][20] = { //1-6
"begin","if","then","while","do","end"
};
int searchReserve(char reserveWord[][20], char s[]); //保留字
bool IsLetter(char letter); //字母
bool IsDigital(char digital); //数字
int CodeProcessing(char str[], int iProjectLong); //修饰
void ScanfProject(char str[], const int strLength); //扫描程序
void PrintData(const char str[], int pFlag); //输出
void PrintData(const char str[], int pFlag, const char ErrorStr[]); //输出错误
int main()
{
char str[10000];
int TabCount = 0; //回车标记数
int szCount = 0; //字符计数
int szTureLength = 0;//实际长度
FILE *fpin, *fpout;
if (NULL == (fpin = fopen("sz.txt", "r")))
{
puts("文件读取失败或者文件不存在 \n");
return 0;
}
do
{
str[szCount] = fgetc(fpin);
} while (EOF != str[szCount++] /* condition */);
str[szCount] = '\0';
szTureLength = CodeProcessing(str, szCount);
/*for (int i = 0; i < szTureLength; i++)
{
putchar(str[i]);
}*/
ScanfProject(str, szTureLength);
return 0;
}
int searchReserve(char reserveWord[][20], char s[])
{
for (int i = 0; i < 6; i++)
if (strcmp(reserveWord[i], s) == 0) return i + 1;
return -1;//否则返回-1,代表查找不成功,即为标识符
}
bool inline IsLetter(char letter)
{
if (letter >= 'a'&&letter <= 'z' || letter >= 'A'&&letter <= 'Z' || letter == '_') return true;
else return false;
}
inline bool IsDigital(char digital)
{
if (digital >= '0'&& digital <= '9') return true;
else return false;
}
void PrintData(const char str[], int pFlag)
{
printf("( %s , %d )\n", str, pFlag);
}
void PrintData(const char str[], int pFlag, const char ErrorStr[])
{
printf("(%s %s , 错误)\n", str, ErrorStr);
}
int CodeProcessing(char str[], const int iProjectLong)
{
//代码优化
char tempString[10000];
int count = 0;
for (int i = 0; i < iProjectLong - 1; i++)
{
switch (str[i])
{
case '/':
//去掉注释
switch (str[i + 1])
{
case '/':
i++;
while ('\n' != str[++i]);
tempString[count++] = '\n';
break;
case '*':
i++; //添加换行检测,输出错误行码
do
{
i++;
} while ('*' != str[i] && '/' != str[i + 1] && i < iProjectLong);
i++;
if (iProjectLong <= i) printf("error : 注释结束符/n");
i++;
break;
default:
break;
}
case ' ':
//多余空格处理
while (' ' == str[i + 1])
i++;
break;
default:
break;
}
tempString[count++] = str[i];
}
tempString[count] = '\0';
strcpy(str, tempString);
return count;
}
void ScanfProject(char str[], const int strLength) //dfa
{
/*
标识符: 字母开头
保留字: 查
常数:
运算符: + - * / < > = ~~~
界符:
*/
char szIdentifier[255];//标识符
char szoper[3]; //操作
char szLimit[3];
char szDigital[255];
//标识符中只能出现数字字母 出现其他字符或空格次标识符结束
//扫描开始
int Length = 0;
while (Length < strLength) //每一个词组循环
{
int iFlag = RESTART;
int num = 0;
int ierror = 0; //计数
switch (str[Length]) //
{
//标识符
/*
字母开头,可以包喊数字字母,扫描到其他符号时进行关键字检查
*/
//标示符数字先不进行判断,最后判断
case ':':
{
if ('=' == str[Length + 1])
{
strcpy(szoper, ":=");
PrintData(szoper, 18);
Length++;
Length++;
break;
}
else
{
strcpy(szoper, ":");
PrintData(szoper, 17);
Length++;
break;
}
}
case '\n':
Length++;
break;
case ' ':
Length++;
break;
case '<':
{
if ('>' == str[Length + 1])
{
strcpy(szoper, "<>");
PrintData(szoper, 21);
Length++;
Length++;
break;
}
else if ('=' == str[Length + 1])
{
strcpy(szoper, "<=");
PrintData(szoper, 22);
Length++;
Length++;
break;
}
else
{
strcpy(szoper, "<");
PrintData(szoper, 20);
Length++;
break;
}
}
case '>':
{
if ('=' == str[Length + 1])
{
strcpy(szoper, ">=");
PrintData(szoper, 24);
Length++;
Length++;
break;
}
else
{
strcpy(szoper, ">");
PrintData(szoper, 23);
Length++;
break;
}
}
case ';':
{
PrintData(";", 26);
Length++;
break;
}
case '\0':
{
Length++;
break;
}
case '(':
{
PrintData("(", 27);
Length++;
break;
}
case '=':
{
PrintData("=", 25);
Length++;
break;
}
case ')':
{
PrintData(")", 28);
Length++;
break;
}
case '#':
{
PrintData("#", 0);
Length++;
break;
}
case '+':
{
PrintData("+", 13);
Length++;
break;
}
case '-':
{
PrintData("-", 14);
Length++;
break;
}
case '*':
{
PrintData("*", 15);
Length++;
break;
}
case '/':
{
PrintData("/", 16);
Length++;
break;
}
default:
{//字母,数字,保留字分析
if (IsLetter(str[Length])) //letter(letter|digital)*自动机
{
szIdentifier[0] = str[Length];
Length++;
num++;
while ((IsLetter(str[Length]) || IsDigital(str[Length])) && num < 255)
{
szIdentifier[num] = str[Length];
Length++;
num++;
}
if (255 < num)
{
PrintData(" 程序 ", OVERLENGTH, " ");
break;
}
else
{
szIdentifier[num] = '\0';
int temp = searchReserve(reserveWord, szIdentifier);
if (-1 == temp)
{
PrintData(szIdentifier, 10);
break;
}
else
{
PrintData(szIdentifier, temp);
break;
}
}
}
else if (IsDigital(str[Length]))
{
szDigital[0] = str[Length];
Length++;
num++;
while (IsDigital(str[Length]) && num < 255)
{
szDigital[num] = str[Length];
Length++;
num++;
}
if (255 < num)
{
PrintData("", OVERLENGTH, "");
break;
}
else
{
szDigital[num] = '\0';
PrintData(szDigital, 11);
break;
}
}
else
{
szIdentifier[0] = str[Length];
szIdentifier[1] = '\0';
PrintData(szIdentifier, ERROR, " 未定义标示");
Length++;
break;
}
}
}
}
}
base.h :
#pragma once
//???flag
#define RESTART 0x0000
//??????flag
#define OVERLENGTH 0x0101 //???????
#define ERROR 0x0102 //自传参
//??????
#define IDENTIFIER 0x0001 //????????
#define RESERVEWORD 0x0002 //??????
#define OPERLIMIT 0x0003 //?????
#define DIGITAL 0x0004 //????
#define OPERATOR 0x0005 //??????
保留字越多,词法分析器越复杂,6个保留字...........