程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 一個小語言的詞法分析程序

一個小語言的詞法分析程序

編輯:關於VC++

前些天寫了個小語言的詞法分析程序,因為前些天在VC知識庫看到一個pascal詞法分析的程序,覺得寫得挺復雜的。其實詞法分析程序的原理都是一樣的,所以我想只要搞明白了簡單的詞法分析程序,再寫復雜的就不難了,無非是多加幾個關鍵字,多寫幾個條件判斷語句而已。詞法分析是編譯程序的基礎,也是最簡單的。好,現在讓我們看程序吧。

先讓我們看看這個小語言的文法吧。

G[<程序>]:

<程序>∷=<程序首部>;<分程序>.

<程序首部>∷=program<標識符>

<分程序>∷=<復合語句>

<復合語句>∷=begin<語句序列>end

<語句序列>∷=<語句>{;<語句>}

<語句>∷=<賦值語句>|<復合語句>|<條件語句>

<賦值語句>∷=<標識符>:=<表達式>

<條件語句>∷=if <布爾表達式> then <語句> else <語句>

<表達式>∷=<項>{(+|-)<項>}

<項>∷=<因式>{(*|/)<因式>}

<因式>∷=<標識符>|<無正負號常量>|’(’<表達式>’)’

<布爾表達式>∷=<表達式><關系運算符><表達式>

<關系運算符>∷= =|<|<=|>|>=|<>

<標識符>∷=<字母>{<字母>|<數字>}

<無正負號常量>∷=<數字>{<數字>}[.<數字>{<數字>}]

<字母>∷=a|b|c|d|e|f|g|……|u|v|w|x|y|z

<數字>∷=0|1|2|3|4|5|6|7|8|9

根據此文法,構造一詞法分析程序。輸入以“#”為結束符

按照這個文法,找出該語言的關鍵字,如program,begin,end ,if,then,else,以及其他一些特殊符號,然後再構造一個分析表,如下表: 單詞符號 類別編號 標識符 1 常數 2 if 3 then 4 else 5 program 6 begin 7 end 8 + 9 - 10 * 11 / 12 ( 13 ) 14 > 15 >= 16 < 17 <= 18 <> 19 := 20 ; 21 . 22 , 23

根據這個表來構造程序,程序的核心是下面的這個函數,

/********************************************************************
以下為主分析函數
從輸入文件裡面讀,把分析結果寫到輸出文件中
參數:fpin :輸入文件指針  fpout: 輸出文件指針
********************************************************************/
void parse(FILE* fpin,FILE* fpout)
{
	char arr[MAXBUF];//讀出的最長的字符串不超過MAXBUF,MAXBUF定義為255,夠長了我想
	int i=0;//分析含字母的字符串用
	int j=0;//分析純數字的字符串用
	while(1)
	{
	fscanf(fpin,"%c",&ch);//從輸入文件中讀入一個字符
		if( ch=='' ''|| ch ==''\t'')//過濾掉空格和tab
			;
		else if( ch==''\n'')//回車換行符,為下面進行錯誤判斷
			lineno++;
		else if( IsDigit(ch))//讀入的是數字
		{
			while(IsDigit(ch))
			{
				arr[j] = ch;
				j++;
				fscanf(fpin,"%c",&ch);
			}
		    fseek(fpin,-1L,SEEK_CUR);//文件指針後退一個字節
			char* temp1 =(char*)malloc(j+1);/
			memcpy(temp1,arr,j);
			temp1[j] =''\0'';//把數組裡面的內容拷貝到連外一個數組裡面,因為我定義的
			//arr為255個字節,實際上寫不到那麼多,所以只拷貝實際上有數據的
			j=0;//恢復初始狀態,以備下次使用
			fprintf(fpout,"%s\t\t%d\n",temp1,2);//常數
			free(temp1);//釋放內存
		}
		else if(IsAlpha(ch))//是字母開頭的
		{
			while(IsAlpha(ch) || IsDigit(ch))
			{
				arr[i] =ch;
				i++;
				fscanf(fpin,"%c",&ch);
			}
			fseek(fpin,-1L,SEEK_CUR);
			char* temp = (char*)malloc(i+1) ;
			memcpy(temp,arr,i);
			temp[i] =''\0'';
			i=0;
			/*基本思想同處理數字的*/
          if(FindOK(temp))//FindOK函數在關鍵字表中查找和temp字符串相同的,找到就返回類別編號
		  {
			 fprintf(fpout,"%s\t\t%d \n",temp,FindOK(temp));
		  }
		  else
		  {
			  fprintf(fpout,"%s\t\t%d\n",temp,1);//標示符號
		  }
		  free(temp);
		}
		//以下為2字節的運算符號
		else if( ch=='':'')//符號“:=”
		{
			fscanf(fpin,"%c",&ch);
			if(ch==''='')
				fprintf(fpout,"%s\t\t%d\n",":=",20);
		else
			fprintf(fpout,"error in compileing %d lines unknown character %c \n",lineno,ch);//出錯了
		}
		else if(ch==''>'')//符號 “> “ 和”>=”
		{
			fscanf(fpin,"%c",&ch);
			if(ch==''='')
			fprintf(fpout,"%s\t\t%d\n",">=",16);
			else
			fprintf(fpout,">\t\t15\n");
		}
		else if( ch==''<'') //符號 “< “ 和”<=”
		{
			fscanf(fpin,"%c",&ch);
			if(ch==''='')
			{fprintf(fpout,"<=\t\t18\n");}
			else if( ch==''>'')
			{fprintf(fpout,"<>\t\t19");}
			else
			{fprintf(fpout,"<\t\t19\n");}
		}
		else {
	   	//以下為一個字節的運算符號
		if(ch==''-'') {fprintf(fpout,"%s\t\t%d\n",''-'',10);continue;}//在文件中輸出為“-   10”
		if(ch=='';'') {fprintf(fpout,";\t\t21\n");continue;}
		if(ch==''+'') {fprintf(fpout,"+\t\t9\n");continue;}
		if(ch==''*'') {fprintf(fpout,"*\t\t11\n");continue;}
		if(ch==''/'') {fprintf(fpout,"/ \t\t12\n");continue;}
		if(ch==''('') {fprintf(fpout,"(\t\t13\n");continue;}
		if(ch=='')'') {fprintf(fpout,")\t\t14\n");continue;}
		if(ch==''.'') {fprintf(fpout,".\t\t22\n");continue;}
		if(ch=='','') {fprintf(fpout,",\t\t23\n");continue;}
		if(ch==''#'') break;//分析結束
		else fprintf(fpout,"error in compileing %d lines unknown character %c \n",lineno,ch);//出錯了,輸出出錯信息
		}
	}
}

其他請看源代碼,注釋很詳細,但是肯定有不足的地方,請大家吝賜教。有什麼問題,可以給我發郵件。這是我第一次向VC知識庫投稿,以後將會陸續寫一些VC方面的程序來和大家共享。我的email:[email protected],QQ:110902663, 謝謝大家。

本文配套源碼

  1. 上一頁:
  2. 下一頁:
欄目導航
Copyright © 程式師世界 All Rights Reserved