词法分析——判断单词类别并输出

这篇博客介绍了词法分析的基本概念,包括关键字、运算符、标识符和整型常数的定义,并展示了词法分析程序的功能。该程序接收源程序字符串,输出单词类别和对应的字符串或数值。文章提到了状态转换图方法,并讨论了设计过程和技术难点,如结束标记的选择和字符映射的建立。

词法分析小程序。

实验目的

1.待分析的简单的词法

(1)关键字:

   begin  if then  while  do end 

注:所有的关键字都是小写。

(2)运算符和界符

. + -  *  /   =<>  <  <= > >=  (  ) ; :=

(3)其他单词是标识符(IDENT)和整型常数(NUMBER),通过以下正规式定义:

IDENT  ::= letter (letter |digit)*

NUMBER ::= digit digit*

注:所有的IDENTNUMBER的长度不超过20

(4)空格有空白、制表符和换行符组成。空格一般用来分隔IDENT、NUMBER、运算符、界符和关键字,词法分析阶段通常被忽略。整个程序串长度不超过80个字符。

2. 各种单词符号对应的类别值:

表 各种单词符号对应的类别码

单词符号

是否保留字

枚举值

类别码

.

 

period

0

+

 

plus

1

-

 

minus

2

*

 

times

3

/

 

slash

4

=

 

eql

5

<> 

 

neq

6

 

lss

7

<=

 

leq

8

 

gtr

9

>=

 

geq

10

(

 

lparen

11

)

 

rparen

12

;

 

semicolon

13

:=

 

becomes

14

begin

Y

beginsym

15

end

Y

endsym

16

if

Y

ifsym

17

then

Y

thensym

18

while

Y

whilesym

19

do

Y

dosym

20

IDENT

 

ident

21

NUMBER

 

number

22

 

3. 词法分析程序的功能:

输入:所给文法的源程序字符串,以“.”结束。

输出:二元组(sym, token或number)构成的序列。

其中:sym为单词种别

      token为存放的单词自身字符串;

      number为整型常数。对于数值串需要转化为实际的值。

示例

源程序:begin x:=9;if x<10 then x:=(x+10)*2 end.

经过词法分析后输出如下序列:(15,begin)(21,x)(14,:=)(22,9)(13,;)……

 

4. 词法分析程序的设计

1)词法分析识原理采用状态转换图方法:    



设计思路

1.实验的设计方法:遍历字符串,模拟判断。


2.设计流程描述:

字符对应表

 

增加保留字表:

 

判断过程:

 

3.主要技术难点:

       1)结束标记:这里选择使用‘.’作为结束标记

       2)设计我们要判断的字符对应表

       3)建立字符和字符对应表之间的映射


代码:

#include <bits/stdc++.h>
using namespace std;

/*
变量说明:
 line	从终端读入的字符串;		当前所指位置在计数器 p, 字符为ch
 token	正在识别的单词字符串;  当前所指位置在计数器 m
 num	整型常数
 sym	每个单词符号种类
 word	保留字表
*/

enum symbol {
	period=0,
	Plus=1,
	Minus=2,
	times=3,
	slash=4,
	eql=5,
	neq=6,
	lss=7,
	leq=8,
	gtr=9,
	geq=10,
	lparen=11,
	rparen=12,
	semicolon=13,
	becomes=14,
	beginsym=15,
	endsym=16,
	ifsym=17,
	thensym=18,
	whilesym=19,
	dosym=20,
	ident=21,
	number=22,
    note=23,
	nil,
};

char line[80],token[8],ch;
int p,m, num;
enum symbol sym;
char* word[6]={"begin","if","then","while","do","end"};

void getsym();
void printsym(enum symbol sym);

int  main()
{
	freopen("t.txt","r",stdin);
	//读了字符串, 直到遇.结束
	p=0;
	printf("\n please input a string(end with '.'): \n");
	do
	{
		scanf("%c",&ch);
		line[p++]=ch;
    }while(ch!='.');
	line[p++]='\0';

	//逐个单词扫描;
	p=0;
	do
	{
		getsym();		//当前扫描的单词存放在syn中
		printsym(sym);
	} while (sym != period);
	getchar();

	return 0;
}

