http://www.Sina.com/http://www.Sina.com /
)1)关键词:
begin if then while do end
所有关键字都是小写的。
)2)运算符和边界符号
()-)/==; () #
)3)其他单词为标识符(ID )和整数常量(SUM ),用以下正则表达式定义。
id=letter(letter|digit ) *
NUM=digit digit*
(4)空白由空格、制表符、换行符构成。 空格通常用于分隔ID、SUM、运算符、边界字符和关键字,并在词法分析阶段被忽略。
词法分析器设计与实现
单词符号
类别代码
单词符号
类别代码
bgin
1
:
17
国际机场
2
() )=
18
Then
3
20
维鲁
4
21
do
5
=
22
结束
6
23
lettet(letter|digit ) *
10
=
24
dight dight*
11
=
25
13
;
26
-
14
(
/p>27
*
15
)
28
/
16
#
0
词法分析程序的功能:
输入:所给文法的源程序字符串。
输出:二元组(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)……
原理、方法和手段算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
主程序示意图:
主程序示意图如图3-1所示。其中初始包括以下两个方面:
⑴ 关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。如能查到匹配的单词,则该单词为关键字,否则为一般标识符。关键字表为一个字符串数组,其描述如下:
Char *rwtab[6] = {“begin”, “if”, “then”, “while”, “do”, “end”,};
(2)程序中需要用到的主要变量为syn,token和sum
扫描子程序的算法思想:
首先设置3个变量:①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。扫描子程序主要部分流程如图3-2所示。
补充内容ch: 字符变量、存放最新读入的源程序字符
strToken: 字符数组,存放构成单词符号的字符串
GetChar: 子程序过程,把下一个字符读入到ch中
GetBC: 子程序过程,跳过空白符,直至ch读入一个非空白字符
IsLetter和IsDigit:判断ch字符是否为字母或数字
Retract: 子程序,把搜索指针回调一个字符位置
code:
#include <stdio.h>#include <string.h>#define MaxSize 100007char *rwtab[6] = {"begin", "if", "then", "while", "do", "end"}; // 关键字表 char ch;char chStream[MaxSize]; // 缓存输入的字符流 char strToken[MaxSize]; // 字符数组,存放构成单词符号的字符串 int p, syn, sum;// 搜索指针 种别码和整型常数 // 子程序过程,把下一个字符读入ch中 char GetChar(int *p) {return chStream[(*p)++];}// 跳过空白符,直至读入一个非空字符char GetBC(int *p){while(chStream[*p] == ' '){(*p)++;}return chStream[(*p)++];}// 判断是否为字母 int IsLetter(char c){if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')){return 1;}return 0;}// 判断是否为数字int IsDigit(char c) {if(c >= '0' && c <= '9'){return 1;}return 0;}// 搜索指针回调一个字符位置 void Retract(int *p){(*p)--;}// 运算符和界符的判断 void solve(int *p) {memset(strToken, 0, sizeof(strToken));ch = GetBC(p); // 跳过空白符,直至读入一个非空字符if(IsLetter(ch)){ // 第一个是字母,则可能是关键字也可能是标识符 int idx = 0;while(IsLetter(ch) || IsDigit(ch)){strToken[idx++] = ch;ch = GetChar(p);} //strToken[idx] = ' ';Retract(p); // 搜索指针回调一个字符位置 syn = 10; // 先默认是标识符,接下来再判断是否为关键字for(int i = 0; i < 6; i++){if(strcmp(strToken, rwtab[i]) == 0){ // 与关键字相比较 syn = i+1; // 获取对应关键字的种别 break;} }}else if(IsDigit(ch)){ // 第一个是数字 sum = 0;while(IsDigit(ch)){sum = sum * 10 + (ch - '0');ch = GetChar(p);} Retract(p);syn = 11;}else{switch(ch){case '+': syn = 13; strToken[0] = ch; break;case '-': syn = 14; strToken[0] = ch; break;case '*': syn = 15; strToken[0] = ch; break;case '/': syn = 16; strToken[0] = ch; break;case ':':syn = 17;strToken[0] = ch;ch = GetChar(p); // 超前搜索一个字符 if(ch == '='){strToken[1] = ch;syn = 18;}else{// 如果超前搜索到的字符不能与当前字符相结合,则需要回退 Retract(p); } break;case '<':syn = 20;strToken[0] = ch;ch = GetChar(p);if(ch == '>'){strToken[1] = ch;syn = 21;}else if(ch == '='){strToken[1] = ch;syn = 22;}else{Retract(p);}break;case '>':syn = 23;strToken[0] = ch;ch = GetChar(p);if(ch == '='){strToken[1] = ch;syn = 24;}else{Retract(p);}break;case '=': syn = 25; strToken[0] = ch; break;case ';': syn = 26; strToken[0] = ch; break;case '(': syn = 27; strToken[0] = ch; break;case ')': syn = 28; strToken[0] = ch; break;case '#': syn = 0 ; strToken[0] = ch; break;default : syn = -1; break;}}}int main(){int idx = 0;do{ch = getchar();chStream[idx++] = ch;}while(ch != '#');chStream[idx] = ' '; // 标记字符串结束p = 0;do{solve(&p);switch(syn){case -1: printf("error!n"); break;case 11: printf("<%d, %d>n", syn, sum); break;default:printf("<%d, %s>n", syn, strToken);break;}}while(p < idx && syn != 0);return 0;}