词法分析程序(Lexical Analyzer)要求:
- 从左至右扫描构成源程序的字符流
- 识别出有词法意义的单词(Lexemes)
- 返回单词记录(单词类别,单词本身)
- 滤掉空格
- 跳过注释
- 发现词法错误
程序结构:
输入:字符流(什么输入方式,什么数据结构保存)
处理:
–遍历(什么遍历方式)
–词法规则
输出:单词流(什么输出形式)
–二元组
单词类别:
1.标识符(10)
2.无符号数(11)
3.保留字(一词一码)
4.运算符(一词一码)
5.界符(一词一码)
单词符号 |
种别码 |
单词符号 |
种别码 |
begin |
1 |
: |
17 |
if |
2 |
:= |
18 |
then |
3 |
< |
20 |
while |
4 |
<= |
21 |
do |
5 |
<> |
22 |
end |
6 |
> |
23 |
l(l|d)* |
10 |
>= |
24 |
dd* |
11 |
= |
25 |
+ |
13 |
; |
26 |
- |
14 |
( |
27 |
* |
15 |
) |
28 |
/ |
16 |
# |
0 |
#include<stdio.h>
#include<conio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#define MAXSIZE 50
int i, row = 0, line = 0;
char a[1000]; //程序
int number[1000][100]; //常数表
char mark[100][5]; //标识符表
char file,file1;
FILE fp,fwp;
//词法分析
int wordanalysis()
{
if ((a[i] >= ‘A‘&&a[i] <= ‘Z‘)||(a[i]>=‘a‘&&a[i]<=‘z‘))
{
char word[10];
char pro[100][100] = {"char","int","if","else","return","break","do","while","for","double","float","short"};
int n = 0;
word[n++] = a[i++];
//若字符为AZ或09,则继续读取
while ((a[i] >= ‘A‘&&a[i] <= ‘Z‘) || (a[i] >= ‘0‘ && a[i] <= ‘9‘)||(a[i]>=‘a‘&&a[i]<=‘z‘))
{
word[n++] = a[i++];
}
word[n] =‘\0‘;
//i-;
//判断该标识符是否为保留字
for (n = 0; n < 100; n++)
{
if (strcmp(word, pro[n]) == 0)
{
printf("( %d,%s) 关键字\n", n + 1,pro[n]);
fprintf(fwp,"( %d,%s) 关键字\n", n + 1,pro[n);
return 3;
}
}
//判断标识符长度是否超出规定
if (strlen(word)>10)
{
printf("%s\tERROR\n",word);
fprintf(fwp,"%s\tERROR\n",word );
return 3;
}
//判断该标识符是否存在标识符表中
int m = 0;
if (line != 0)
{
int q = 0;
while (q<line)
{
if (strcmp(word, mark[q++]) == 0)
{
printf("( %d,%s) 标识符\n", q,word);
fprintf(fwp,"( %d,%s) 标识符\n", q,word);
return 3;
}
}
}
//将该标识符保存到标识符表中
strcpy(mark[line], word);
printf("( %d,%s ) 标识符\n", line + 1,word);
fprintf(fwp,"( %d,%s ) 标识符\n", line + 1,word);
line++;
return 3;
}
//判断该标识符是否存在标识符表中
else if (a[i] >= ‘0‘ && a[i] <= ‘9‘) //分析常数
{
char x[100];
int n = 0, sum;
x[n++] = a[i++];
//判断字符是否是0~9
while (a[i] >= ‘0‘ && a[i] <= ‘9‘)
{
x[n++] = a[i++];
}
x[n] = ‘\0‘;
i-;
int num = atoi(x); //将字符串转换成int型
//判断该常数是否存在于常数表中
if (row != 0)
{
int y;
for (y = 0; y < 1000; y++)
{
int w = number[y][0];
sum = 0;
int d;
for (d = 1; d <= number[y][0]; d++)
{
w = w - 1;
sum = sum + number[y][d] * pow(2, w);
}
if (num == sum)
{
printf("( %d,%d ) 数字\n", y + 1,num);
fprintf(fwp,"( %d,%d ) 数字\n", y + 1,num);
return 3;
}
}
}
int z = num, c = num;
int m = 0;
do //计算是几位二进制数
{
z = z / 2;
m++;
} while (z != 0);
for (n = m; n > 0; n-) //将二进制保存于常数表中
{
number[row][n] = c % 2;
c = c / 2;
}
number[row][0] = m;
int line = row;
printf("( %d,%d ) 数字\n", line + 1,num);
fprintf(fwp,"( %d,%d ) 数字\n", line + 1,num);
row++;
return 3;
}
else //分析符号
switch (a[i])
{
case ‘ ‘:
case ‘\n‘:return -1;
case ‘#‘: return 0;
case ‘=‘:printf("( 14,= ) 运算符\n"); fprintf(fwp,"( 14,= ) 运算符\n");return 3;
case ‘<‘:
i++;
if (a[i] == ‘=‘)
{
printf("( 16,<= ) 运算符\n"); fprintf(fwp,"( 16,<= ) 运算符\n");return 3;
}
else if (a[i] == ‘>‘)
{
printf("( 19,<> ) 界符\n"); fprintf(fwp,"( 19,<> ) 界符\n");return 3;
}
else
{
i-;
printf("( 15,< ) 运算符\n"); fprintf(fwp,"( 15,< ) 运算符\n"); return 3;
}
case ‘>‘:
i++;
if (a[i] == ‘=‘)
{
printf("( 18,>= ) 运算符\n"); fprintf(fwp,"( 18,>= ) 运算符\n"); return 3;
}
else
{
i-;
printf("( 17,> ) 运算符\n"); fprintf(fwp,"( 17,> ) 运算符\n"); return 3;
}
case ‘+‘: printf("( 20,+ ) 运算符\n"); fprintf(fwp,"( 20,+ ) 运算符\n"); return 3;
case ‘-‘: printf("( 21,- ) 运算符\n");fprintf(fwp,"( 21,- ) 运算符\n"); return 3;
case ‘ ‘: printf("( 22, ) 运算符\n"); fprintf(fwp,"( 21, ) 运算符\n"); return 3;
case ‘/‘:
i++;
if(a[i]!=‘/‘){
i-;
printf("( 23,/ ) 运算符\n");fprintf(fwp,"( 23,/ ) 运算符\n"); return 3;
}
else{
while(1){
if(a[i++]==‘\n‘)
return -1;
}
printf("( 35,// ) 界符\n");fprintf(fwp,"( 35,// ) 界符\n");return 3;
}
case ‘:‘: printf("( 24,: ) 界符\n");fprintf(fwp,"( 24,: ) 界符\n"); return 3;
case ‘;‘: printf("( 25,; ) 界符\n");fprintf(fwp,"( 25,; ) 界符\n"); return 3;
case ‘(‘: printf("( 26,( ) 界符\n");fprintf(fwp,"( 26,( ) 界符\n"); return 3;
case ‘)‘: printf("( 27,) ) 界符\n");fprintf(fwp,"( 27,) ) 界符\n"); return 3;
case ‘{‘: printf("( 28,{ ) 界符\n");fprintf(fwp,"( 28,{ ) 界符\n"); return 3;
case ‘}‘: printf("( 29,} ) 界符\n");fprintf(fwp,"( 29,} ) 界符\n"); return 3;
case ‘[‘: printf("( 30,[ ) 界符\n");fprintf(fwp,"( 30,[ ) 界符\n"); return 3;
case ‘]‘: printf("( 31,] ) 界符\n");fprintf(fwp,"( 31,] ) 界符\n"); return 3;
case ‘|‘: printf("( 32,| ) 运算符\n");fprintf(fwp,"( 32,| ) 运算符\n"); return 3;
case ‘!‘: printf("( 33,! ) 界符\n");fprintf(fwp,"( 33,! ) 界符\n"); return 3;
case ‘,‘: printf("( 34, ) 界符\n");fprintf(fwp,"( 34, ) 界符\n"); return 3;
case ‘~‘: printf("( 35,~ ) 运算符\n");fprintf(fwp,"( 35,~ ) 运算符\n"); return 3;
case ‘&‘:
i++;
if(a[i]!=‘&‘){
i-;
printf("( 37,& ) 运算符\n");fprintf(fwp,"( 37,& ) 运算符\n"); return 3;
}
else{
printf("( 38,&& ) 运算符\n");fprintf(fwp,"( 38,&& ) 运算符\n"); return 3;
}
//case ‘\‘: printf("( 39,\ ) 界符\n");fprintf(fwp,"( 39,\ ) 界符\n"); return 3;
}
fclose(fwp);
}
int main()
{
int l = 0;
int m;
i = 0;
file=(char)malloc(sizeof(char)MAXSIZE);
file1=(char)malloc(sizeof(char)MAXSIZE);
printf(" 词法分析器*\n");
printf("请输入要进行词法分析的文件名(含路径):");
gets(file);
if(!(fp=fopen(file,"r")))
{
puts("打开文件失败!\n");
printf("请重新输入要进行词法分析的文件名(含路径):");
gets(file);
}
else
{
printf("成功打开文件%s!\n",file);
}
printf("请输入词法分析结果要存放的文件名(含路径):");
gets(file1);
if(!(fwp=fopen(file1,"w")))
{
printf("该文件不存在!\n");
}
else {
fwp = fopen(file1,"w");//打开文档,写入
while (!feof(fp))//检测流上的文件结束符,文件结束,返回非0值,否则返回0
{
a[l++] = fgetc(fp);
}
a[l] = ‘#‘;
do
{
m = wordanalysis();
switch (m)
{
case -1:i++; break;
case 0: i++; break;
case 3: i++; break;
}
} while (m != 0);
}
return 0;
}
转自http://www.pianshen.com/article/9571146300/
太难了
原文:https://www.cnblogs.com/hjqq/p/11656681.html