void getsym()
{

	for(m=0; m<8;m++) token[m++]=NULL;
	ch=line[p++];
	m=0;
	/************************************************
  ****									                     	****
	****         TODO: 单词识别                 ****
	****                                        ****
	*************************************************/
	while((ch==' '||ch=='\n')) ch=line[p++];
	//字母打头的字符串;标识符
	if((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A'))
	{
		do
		{
			token[m++]=ch;
			ch=line[p++];
		}while((ch<='z'&&ch>='a')||(ch<='Z'&&ch>='A')||(ch<='9'&&ch>='0'));
		sym=ident;
		token[m++]='\0';
		ch=line[p--];
		for(int n=0;n<6;n++)
		{
			if(strcmp(token,word[n])==0)
			{
				if(n==0) sym=beginsym;
				else if(n==1) sym=endsym;
				else if(n==2) sym=ifsym;
				else if(n==3) sym=thensym;
				else if(n==4) sym=whilesym;
				else if(n==5) sym=dosym;
				break;
			}
		}

		/*TODO识别标识符IDENT和保留字*/

	}
	else if((ch<='9'&&ch>='0'))
	{
		num=0;
		do{
			num=num*10+ch-'0';
			ch=line[p++];
		}while((ch<='9'&&ch>='0'));
		ch=line[p--];
		sym=number;
		/*TODO识别数字NUMBER*/
	}
	else {
		switch(ch)
		{
		case ':':		//赋值符号
			token[m++]=ch;
			ch=line[p++];
			if(ch=='=')
			{
				sym=becomes;
				token[m++]=ch;
			}
			else{
				sym=nil;
			}
			break;
		case '<':		//<=和<符号
			token[m++]=ch;
			ch=line[p++];
			if(ch=='=')
			{
				token[m++]=ch;
				sym=leq;
			}
			else if(ch=='>'){
				token[m++]=ch;
				sym=neq;
			}
			else{
				sym=lss;
				p--;
			}
			break;
		case '>':		//>=和>符号
			token[m++]=ch;
			ch=line[p++];
			if(ch=='=')
			{
				sym=geq;
				token[m++]=ch;
			}
			else{
				sym=gtr;
				p--;
			}
			break;
		case '+':
			sym=Plus;
			token[m++]=ch;
			break;
		case '-':
			sym=Minus;
			token[m++]=ch;
			break;
		case '*':
			sym=times;
			token[m++]=ch;
			break;
		case '/':
			ch=line[p++];
			if(ch=='*'){
				//cout<<"in\n";
				char fr;//前面的一个符号
				fr='*';
				ch=line[p++];
				while(1){
					fr=ch;
					ch=line[p++];
					if(fr=='*'&&ch=='/') break;
				}
				sym=note;
				token[m++]=ch;
			}
			else
			{
				sym=slash;
				token[m++]=ch;
				p--;
			}
			break;
		case '=':
			sym=eql;
			token[m++]==ch;
			break;
		case '(':
			sym=lparen;
			token[m++]=ch;
			break;
		case ')':
			sym=rparen;
			token[m++]=ch;
			break;
		case ';':
			sym=semicolon;
			token[m++]=ch;
			break;
		case '.':
			sym=period;
			token[m++]=ch;
			break;
		case ' ':
			token[m++]=ch;
			break;
		default:
			sym=nil;
			break;
		}
	}
	token[m++]='\0';
}

void printsym(enum symbol sym)
{

	/************************************************
  ****										                    ****
	****         TODO: 输出单词                  ****
	****                                        ****
	*************************************************/
	switch(sym)
	{
	case period:
		return;
	case number:
		printf("(    number,%-10d)\n",num);
		break;
	case nil:
		printf("you have input a wrong string\n");
		break;
	case note:
		printf("this is notes\n");
		break;
	case Plus:
		printf("(      Plus,%-10s)\n","+");
		break;
	case Minus:
		printf("(     Minus,%-10s)\n","-");
		break;
	case times:
		printf("(     times,%-10s)\n","*");
		break;
	case slash:
		printf("(     slash,%-10s)\n","/");
		break;
	case eql:
		printf("(       eql,%-10s)\n","=");
		break;
	case neq:
		printf("(       neq,%-10s)\n","><");
		break;
	case lss:
		printf("(       lss,%-10s)\n","<");
		break;
	case leq:
		printf("(       leq,%-10s)\n","<=");
		break;
	case gtr:
		printf("(       gtr,%-10s)\n",">");
		break;
	case geq:
		printf("(       geq,%-10s)\n",">=");
		break;
	case lparen:
		printf("(    lparen,%-10s)\n","(");
		break;
	case rparen:
		printf("(    rparen,%-10s)\n",")");
		break;
	case semicolon:
		printf("( semicolon,%-10s)\n",";");
		break;
	case becomes:
		printf("(   becomes,%-10s)\n",":=");
		break;
	case beginsym:
		printf("(  beginsym,%-10s)\n","begin");
		break;
	case endsym:
		printf("(    endsym,%-10s)\n","end");
		break;
	case ifsym:
		printf("(     ifsym,%-10s)\n","if");
		break;
	case thensym:
		printf("(   thensym,%-10s)\n","then");
		break;
	case whilesym:
		printf("(  whilesym,%-10s)\n","while");
		break;
	case dosym:
		printf("(     dosym,%-10s)\n","do");
		break;
	case ident:
		printf("(     ident,%-10s)\n",token);
		break;
	default:
		break;
	}


}



结果截屏:



 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值