欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C/C++實(shí)現(xiàn)詞法分析程序的示例代碼

 更新時(shí)間:2023年05月24日 09:36:19   作者:Aricl.  
這篇文章主要為大家詳細(xì)介紹了如何基于C/C++實(shí)現(xiàn)一個(gè)簡(jiǎn)單的詞法分析程序,并通過(guò)完成詞法分析程序,了解詞法分析的過(guò)程,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)

一、實(shí)驗(yàn)內(nèi)容

通過(guò)完成詞法分析程序,了解詞法分析的過(guò)程。編制一個(gè)讀單詞程序,對(duì)PL/0語(yǔ)言進(jìn)行詞法分析,把輸入的字符串形式的源程序分割成一個(gè)個(gè)單詞符號(hào),即基本保留字、標(biāo)識(shí)符、常數(shù)、運(yùn)算符、分界符五大類(lèi)。

對(duì)PL/0語(yǔ)言進(jìn)行詞法分析,把輸入的字符串形式的源程序分割成一個(gè)個(gè)單詞符號(hào),其詞法描述如下:

(1)關(guān)鍵字:

begin,call,const,do,end,if,odd,procedure,read,then,var,while,write

(2) 標(biāo)識(shí)符:用來(lái)表示各種名字,必須以字母開(kāi)頭小于10位字符組成

(3) 數(shù)字:以0-9組成小于14位的數(shù)字

(4) 運(yùn)算符:+,-,*,/,:=,<,<=,>,>=,#

(5) 分界符:, ,. ,; ,( ,)

