C語言實現(xiàn)詞法分析器
問題描述:
用C或C++語言編寫一個簡單的詞法分析程序,掃描C語言小子集的源程序,根據(jù)給定的詞法規(guī)則,識別單詞,填寫相應(yīng)的表。如果產(chǎn)生詞法錯誤,則顯示錯誤信息、位置,并試圖從錯誤中恢復(fù)。簡單的恢復(fù)方法是忽略該字符(或單詞)重新開始掃描。
相關(guān)詞法規(guī)則
<標(biāo)識符>::=<字母> 
<標(biāo)識符>::=<標(biāo)識符><字母> 
<標(biāo)識符>::=<標(biāo)識符><數(shù)字> 
<常量>::=<無符號整數(shù)> 
<無符號整數(shù)>::=<數(shù)字序列> 
<數(shù)字序列>::=<數(shù)字序列><數(shù)字> 
<數(shù)字序列>::=<數(shù)字> 
<字母>::=a|b|c|……|x|y|z 
<數(shù)字>::=0|1|2|3|4|5|6|7|8|9 
<加法運算符>::=+|- 
<乘法運算符>::=*|/ 
<關(guān)系運算符>::=<|>|!=|>=|<=|== 
<分界符>::=,|;|(|)|{|} 
<保留字>::=main|int|if|else|while|do
編寫詞法分析程序的步驟:
(1)確定所要翻譯的語言(或其子集)。
C語言
(2)設(shè)計屬性字,及各類表格,如標(biāo)識符表、常量表、符號及其機內(nèi)表示對照表等。
與詞法分析有關(guān)的表格:
1. 字符表
保留字:main,int,if,else,while,do 
字母(全小寫):a|b|c|……|x|y|z 
數(shù)字:0,1,2,3,4,5,6,7,8,9 
運算符和界符:<,>,!=,>=,<=,==,,,;,(,),{,}
2. 特定單詞機內(nèi)表示表
3.畫出總控流程圖及各個子程序的流程圖。
4. 程序
輸入:一個存放C語言程序的s.txt文件 
輸出:存放以(單詞,種別碼)形式輸出的result.txt文件
需要6個數(shù)組:
1. 存儲關(guān)鍵字 key[6] 
2. 存儲對應(yīng)下標(biāo)關(guān)鍵字的種別碼 keyNum[6] 
3. 存儲運算符和界符 symbol[17] 
4. 存儲運算符對應(yīng)下標(biāo)的種別碼 symbolNum[17] 
5. 存儲從文件中取出的每個字符(不包括括號)letter[1000]
主要函數(shù):
TakeWord();
功能:將文件letter[]中每個字符進行提取,找出關(guān)鍵字,輸出種別碼
Num作為全局變量保存提取到字符的哪個下標(biāo)
1. 先提取一個字符,如果是字母,進入case1,調(diào)用identifier(),不斷的提取字母或數(shù)字進行連接,沒連接一個字符用int isKeyWord()程序(返回關(guān)鍵字種別碼)判斷是否為關(guān)鍵字,是就退出函數(shù)返回string,不是就繼續(xù)執(zhí)行函數(shù),直到連接的字符不再是字母或數(shù)字,即此時字符串為標(biāo)識符
2. 如果是數(shù)字,進入case 2,調(diào)用Number()函數(shù),不斷進行字符串連接,知道下一個連接字符不再是數(shù)字
3. 如果是符號,進入case 3,調(diào)用symbolStr()函數(shù),如果是=,>,<,!,則要繼續(xù)進行下個字符判斷,其余符號可以直接返回
其他輔助函數(shù):
int isSymbol()判斷運算符和界符,并返回種別碼 
bool isNum() 判斷是否為數(shù)字 
bool isLetter()判斷是否為字母 
int isKeyWord()判斷是否為關(guān)鍵字,是返回種別碼 
int typeword()返回單個字符的類型 
string identifier()標(biāo)識符的連接 
string symbolStr()符號和界符的連接 
string Number()數(shù)字的連接 
void print()輸出
程序:
#include <iostream>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
using namespace std;
//關(guān)鍵字 
string key[6]={"main","int","if","else","while","do"}; 
//關(guān)鍵字的種別碼
int keyNum[6]={1,2,3,4,5,6}; 
//運算符和界符 
string symbol[17]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="};
//char symbol[12]={'<','>','!=','>=','<=','==',',',';','(',')','{','}'};
//運算符和界符的種別碼 
int symbolNum[17]={7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
//存放文件取出的字符 
string letter[1000];
//將字符轉(zhuǎn)換為單詞
string words[1000];
int length; //保存程序中字符的數(shù)目 
int num;
int isSymbol(string s){ //判斷運算符和界符 
 int i;
 for(i=0;i<17;i++){
  if(s==symbol[i])
   return symbolNum[i]; 
 }
 return 0;
} 
//判斷是否為數(shù)字 
bool isNum(string s){
 if(s>="0" && s<="9")
  return true;
 return false;
}
//判斷是否為字母 
bool isLetter(string s)
{
 if(s>="a" && s<="z")
  return true;
 return false;
}
//判斷是否為關(guān)鍵字,是返回種別碼 
int isKeyWord(string s){
 int i;
 for(i=0;i<6;i++){
  if(s==key[i])
   return keyNum[i];
 }
 return 0;
}
//返回單個字符的類型 
int typeword(string str){
 if(str>="a" && str<="z") // 字母 
  return 1;
 if(str>="0" && str<="9") //數(shù)字 
  return 2;
 if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}"
  ||str=="+"||str=="-"||str=="*"||str=="/") //判斷運算符和界符 
  return 3; 
}
string identifier(string s,int n){
 int j=n+1;
 int flag=1;
 while(flag){
  if(isNum(letter[j]) || isLetter(letter[j])){
   s=(s+letter[j]).c_str();
   if(isKeyWord(s)){
    j++;
    num=j;
    return s;
   }
   j++;
  }
  else{
   flag=0;
  }
 } 
 num=j;
 return s;
}
string symbolStr(string s,int n){
 int j=n+1;
 string str=letter[j];
 if(str==">"||str=="="||str=="<"||str=="!") {
  s=(s+letter[j]).c_str();
  j++;
 }
 num=j;
 return s;
}
string Number(string s,int n){
 int j=n+1;
 int flag=1;
 while(flag){
  if(isNum(letter[j])){
   s=(s+letter[j]).c_str();
   j++;
  }
  else{
   flag=0;
  }
 }
 num=j;
 return s;
}
void print(string s,int n){
 cout<<"("<<s<<","<<n<<")"<<endl;
}
void TakeWord(){ //取單詞 
 int k;
 for(num=0;num<length;){
  string str1,str;
  str=letter[num];
  k=typeword(str);
  switch(k){
   case 1:
    {
     str1=identifier(str,num);
     if(isKeyWord(str1))
      print(str1,isKeyWord(str1));
     else
      print(str1,0);
     break;
    }
   case 2:
    {
     str1=Number(str,num);
     print(str1,24);
     break;
    }
   case 3:
    {
     str1=symbolStr(str,num);
     print(str1,isSymbol(str1));
     break; 
    }
  }
 } 
}
int main(){
 char w;
 int i,j;
 freopen("s.txt","r",stdin);
 freopen("result.txt","w",stdout); //從控制臺輸出,而不是文本輸出
 length=0;
 while(cin>>w){
  if(w!=' '){
   letter[length]=w;
   length++;
  } //去掉程序中的空格
 }
 TakeWord();
// for(j=0;j<length;j++){
//  cout<<letter[j]<<endl;
// } 
 fclose(stdin);//關(guān)閉文件 
 fclose(stdout);//關(guān)閉文件 
 return 0;
} 
運行結(jié)果:
s.txt
Result.txt
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
您可能感興趣的文章
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用函數(shù)刪除字符
 - 04-02c語言的正則匹配函數(shù) c語言正則表達式函數(shù)庫
 - 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
 - 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對數(shù)怎么表達
 - 04-02c語言用函數(shù)寫分段 用c語言表示分段函數(shù)
 - 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排序法函數(shù)
 - 04-02c語言沒有round函數(shù) round c語言
 - 04-02c語言分段函數(shù)怎么求 用c語言求分段函數(shù)
 - 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
 - 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求階乘
 


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
 - 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
 - 04-02c語言的正則匹配函數(shù) c語言正則表達
 - 04-02c語言用函數(shù)寫分段 用c語言表示分段
 - 04-02c語言中對數(shù)函數(shù)的表達式 c語言中對
 - 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
 - 04-02c語言沒有round函數(shù) round c語言
 - 04-02c語言分段函數(shù)怎么求 用c語言求分段
 - 04-02C語言中怎么打出三角函數(shù) c語言中怎
 - 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
 
隨機閱讀
- 04-02jquery與jsp,用jquery
 - 01-10delphi制作wav文件的方法
 - 08-05DEDE織夢data目錄下的sessions文件夾有什
 - 08-05織夢dedecms什么時候用欄目交叉功能?
 - 01-10C#中split用法實例總結(jié)
 - 01-10使用C語言求解撲克牌的順子及n個骰子
 - 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
 - 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
 - 01-11ajax實現(xiàn)頁面的局部加載
 - 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
 


