程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 擴充C0文法編譯器開發筆記(一)符號表,c0文法

擴充C0文法編譯器開發筆記(一)符號表,c0文法

編輯:C++入門知識

擴充C0文法編譯器開發筆記(一)符號表,c0文法


零、簡介

  這是一個編譯大作業。

一、擴充C0文法

  文法包括 常量說明和定義、變量說明和定義、無返回值函數定義和調用、有返回值函數定義和調用、條件語句、while循環語句、情況語句、賦值語句、返回語句、讀語句、寫語句,支持加減乘除四則運算、整數比較運算。包含一維數組、不包含實型、不包含for循環語句。程序由main方法進入。具體文法見下:

1 <加法運算符> ::= +|- 2 <乘法運算符> ::= *|/ 3 <關系運算符> ::= <|<=|>|>=|!=|== 4 <字母> ::= _|a|...|z|A|...|Z 5 <數字> ::= 0|<非零數字> 6 <非零數字> ::= 1|...|9 7 <字符> ::= '<加法運算符>'|'<乘法運算符>'|'<字母>'|'<數字>' 8 <字符串> ::= "{十進制編碼為32,33,35-126的ASCII字符}" 9 <程序> ::= [<常量說明>][<變量說明>]{<有返回值函數定義>|<無返回值函數定義>}<主函數> 10 <常量說明> ::= const<常量定義>;{ const<常量定義>;} 11 <常量定義> ::= int<標識符>=<整數>{,<標識符>=<整數>} 12 | char<標識符>=<字符>{,<標識符>=<字符>} 13 <無符號整數> ::= <非零數字>{<數字>} 14 <整數> ::= [+|-]<無符號整數>|0 15 <標識符> ::= <字母>{<字母>|<數字>} 16 <聲明頭部> ::= int<標識符> | char<標識符> 17 <變量說明> ::= <變量定義>;{<變量定義>;} 18 <變量定義> ::= <類型標識符>(<標識符>|<標識符>‘[’<無符號整數>‘]’){,(<標識符>|<標識符>‘[’<無符號整數>‘]’ )} 19 <常量> ::= <整數>| <字符> 20 <類型標識符> ::= int | char 21 <有返回值函數定義> ::= <聲明頭部>‘(’<參數>‘)’ ‘{’<復合語句>‘}’ 22 <無返回值函數定義> ::= void<標識符>‘(’<參數>‘)’‘{’<復合語句>‘}’ 23 <復合語句> ::= [<常量說明>][<變量說明>]<語句列> 24 <參數> ::= <參數表> 25 <參數表> ::= <類型標識符><標識符>{,<類型標識符><標識符>}| <空> 26 <主函數> ::= void main‘(’‘)’ ‘{’<復合語句>‘}’ 27 <表達式> ::= [+|-]<項>{<加法運算符><項>} 28 <項> ::= <因子>{<乘法運算符><因子>} 29 <因子> ::= <標識符>|<標識符>‘[’<表達式>‘]’|<整數>|<字符>|<有返回值函數調用語句>|‘(’<表達式>‘)’ 30 <語句> ::= <條件語句>|<循環語句>| ‘{’<語句列>‘}’|<有返回值函數調用語句>; 31 |<無返回值函數調用語句>;|<賦值語句>;|<讀語句>;|<寫語句>;|<空>; |<情況語句>|<返回語句>; 32 <賦值語句> ::= <標識符>=<表達式>|<標識符>‘[’<表達式>‘]’=<表達式> 33 <條件語句> ::= if ‘(’<條件>‘)’<語句>[else<語句>] 34 <條件> ::= <表達式><關系運算符><表達式>|<表達式> //表達式為0條件為假,否則為真 35 <循環語句> ::= while ‘(’<條件>‘)’<語句> 36 <情況語句> ::= switch ‘(’<表達式>‘)’ ‘{’<情況表> ‘}’ 37 <情況表> ::= <情況子語句>{<情況子語句>} 38 <情況子語句> ::= case<常量>:<語句> 39 <有返回值函數調用語句> ::= <標識符>‘(’<值參數表>‘)’ 40 <無返回值函數調用語句> ::= <標識符>‘(’<值參數表>‘)’ 41 <值參數表> ::= <表達式>{,<表達式>}|<空> 42 <語句列> ::= {<語句>} 43 <讀語句> ::= scanf ‘(’<標識符>{,<標識符>}‘)’ 44 <寫語句> ::= printf ‘(’ <字符串>,<表達式> ‘)’| printf ‘(’<字符串> ‘)’| printf ‘(’<表達式>‘)’ 45 <返回語句> ::= return[‘(’<表達式>‘)’] 46 47 48 附加說明: 49 50 (1)char類型的表達式,用字符的ASCII碼對應的整數參加運算,在寫語句中輸出字符 51 52 (2)標識符不區分大小寫字母 53 54 (3)寫語句中的字符串原樣輸出 55 56 (4)情況語句中,switch後面的表達式和case後面的常量只允許出現int和char類型;每個情況子語句執行完畢後,不繼續執行後面的情況子語句 57 58 (5)數組的下標從0開始 擴充C0文法

 二、符號表(Table)

  符號表是在編譯過程中編譯程序用來記錄源程序中的各種名字(即標識符)的特性信息的表格。符號表的每一個符號表項將填入名字標識符以及與該名字相關聯的信息,這些信息將全面地反映各個符號的屬性及他們在編譯過程中的特征,比如名字的種類(數組、變量、常量等)、類型(整形、字符型等)、值等與該名字的語義有關的其他信息等。

