目录
一、题目
假设某语言允许的标识符为字母开头的字母数字串,允许的数据为无符号的十进制或十六进制整数。其中规定十六进制数必须以数字打头、以H结尾,数中允许使用的字母为A,B,C,D,E,F(分别表示10~15)。试设计一个DFA,使它能识别标识符、无符号的十进制和十六进制整数(假定各单词之间用界限符或空格分开),并编制相应的词法识别程序。
输入:可以自定义符号串的输入形式,如键盘输入、文本文件、字符数组等。
输出:标识出规范的符号串与不合规范的符号串。
例:
若输入:" Ae35 6638 5392H A10 83A2Eh 65Ha 3G2H 80 "
则输出:
Ae35是一个标识符(Identifier)
6638是一个十进制整数(DecimalInteger)
5392H是一个十六进制数(HexDigit)
A10是一个标识符(Identifier)
83A2Eh是一个十六进制数(HexDigit)
65Ha非法输入(InvalidInput)
3G2H非法输入(InvalidInput)
80是一个十进制整数(DecimalInteger)
二、分析与设计
(1) 分析与设计
a)根据给定的语言求出其正规式(或文法)
G[S]:
S->lA | dB
A-> lA | dA | ε
B-> hC | dB | (a,f)D
C->ε
D-> dD | (a,f)D | hC
c) 给出最小化的DFA
(2) 编程
a) 根据最小化的DFA绘制程序流程图(核心部分)
b) 编写词法分析程序
(3) 系统调试
三、源代码
#include "stdio.h"
#include "string.h"
#include "conio.h"
enum type{digit,space,Hh,AF,letter};
//测试的输入字符串
char words[100] = " Ae35 6638 5392H A10 83A2Eh 65Ha 3G2H 80 ";
char* q;//指向输入符号串中当前的字符
char word[20];//存储当前识别的单词
int state = 0;//表示所处的状态,初始状态为0
int i;//单词的下标
int isDigitOrChar(char ch) {
if (ch >= 48 && ch <= 57) //数字
return digit;
else if (ch == 32)
return space; //空格
else if (ch == 72 || ch == 104)
return Hh; //Hh
else if ((ch >= 65 && ch <= 70) || (ch >= 97 && ch <= 102))//ABCDEF或者abcdef
return AF;
else if ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122))//除A-F外的其他字母
return letter;
}
int main() {
printf("%s \n", words);
q = words;
while (*q) {
switch (state) {
case 0: //当前为0状态
switch (isDigitOrChar(*q)) {
case digit://数字
word[i++] = *q;
state = 2;
break;
case Hh: //Hh
case AF: //ABCDEF或者abcdef
case letter: //除A-F外的其他字母
word[i++] = *q;
state = 1;
break;
case space: //空格
state = 0;
memset(word, 0, sizeof(word));
i = 0;
break;
default: //其他字符(非法)
word[i++] = *q;
state = 5; //转到出错状态
break;
}
break;
case 1: //当前为1状态
switch (isDigitOrChar(*q)) {
case digit://数字
word[i++] = *q;
state = 1;
break;
case Hh: //Hh
case AF: //ABCDEF或者abcdef
case letter: //除A-F外的其他字母
word[i++] = *q;
state = 1;
break;
case space: //空格,1状态可以为标识符的结束状态
word[i++] = *q;
state = 0;
for (int m = 0;m < sizeof(word);m++) {
printf("%c", word[m]);
}
memset(word, 0, sizeof(word));
i = 0;
printf("是一个标识符(Identifier)\n");
break;
default: //其他字符(非法)
word[i++] = *q;
state = 5; //转到出错状态
break;
}
break;
case 2: //当前为2状态
switch (isDigitOrChar(*q)) {
case digit://数字
word[i++] = *q;
state = 2;
break;
case Hh: //Hh
word[i++] = *q;
state = 3;
break;
case AF: //ABCDEF或者abcdef
word[i++] = *q;
state = 4;
break;
case space: //空格,2状态可以为十进制整数的结束状态
word[i++] = *q;
state = 0;
for (int m = 0;m < sizeof(word);m++) {
printf("%c", word[m]);
}
memset(word, 0, sizeof(word));
i = 0;
printf("是一个十进制整数(DecimalInteger)\n");
break;
default: //其他字符(非法)
word[i++] = *q;
state = 5; //转到出错状态
break;
}
break;
case 3: //当前为3状态
switch (isDigitOrChar(*q)) {
case space: //空格,3状态可以为十六进制整数的结束状态
word[i++] = *q;
state = 0;
for (int m = 0;m < sizeof(word);m++) {
printf("%c", word[m]);
}
memset(word, 0, sizeof(word));
i = 0;
printf("是一个十六进制数(HexDigit)\n");
break;
default: //其他字符(非法)
word[i++] = *q;
state = 5;
break;
}
break;
case 4: //当前为4状态
switch (isDigitOrChar(*q)) {
case digit://数字
word[i++] = *q;
state = 4;
break;
case Hh: //Hh
word[i++] = *q;
state = 3;
break;
case AF: //ABCDEF或者abcdef
word[i++] = *q;
state = 4;
break;
case space: //空格
word[i++] = *q;
state = 0;
memset(word, 0, sizeof(word));
i = 0;
break;
default: //其他字符(非法)
word[i++] = *q;
state = 5; //转到出错状态
break;
}
break;
case 5: //出错状态
switch (isDigitOrChar(*q)) {
case space: //空格
word[i++] = *q;
state = 0;
for (int m = 0;m < sizeof(word);m++) {
printf("%c", word[m]);
}
memset(word, 0, sizeof(word));
i = 0;
printf("非法输入\n");
break;
default: //其他字符(非法)
word[i++] = *q;
state = 5; //转到出错状态
break;
}
break;
}
q++; //指针下移(指向输入符号串的下一个字符)
}
printf("》》》分析结束《《《\n\n\n");
return 0;
}