词法分析器的设计与实现

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、源代码

cpp 复制代码
#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和""不是单词符号表中的符号,因而判定输入有错

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

相关推荐
Zer0_on4 小时前
数据结构栈和队列
c语言·开发语言·数据结构
一只小bit4 小时前
数据结构之栈,队列,树
c语言·开发语言·数据结构·c++
马浩同学5 小时前
【GD32】从零开始学GD32单片机 | DAC数模转换器 + 三角波输出例程
c语言·单片机·嵌入式硬件·mcu
一个没有本领的人5 小时前
win11+matlab2021a配置C-COT
c语言·开发语言·matlab·目标跟踪
一只自律的鸡5 小时前
C项目 天天酷跑(下篇)
c语言·开发语言
长安——归故李6 小时前
【C语言】成绩等级制
c语言·开发语言
青い月の魔女7 小时前
数据结构初阶---二叉树
c语言·数据结构·笔记·学习·算法
苹果醋38 小时前
React系列(八)——React进阶知识点拓展
运维·vue.js·spring boot·nginx·课程设计
最后一个bug8 小时前
STM32MP1linux根文件系统目录作用
linux·c语言·arm开发·单片机·嵌入式硬件
FeboReigns8 小时前
C++简明教程(4)(Hello World)
c语言·c++