1、实验目的及要求
1.1、实验目的
加深对词法分析器的工作过程的理解;加强对词法分析方法的掌握;能够采用一种编程语言实现简单的词法分析程序;能够使用自己编写的分析程序对简单的程序段进行词法分析。
1.2、实验要求
1)对单词的构词规则有明确的定义;
2)编写的分析程序能够正确识别源程序中的单词符号;
3)识别出的单词以<种别码,值>的形式保存在符号表中,正确设计和维护符号表;
4)对于源程序中的词法错误,能够做出简单的错误处理,给出简单的错误提示,保证顺利完成整个源程序的词法分析;
2、实验步骤
2.1、词法分析规则
<标识符>::=<字母>|<标识符><字母>|<标识符><数字>
<常数>::=<数字>|<数字序列><数字>
<数字序列>::=<数字序列><数字>|<数字>|<.>
<字母>::=a|b|c|……|x|y|z
<数字>::=0|1|2|3|4|5|6|7|8|9
<运算符>::=<关系运算符>|<算术运算符>|<逻辑运算符>|<位运算符>|<赋值运算符>
<算数运算符>::=+|-|*|/|...|--
<关系运算符>::=<|>|!=|>=|<=|==
<逻辑运算符>::=&&| || |!
<位运算符>::=&| | |!
<赋值运算符>::==|+=|-=|/=|*=
<分界符>::=,|;|(|)|{|}|:| // |/**/
<保留字>::=main|if|else|while|do|for|...|void
2.2、单词符号的编码
单词符号 |
种别码 |
单词符号 |
种别码 |
main |
0 |
> |
26 |
if |
1 |
>= |
27 |
else |
2 |
< |
28 |
while |
3 |
<= |
29 |
do |
4 |
! |
30 |
for |
5 |
!= |
31 |
switch |
6 |
= |
32 |
case |
7 |
== |
33 |
int |
8 |
( |
34 |
double |
9 |
) |
35 |
float |
10 |
{ |
36 |
long |
11 |
} |
37 |
void |
12 |
; |
38 |
+ |
13 |
: |
39 |
+= |
14 |
| |
40 |
++ |
15 |
|| |
41 |
- |
16 |
数字 |
42 |
-= |
17 |
标识符 |
43 |
-- |
18 |
, |
44 |
& |
19 |
// |
45 |
&& |
20 |
/**/ |
46 |
# |
21 |
||
* |
22 |
||
*= |
23 |
||
/ |
24 |
||
/= |
25 |
2.3、状态转换图
2.4、算法分析
①词法分析器工作的第一步是输入源程序文本。为了更好地对单词符号识别,把输入串预处理一下。预处理主要滤掉空格,跳过注释、换行符等。
②对预处理后的输入串依次扫描单个字符,使用if-while嵌套语句和switch case语句判断字符的类型,具体识别方法可看状态转换图。有时为了确定词性,需要超前扫描,若超前扫描的字符对识别当前单词无用处,则需要退还给输入串,以备识别下一单词字符时使用。
③若读入的字符与单词符号编码表的字符匹配不上,则报错,并输出出错行数。对识别处的单词符号以(单词符号,种别码)二元式的形式输出。
3、实验内容
3.1、流程图
3.2、程序的变量与函数说明
- input:全局字符数组,用来存放输入串
- word:全局字符数组,用来存放获取到的单词符号,限定长度为8
- ch:全局字符变量,用来存放最新读入的字符
- syn:全局整型变量,表示单词符号的编码
- p:全局整型变量,表示当前字符在input数组的位置
- m:全局整型变量,表示最新读入的字符在word数组的下标
- line:全局整型变量,当前行数
- keyword:全局字符数组,存放关键字
- init():获取输入串
- isKey():判断关键字的函数,若参数数组中是关键字,则把syn置为该关键字对应的编码并返回1,否则返回0
- isLetter():判断字母的函数,若参数字符是字母,则返回1,否则返回0
- isDigit():判断数字的函数,若参数字符是数字,则返回1,否则返回0
- isSpace():判断空白符的函数,若参数字符是空格、TAB或换行符,则返回1,否则返回0
- scaner():扫描输入串的函数,对读出的字符进行判断,若是单词符号表中的符号,则将syn置为对应的编码
3.3、源代码
#include <stdio.h>
#include <string.h>
char input[1000];//输入串
char word[8];//获取到的单词
char ch;
int syn;//种别码
int p;
int m;
int line;//行数
//关键字
char keyword[][8]={"main","if","else","while","do","for","switch","case","int","double","float","long","void"};
void scaner(void);
//获取输入串
void init()
{
int i=0;
printf("\n please input a string(end with '#'):\n");
do{
scanf("%c",&ch);
input[i++]=ch;
}while(ch!='#');
}
//判断是不是关键字
int isKey(char *str)
{
int n;
for(n=0;n<13;n++)
{
if(strcmp(str,keyword[n])==0)
{
syn=n;
return 1;
}
}
return 0;
}
//判断是不是数字
int isDigit(char c)
{
if (c>='0'&&c<='9')
return 1;
else
return 0;
}
//判断是不是字母
int isLetter(char c)
{
if ((c<='z'&&c>='a')||(c>='A'&&c<='Z'))
return 1;
else
return 0;
}
int isSpace(char c)
{
if (c==' '||c=='\t'||c=='\n')
{
return 1;
}
return 0;
}
void main()
{
init();//输入字符串
line=0;
p=0;
do{
scaner();
switch(syn)
{
case -1:
printf("you have input a wrong string in line %d\n",line);
break;
default:
printf("( %s,%d )\n",word,syn);
break;
}
}while(syn!=21);
}
void scaner(void)
{
//清空word
for(m=0;m<8;m++)
{
word[m] = ' ';
}
//读取字符
ch=input[p++];
m=0;
//当ch为空格或换行符时,继续往下读
while(isSpace(ch))
{
if (ch=='\n')
{
line++;
}
ch=input[p++];
}
//如果以字母开头
if(isLetter(ch))
{
//如果往后是字母或数字,把字符存入word中,然后往下继续读
//串长超过8则截断
while((isLetter(ch)||isDigit(ch))&&m<8)
{
word[m++]=ch;
ch=input[p++];
}
p--;
syn=43;
word[m++]='\0';
isKey(word);//判断是不是关键字
}
//如果是以数字开头,并且往后是数字
else if(isDigit(ch))
{
while((isDigit(ch)||ch=='.')&&m<8)
{
word[m++]=ch;
ch=input[p++];
}
//如果数字之后是字母 ,则出错
if (isLetter(ch))
{
while(!isSpace(ch))
{
ch=input[p++];
}
syn=-1;
return ;
}
p--;
syn=42;
}
else
{
switch(ch)
{
//比较运算符
case '<':
word[m++]=ch;
ch=input[p++];
if(ch=='=')
{
syn=29;
word[m++]=ch;
}
else
{
syn=28;
p--;
}
break;
case '>':
word[m++]=ch;
ch=input[p++];
if(ch=='=')
{
syn=27;
word[m++]=ch;
}
else
{
syn=26;
p--;
}
break;
case '!':
ch=input[p++];
if(ch=='=')
{
syn=31;
word[m++]=ch;
}
else
{
syn=30;
p--;
}
break;
case '=':
word[m++]=ch;
ch=input[p++];
if(ch=='=')
{
syn=33;
word[m++]=ch;
}
else
{
syn=32;
p--;
}
break;
//算术运算符+、-、*、/
case '+':
word[m++]=ch;
ch=input[p++];
if(ch=='+')
{
syn=15;
word[m++]=ch;
}
else if(ch=='=')
{
syn=14;
word[m++]=ch;
}
else
{
syn=13;
p--;
}
break;
case '-':
word[m++]=ch;
ch=input[p++];
if(ch=='-')
{
syn=18;
word[m++]=ch;
}
else if(ch=='=')
{
syn=17;
word[m++]=ch;
}
else if (isDigit(ch))
{
while(isDigit(ch))
{
word[m++]=ch;
ch=input[p++];
}
p--;
syn=42;
}
else
{
syn=16;
p--;
}
break;
case '*':
word[m++]=ch;
ch=input[p++];
if(ch=='=')
{
syn=23;
word[m++]=ch;
}
else
{
syn=22;
p--;
}
break;
case '/':
word[m++]=ch;
ch=input[p++];
if(ch=='=')
{
syn=25;
word[m++]=ch;
}
//如果是单行注释,则读到换行符为止
else if (ch=='/')
{
word[m++]=ch;
syn=45;
while (ch!='\n')
{
ch=input[p++];
}
line++;
}
//如果是多行注释,则读到匹配的*/为止
else if(ch=='*')
{
word[m++]=ch;
syn=46;
int flag=1;
while (flag)
{
ch=input[p++];
if (ch=='*')
{
if (input[p++]=='/')
{
word[m++]='*';
word[m++]='/';
flag=0;
}
else
{
p--;
}
}
if (ch=='\n')
{
line++;
}
}
}
else
{
syn=24;
p--;
}
break;
//界符
case '(':
syn=34;
word[m++]=ch;
break;
case ')':
syn=35;
word[m++]=ch;
break;
case '{':
syn=36;
word[m++]=ch;
break;
case '}':
syn=37;
word[m++]=ch;
break;
case ';':
syn=38;
word[m++]=ch;
break;
case '#':
syn=21;
word[m++]=ch;
break;
case ':':
syn=39;
word[m++]=ch;
break;
case ',':
syn=44;
word[m++]=ch;
break;
//逻辑运算符
case '&':
word[m++]=ch;
ch=input[p++];
if(ch=='&')
{
syn=20;
word[m++]=ch;
}
else
{
syn=19;
p--;
}
break;
case '|':
word[m++]=ch;
ch=input[p++];
if(ch=='|')
{
syn=41;
word[m++]=ch;
}
else
{
syn=40;
p--;
}
break;
default:
syn=-1;
break;
}
}
//字符串结束符
word[m++]='\0';
}
4、实验结果
因为printf和""不是单词符号表中的符号,因而判定输入有错
文章来源:https://www.toymoban.com/news/detail-646746.html
完整实验报告:词法分析器的设计与实现-C文档类资源-CSDN文库文章来源地址https://www.toymoban.com/news/detail-646746.html
到了这里,关于词法分析器的设计与实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!