1、符號表結構

  符號表由符號表項(TableItem)構成,每個符號表項結構見下:

1 class Table; 2 class TableItem 3 { 4 public: 5 string name; // 符號表項名,如函數名、變量名等 6 int kind; // 標識符種類,如VAR、CONST、ARRAY、FUNCTION等 7 int type; // 標識符類型,如INT、CHAR等 8 string value; // 值或地址(例如常量的值、變量的地址) 9 int dimension; // 數組的上界、函數的參數個數 10 Table* pChildTable; // 指向由該項引出的子表 11 Table* pParentTable; // 指向該項所在的表 12 13 TableItem(string name, int kind, int type, string value, int dimension, Table* parentTable); 14 ~TableItem(); 15 }; 符號表項結構

2、符號表管理

  符號表由符號表管理類(TableManager)管理,如下:

1 class Table; 2 class TableItem; 3 class TableManager 4 { 5 public: 6 Table* pCurrentTable; // 指向當前符號表 7 Table* pTopTable; // 指向最頂層符號表 8 TableItem* pCurrentItem; // 指向當前符號表項 9 10 TableManager(); 11 virtual ~TableManager(); 12 13 // 檢查當前符號表,是否存在名稱為name的符號表項 14 int checkCurrent(string name, int isCaseSensitive); 15 // 檢查所有的符號表,是否存在名稱為name的符號表項 16 int checkAll(string name, int isCaseSensitive); 17 // 根據名稱name返回對應的符號表項 18 TableItem* find(string name, int isCaseSensitive); 19 // 插入符號表項 20 void insert(string name, int kind, int type, string value, int dimension); 21 // 當前符號表項出棧 22 void pop(); 23 // 將name對應的符號表項壓棧 24 void push(string name); 25 }; 符號表管理類

3、符號表管理算法

(1)壓棧算法:符號表壓棧操作,若當前符號表的最後一項為函數頭部或過程頭部,則為該項建立子符號表,並將當前符號表指針更新為此符號表

1 void TableManager::push(string name) 2 { 3 if(pCurrentTable->itemNumber == 0) 4 { 5 ;// 如果當前沒有符號表項,DONOTHING 6 } 7 // 如果名稱叫name的符號表項有引出的表,則將該表壓入棧頂 8 else if(find(name, 1)->pChildTable != NULL) 9 { 10 pCurrentTable = find(name, 1)->pChildTable; 11 } 12 else 13 { 14 ;//如果該符號表項沒有引出的子表,DONOTHING 15 } 16 } push(string name)

(2)出棧算法:符號表退棧操作,將當前符號表更新為次棧頂符號表

1 void TableManager::pop() 2 { 3 // 如果當前符號表是由某個符號表項引出的,則更新當前符號表為該符號表項所在的符號表 4 if(pCurrentTable->pParentItem != NULL) 5 { 6 pCurrentTable = pCurrentTable->pParentItem->pParentTable; 7 } 8 else 9 { 10 ;// 如果為頂層符號表,DONOTING 11 } 12 } pop()

(3)查詢算法:修改自二分查找(符號表項按其名稱的字母順序,將其索引值存入一個數組,在該數組中二分查找),如果存在該符號表項,則返回索引值,否則返回該符號表項應該插入的位置

1 int Table::find(string name, int left, int right, int isCaseSensitive) 2 { 3 int mid = (left+right)/2; 4 if(left == right) 5 { 6 if(compare(name, itemList[itemIndex[left]]->name, isCaseSensitive) == 0) 7 { 8 itemExist = 1; 9 return left; 10 } 11 else if(compare(name, itemList[itemIndex[left]]->name, isCaseSensitive) == 1) 12 { 13 itemExist = 0; 14 return left+1; 15 } 16 else 17 { 18 itemExist = 0; 19 return left; 20 } 21 } 22 else if(left+1 == right) 23 { 24 if(compare(name, itemList[itemIndex[left]]->name, isCaseSensitive) == 0) 25 { 26 itemExist = 1; 27 return left; 28 } 29 else if(compare(name, itemList[itemIndex[right]]->name, isCaseSensitive) == 0) 30 { 31 itemExist = 1; 32 return right; 33 } 34 else 35 { 36 itemExist = 0; // newItem位置在left和right中間 37 return right; 38 } 39 } 40 else if(compare(name, itemList[itemIndex[mid]]->name, isCaseSensitive) == -1) 41 { 42 return find(name, left, mid, isCaseSensitive); 43 } 44 else if(compare(name, itemList[itemIndex[mid]]->name, isCaseSensitive) == 1) 45 { 46 return find(name, mid, right, isCaseSensitive); 47 } 48 else 49 { 50 itemExist = 1; 51 return mid; 52 } 53 } find(string name, int left, int right, int isCaseSensitive)

(4)插入算法:將新的符號表項插入符號表中,並根據其名稱的字母序建立索引,存入有序數組中,方便二分查找

1 int Table::insert(string name, int kind, int type, string value, int dimension) 2 { 3 newItem = new TableItem(name, kind, type, value, dimension, this); 4 if(itemNumber == 0) 5 { 6 itemIndex[0] = 0; 7 itemList[itemNumber++] = newItem; 8 return 0; 9 } 10 else 11 { 12 if(name < itemList[itemIndex[0]]->name) 13 { 14 for(int i = itemNumber - 1; i >= 0; i--) 15 itemIndex[i+1] = itemIndex[i]; 16 itemIndex[0] = itemNumber; 17 itemList[itemNumber++] = newItem; 18 } 19 else if(name > itemList[itemIndex[itemNumber-1]]->name) 20 { 21 itemIndex[itemNumber] = itemNumber; 22 itemList[itemNumber++] = newItem; 23 } 24 else 25 { 26 int index = find(newItem->name, 0, itemNumber-1, 0); 27 if(itemExist == 1) 28 { 29 //ERROR 30 return -1; 31 } 32 else 33 { 34 for(int i = itemNumber - 1; i >= index; i--) 35 itemIndex[i+1] = itemIndex[i]; 36 itemIndex[index] = itemNumber; 37 itemList[itemNumber++] = newItem; 38 } 39 } 40 return 0; 41 } 42 } insert(string name, int kind, int type, string value, int dimension)

 

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