词法分析器的设计与实现

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、状态转换图

词法分析器的设计与实现_第1张图片

2.4、算法分析

        ①词法分析器工作的第一步是输入源程序文本。为了更好地对单词符号识别,把输入串预处理一下。预处理主要滤掉空格,跳过注释、换行符等。

        ②对预处理后的输入串依次扫描单个字符,使用if-while嵌套语句和switch case语句判断字符的类型,具体识别方法可看状态转换图。有时为了确定词性,需要超前扫描,若超前扫描的字符对识别当前单词无用处,则需要退还给输入串,以备识别下一单词字符时使用。

        ③若读入的字符与单词符号编码表的字符匹配不上,则报错,并输出出错行数。对识别处的单词符号以(单词符号,种别码)二元式的形式输出。

3、实验内容

3.1、流程图

词法分析器的设计与实现_第2张图片

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 
#include 

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、实验结果

词法分析器的设计与实现_第3张图片

因为printf和""不是单词符号表中的符号,因而判定输入有错

 词法分析器的设计与实现_第4张图片

 词法分析器的设计与实现_第5张图片

 完整实验报告:词法分析器的设计与实现-C文档类资源-CSDN文库

你可能感兴趣的:(课程设计,c语言,课程设计)