二、實(shí)驗(yàn)代碼

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<iomanip>
using namespace std;
//創(chuàng)建四個(gè)表,儲(chǔ)存符號(hào) 
const char *k[13]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write"};//關(guān)鍵字表
const char *s1[5]={",",".",";","(",")"};//界符表
const char *s2[6]={"+","-","*","/","++","--",};//運(yùn)算符號(hào)表 
const char *s3[9]={"<=",">",">=","=",">",">=","<>",":=","#"}; //關(guān)系運(yùn)算符號(hào)表 
//定義全局變量
int row=1,line=1; 
int t,p=0;//單詞類(lèi)別碼以及記錄移動(dòng)指針
char instring[100];//保存輸入的程序代碼緩存數(shù)組
char outtoken[10];//輸出
char ci[8],id[10];//暫時(shí)保存數(shù)字和字符
//函數(shù)的聲明
void analysis();//分析函數(shù),決定調(diào)用哪個(gè)函數(shù)進(jìn)行分析
void symbol();//分析以非字母數(shù)字開(kāi)頭的字符
void constant();//分析常數(shù)
void alphabet();//分析標(biāo)識(shí)符和關(guān)鍵字
void show();//打印輸出函數(shù)
bool isnumber(char x);//判斷是否是數(shù)字 
bool isalpha(char x);//判斷是否是字母 
int main(){
	cout<<"請(qǐng)輸入一段程序代碼并以@結(jié)束:"<<endl;
	//輸出程序代碼 
	do{
		instring[p++]=getchar();
	} while(instring[p-1]!='@'); 
	getchar();//吸收回車(chē)鍵 
	instring[p-1]='\0';//抵消掉@
	p=0;//移動(dòng)指針歸零
	cout<<left;
	cout<<"------------------------------------------------------------------------------"<<endl; 
	cout<<setw(6)<<"單詞"<<"			"<<setw(6)<<"二元序列"<<"			"<<setw(6)<<"類(lèi)型"<<"			"<<endl;
	//掃描輸入的字符 
	while(p<strlen(instring)){
		analysis();
		show();
	} 
	cout<<"------------------------------------------------------------------------------"<<endl; 
	cout<<"[注]:"<<endl;
	cout<<"t=1:關(guān)鍵字,"<<"t=2:分界符,"<<"t=3:算術(shù)運(yùn)算符,"<<"t=4:關(guān)系運(yùn)算符,"<<"t=5:常數(shù),"<<"t=6:標(biāo)識(shí)符,"<<"t==7:詞法出錯(cuò)"<<endl; 
	cout<<"@為結(jié)束符,不參與到詞法分析中"<<endl; 
	cout<<endl;
	return 0;
} 
//判斷是否是數(shù)字
bool isnumber(char x){
	return x>='0'&&x<='9';
}
//判斷是否是字母
bool isalpha(char x){
	return (x>='a'&&x<='z'||x>='A'&&x<='Z');
}
//分析函數(shù),決定調(diào)用哪個(gè)函數(shù)進(jìn)行分析
void analysis(){
	strcpy(outtoken,"");//清空outtoken數(shù)組
	while(instring[p]==' '||instring[p]=='\n'){
		if(instring[p]=='\n'){
			row++;
			line=1;
		}
		p++;
	} 
	//執(zhí)行完之后指向第一個(gè)不為空格的字符
	char ch=instring[p];
	//按照字符的類(lèi)別調(diào)用不同的分析處理函數(shù) 
	if(isalpha(ch))
	   alphabet();
	else if(isnumber(ch))
		constant();
	else 
		symbol();
}
//常數(shù)處理函數(shù)
void constant(){
	strcpy(ci,"");//清空ci
	t=5;//類(lèi)別碼
	int i=0;
	while(isnumber(instring[p])){
		ci[i++]=instring[p++]; 
	} 
	while(isalpha(instring[p])||isnumber(instring[p])){
		ci[i++]=instring[p++];
		t=7;//出錯(cuò) 
	}
	ci[i]='\0';//結(jié)束符
	//strcpy_s(outtoken,strlen(ci)+1,ci);
	strcpy(outtoken,ci);
	line++;
	return; 
} 
//標(biāo)識(shí)符和關(guān)鍵字的分析函數(shù)
void  alphabet(){
	strcpy(id,"");//清空id
	int i=0;
	//讀取連續(xù)的字母數(shù)字序列 
	while(isalpha(instring[p])||isnumber(instring[p])){
		id[i++]=instring[p++];//p指向連續(xù)序列之后的第一個(gè)字符 
	} 
	id[i]='\0';
	//查關(guān)鍵字表 
	for(i=0;i<8;i++){
		if(strcmp(id,k[i])==0){
			t=1;//表示關(guān)鍵字
			line++;
			strcpy(outtoken,id);
			return; //是關(guān)鍵字的話,直接退出 
		}
	}
	//查看是否是標(biāo)識(shí)符
	for(i=0;i<strlen(id);i++){
		if(!(isalpha(id[i])||isnumber(id[i]))){
			t=7;
			strcpy(outtoken,id);
			line++;
			return;
		}
	} 
	line++;
	t=6;//不是關(guān)鍵字且沒(méi)有出錯(cuò)即為標(biāo)識(shí)符
	strcpy(outtoken,id);
}
//其它運(yùn)算符的分析函數(shù)
void symbol(){
	char ch=instring[p++];
	char ch2=instring[p];
	t=7;
	switch(ch){
		case '+':
			if(ch2=='+')
			  t=3;
			break;
		case '-':
			if(ch2=='-')
			  t=3;
			break;
		case '>':
			if(ch2=='=')
			  t=4;
			break;
		case '<':
			if(ch2=='='||ch2=='>')
			  t=4;
			break;
		case ':':
			if(ch2=='=')
			  t=3;
			break;
	}
	//判斷是否具有兩個(gè)符號(hào)的運(yùn)算符
	if(ch=='>'&&ch2=='='||ch=='<'&&ch2=='='||ch=='<'&&ch2=='>'||ch=='+'&&ch2=='+'||ch=='-'&&ch2=='-'||ch==':'&&ch2=='='){
		p++;
		outtoken[0]=ch;
		outtoken[1]=ch2;
		outtoken[2]='\0';
		line++;
		return;
	} else{
		char chq[2];
		chq[0]=ch;
		chq[1]='\0';
		//分界符比較 
		for(int i=0;i<6;i++){
			if(strcmp(chq,s1[i])==0){
				t=2;
				break;
			}
		}	
		//算術(shù)運(yùn)算符比較 
		for(int i=0;i<6;i++){
			if(strcmp(chq,s2[i])==0){
				t=3;
				break;
			}
		}	
		//關(guān)系運(yùn)算符比較 
		for(int i=0;i<9;i++){
			if(strcmp(chq,s3[i])==0){
				t=4;
				break;
			}
		}
	}
	line++;
	outtoken[0]=ch;
	outtoken[1]='\0';
	return;
} 
//輸出函數(shù),根據(jù)以上分析函數(shù)進(jìn)行打印輸出分析的結(jié)果
void show(){
	cout<<left;
	//setw(6)表示占位寬度為6個(gè)字符 
	if(t==7){
		cout<<setw(6)<<outtoken<<"			"<<setw(6)<<"ERROR!"<<setw(11)<<" "<<setw(10)<<"ERROR!";
	}else{
		cout<<left;
		cout<<setw(6)<<outtoken<<"			"<<"<"<<t<<","<<outtoken;
		cout<<setw(6-strlen(outtoken))<<">"<<"			";
		switch(t){
			case 1:cout<<left<<setw(10)<<"關(guān)鍵字";break;
			case 2:cout<<left<<setw(10)<<"分界符";break;
			case 3:cout<<left<<setw(10)<<"算術(shù)運(yùn)算符";break;
			case 4:cout<<left<<setw(10)<<"關(guān)系運(yùn)算符";break;
			case 5:cout<<left<<setw(10)<<"常數(shù)";break;
			case 6:cout<<left<<setw(10)<<"標(biāo)識(shí)符";break;
		}
	} 
	cout<<endl;
} 
/*變量說(shuō)明: 
k數(shù)組:關(guān)鍵字表; s數(shù)組:分界符表,其中分界符,算術(shù)運(yùn)算符,關(guān)系運(yùn)算符分別存放在s1,s2,s3數(shù)組中 
id:標(biāo)識(shí)符; ci:常數(shù) ;row:行 line:列,單詞的位置 
instring數(shù)組:為輸入源程序代碼的單詞緩存; outtoken數(shù)組:記錄為輸出內(nèi)部表示緩存
 symbol:分析//后的注釋;constant:常數(shù)分析;alphabet:標(biāo)識(shí)符和關(guān)鍵字分析
analysis:分析函數(shù),根據(jù)輸入字符判斷調(diào)用哪一個(gè)函數(shù) ;show:輸出打印函數(shù)
t:單詞的種類(lèi) t=1:關(guān)鍵字 t=2:分界符 t=3:算術(shù)運(yùn)算符 t=4:關(guān)系運(yùn)算符 t=5:常數(shù) t=6:標(biāo)識(shí)符 t=7:出錯(cuò)*/

