前沿:词法分析器是将一段程序的代码按照类别分开.
一般来说是将关键字, 变量名 , 常数 运算符( + _ * / )和界符分类
词法分析算是编译的基础把
今天上编译原理的实验课, 看了看 老师给的代码 添加了一些注释
大致的流程是这样的:
规定关键字的符号是10
数字的符号是数字本身
+ - * = 这些符号代码中的case里面有(分别是13 14 ...),可以看懂的
首先, 把程序存到制定的内存区域, 这里是划出了一个连续的空间(放到字符数组);
然后再按字节读取里面的内容 , 当读到空格(" ")或者是换行符号(
)的时候,就默认是一个单词啦,()
把这个单词放进一个另外一个数组里面,美其名曰token[];
获得这个token之后 ,
首先判断token中的每一个字符是不是属于a-z的字符里面(需要一个while循环遍历)
如果在读取的字符不是一个字母, 那在看看是不是数字(0-9),如果是的话,那就写成相应的标识符
如果读取的是+ 那么将syn(表示代号)为13
每次识别出来之后,都以 ("syn " , string )的形式输出
/**C语言的词法分析
**/
#include<stdio.h>
#include<string.h>
/**
程序规定:
1、关键字:"function","if","then","while","do","endfunc";
2、算术运算符:"+","-","*","/","=";
3、关系运算符:"<" ">" "<=" ">=" "==" "!=";
4、界符:"(" ")" ";" "#";
5、标识符规定以字母开头,字母均为小写;
6、空格和换行符跳过;
**/
char prog[80];//把所有内容放进这个数组里面
char token[8];//存放每次的读取 的 单词
char ch;// 每次读取的 单词的字符的
int syn;//记录编码方式
int p;//指向 要读数字的下标
int m;
int n;
int sum;//求取数字的和
char * rwtab[6]={"function","if","then","while","do","endfunc"};// 关键字
void scaner();//函数 声明
void main(void)//
{
p=0;
printf("
please input string:
");
do///当读取字符#的时候代表结束,把输入的字符存储到数组里 ....
{
scanf("%c",&ch);
prog[++p]=ch;
}
while(ch!='#');
p=0;
do
{
scaner();
switch(syn)
{
case 11:printf("
(%d,%d)",syn,sum);break;
case -1:printf("
error");break;
default:printf("
(%d,%s)",syn,token);
}
}
while(syn!=0);
}
void scaner()
{
for(n=0;n<8;n++)
token[n]=NULL;////清空 token数组
ch=prog[++p];//读取 prog 中 的 字符串的字符
while(ch=='
' || ch==' ') //当读到 换行和空格的时候 说明字符已经结束或者是这个单词已经写完 开始把下一个读取的单词放入 prog中:缓冲区 :80个字符 存放的全是空格和换行符
ch=prog[++p];
if(ch>='a'&&ch<='z')//如果读取的 字符是一个小写字母
{
m=0;
while(ch>='a'&&ch<='z')//把每次从 prog中 读取的字母 读取到 token中
{
token[m++]=ch;
ch=prog[++p];
}
token[m]=' ';//C中的字符结束符号
ch=prog[--p];//???????
syn=10;//?????????
for(n=0;n<6;n++)//检查是否含有关键字 ,如果有的话 ,
if(strcmp(token,rwtab[n])==0)// strcmp()函数,自左向右的按ASCII值比较 , 相等话是=0;
{
syn=n+1;//如果是关键字的话 +1??
break;
}
}
else //如果ch 不在 字符集中...
if(ch>='0'&&ch<='9')//考察是否在0-9的数字中
{
sum=0;
while(ch>='0'&&ch<='9')//
{
sum=sum*10+ch-'0';//讲数字形式的字符从数字转化成 数字形式
ch=prog[++p];//读取下一个数字
}
ch=prog[--p];//>因为前面是++,这里要--
syn=11;
}
else//如果既不在数字 也不在字母中的话.....
switch(ch)
{
case '<':m=0;token[m++]=ch;
ch=prog[++p];
if(ch=='=')
{
syn=21;
token[m+1]=ch;
}
else
{
syn=20;
ch=prog[--p];
}
break;
case '>':m=0;token[m++]=ch;
ch=prog[++p];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=23;
ch=prog[--p];
}
break;
case '=':m=0;token[m++]=ch;
ch=prog[++p];
if(ch=='=')
{
syn=25;
token[m++]=ch;
}
else
{
syn=18;
ch=prog[--p];
}
break;
case '!':m=0;token[m++]=ch;
ch=prog[++p];
if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
syn=-1;
break;
case '+':syn=13;token[0]=ch;break;
case '-':syn=14;token[0]=ch;break;
case '*':syn=15;token[0]=ch;break;
case '/':syn=16;token[0]=ch;break;
case ';':syn=26;token[0]=ch;break;
case '(':syn=27;token[0]=ch;break;
case ')':syn=28;token[0]=ch;break;
case '#':syn=0;token[0]=ch;break;
default:syn=-1;
}
}