三、實(shí)驗(yàn)結(jié)果

測(cè)試一

測(cè)試二

四、實(shí)驗(yàn)總結(jié)

整體的代碼思路是創(chuàng)建四個(gè)數(shù)組分別存放關(guān)鍵字表、界符表、運(yùn)算符號(hào)表、關(guān)系運(yùn)算符號(hào)表,這樣若想新增符號(hào)只需要在數(shù)組中修改即可,實(shí)現(xiàn)動(dòng)態(tài)變化而非寫(xiě)死的。

下面進(jìn)行模塊化設(shè)計(jì),總共分為analysis()、symbol()、constant()、alphabet()、show()、isnumber()、isalpha()七個(gè)函數(shù),analysis函數(shù)作為總的分析函數(shù),通過(guò)分析當(dāng)前字符是否是字母還是數(shù)字或者其它符號(hào),分別調(diào)用不同的函數(shù)進(jìn)行具體的分析,然后將結(jié)果存儲(chǔ)在全局變量outtoken和t中,前者代表輸出的二元組,后者代表該單詞的類(lèi)型,難點(diǎn)在于兩個(gè)符號(hào)的運(yùn)算符的判斷。

本題還有一個(gè)細(xì)節(jié)之處,在輸入完代碼后敲的那個(gè)回車(chē)鍵會(huì)多余需要使用一個(gè)getchar()函數(shù)來(lái)吸收掉,并且結(jié)束符@為自定義的,不參與到詞法分析中,所以在輸入完程序代碼后使用instring[p-1]='\0';//抵消掉@,這樣就使得instring數(shù)組里存放的是完整的有效的程序代碼,不含結(jié)束符。

到此這篇關(guān)于C/C++實(shí)現(xiàn)詞法分析程序的示例代碼的文章就介紹到這了,更多相關(guān)C++詞法分析內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一篇文章徹底搞懂C++常見(jiàn)容器

    一篇文章徹底搞懂C++常見(jiàn)容器

    容器就是一些特定類(lèi)型對(duì)象的集合,容器可以分為順序容器和關(guān)聯(lián)容器,下面這篇文章主要給大家介紹了關(guān)于C++常見(jiàn)容器的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-02-02
  • C++?Queue隊(duì)列類(lèi)模版實(shí)例詳解

    C++?Queue隊(duì)列類(lèi)模版實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹C++?Queue隊(duì)列類(lèi)模版實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02
  • C++內(nèi)存池的簡(jiǎn)單實(shí)現(xiàn)

    C++內(nèi)存池的簡(jiǎn)單實(shí)現(xiàn)

    內(nèi)存池是一種動(dòng)態(tài)內(nèi)存分配與管理技術(shù)。本文主要介紹了C++內(nèi)存池的簡(jiǎn)單實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • C++之文件輸入/輸出流類(lèi)解讀

    C++之文件輸入/輸出流類(lèi)解讀

    這篇文章主要介紹了C++之文件輸入/輸出流類(lèi),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • VSCode 配置C++開(kāi)發(fā)環(huán)境的方法步驟

    VSCode 配置C++開(kāi)發(fā)環(huán)境的方法步驟

    這篇文章主要介紹了VSCode 配置C++開(kāi)發(fā)環(huán)境的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • 基于C語(yǔ)言實(shí)現(xiàn)點(diǎn)餐系統(tǒng)

    基于C語(yǔ)言實(shí)現(xiàn)點(diǎn)餐系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言實(shí)現(xiàn)點(diǎn)餐系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • C++左值引用與指針的區(qū)別及說(shuō)明

    C++左值引用與指針的區(qū)別及說(shuō)明

    左值引用與指針的區(qū)別:左值引用是一個(gè)別名,只能綁定左值,對(duì)左值引用的訪問(wèn)與訪問(wèn)左值是相同的;指針是一個(gè)變量,該變量在內(nèi)存中存在真是的物理地址,該變量?jī)?nèi)的存儲(chǔ)的是一個(gè)內(nèi)存地址,訪問(wèn)指針變量對(duì)應(yīng)的內(nèi)容需要配合解訪問(wèn)符*
    2025-03-03
  • 對(duì)C語(yǔ)言編程標(biāo)準(zhǔn)以及聲明的基本理解

    對(duì)C語(yǔ)言編程標(biāo)準(zhǔn)以及聲明的基本理解

    這篇文章主要介紹了對(duì)C語(yǔ)言編程標(biāo)準(zhǔn)以及聲明的基本理解,有助于對(duì)C語(yǔ)言編寫(xiě)時(shí)的結(jié)構(gòu)有更加清晰的認(rèn)識(shí),需要的朋友可以參考下
    2015-11-11
  • C++如何計(jì)算二進(jìn)制數(shù)中1的個(gè)數(shù)

    C++如何計(jì)算二進(jìn)制數(shù)中1的個(gè)數(shù)

    這篇文章主要介紹了C++如何計(jì)算二進(jìn)制數(shù)中1的個(gè)數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • C++中名稱空間namespace的使用方法示例

    C++中名稱空間namespace的使用方法示例

    namespace中文意思是命名空間或者叫名字空間,下面這篇文章主要給大家介紹了關(guān)于C++中名稱空間namespace使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧。
    2017-12-12

最新評(píng)論