Chomsky文法類型判斷(Recognizing the type of the Chomsky grammar)


1.試驗目的

輸入:一組任意的規則。

輸出:相應的Chomsky 文法的類型。

 

2.實驗原理

1).0型文法(短語文法)

如果對於某文法G,P中的每個規則具有下列形式:

   u:: = v

其中u∈V,v∈V*,則稱該文法G為0型文法或短語文法,簡寫為PSG。

0型文法或短語結構文法的相應語言稱為0型語言或短語結構語言L0。這種文法由於沒有其他任何限制,因此0型文法也稱為無限制文法,其相應的語言稱為無限制性語言。任何0型語言都是遞歸可枚舉的,故0型語言又稱遞歸可枚舉集。這種語言可由圖靈機(Turning)來識別。

2).1型文法(上下文有關文法)

如果對於某文法G,P中的每個規則具有下列形式:

   xUy:: = xuy

其中U∈VN;u∈V;x,y∈V*,則稱該文法G為1型文法或上下文有關文法,也稱上下文敏感文法,簡寫為CSG。

1型文法的規則左部的U和右部的u具有相同的上文x和下文y,利用該規則進行推導時,要用u替換U,必須在前面有x和后面有y的情況下才能進行,顯示了上下文有關的特性。

1型文法所確定的語言為1型語言L1,1型語言可由線性有界自動機來識別。

  

3).2型文法(上下文無關文法)

如果對於某文法G,P中的每個規則具有下列形式:

   U :: = u

其中U∈VN;u∈V,則稱該文法G為2型文法或上下文無關文法,簡寫為CFG。

按照這條規則,對於上下文無關文法,利用該規則進行推導時,無需考慮非終結符U所在的上下文,總能用u替換U,或者將u歸約為U,顯示了上下文無關的特點。

2型文法所確定的語言為2型語言L2,2型語言可由非確定的下推自動機來識別。

一般定義程序設計語言的文法是上下文無關的。如C語言便是如此。因此,上下文無關文法及相應語言引起了人們較大的興趣與重視。

4).3型文法(正則文法,線性文法)

如果對於某文法G,P中的每個規則具有下列形式:

   U :: = T  或  U :: = WT

其中T∈VT;U,W∈VN,則稱該文法G為左線性文法。

如果對於某文法G,P中的每個規則具有下列形式:

   U :: = T  或  U :: = TW

其中T∈VT;U, W∈VN,則稱該文法G為右線性文法。

左線性文法和右線性文法通稱為3型文法或正則文法,有時又稱為有窮狀態文法,簡寫為RG。

按照定義,對於正則文法應用規則時,單個非終結符號只能被替換為單個終結符號,或被替換為單個非終結符號加上單個終結符號,或者被替換為單個終結符號加上單個非終結符號。

3型文法所確定的語言為3型語言L3,3型語言可由確定的有限狀態自動機來識別。

在常見的程序設計語言中,多數與詞法有關的文法屬於3型文法。

可以看出,上述4類文法,從0型到3型,產生式限制越來越強,其后一類都是前一類的子集,而描述語言的功能越來越弱,四類文法及其表示的語言之間的關系可表示為:

0型1型2型3型;即L0 L1 L2 L3

 

3..實驗內容

1)輸入一組文法規則,以S為開始符,大寫字母為非終結符,非大寫字母為終結符。

2)判斷文法類型並生成文法的四元組形式。

3)輸出文法類型及文法。

4.實驗心得

這次實驗讓我體會到了判別文法的復雜性,我的算法是先默認是正則文法,再依次判斷,而許多同學是每次對一條規則進行相同的判斷,我認為這是可以改進的,例如若發現上一條規則是符合1型文法,則當前的規則就只需從1型文法開始判斷,詳見源代碼。

5.實驗代碼與結果

1)源代碼

  1 /********************************************************************
  2 created:    2013/05/28
  3 created:    28:5:2013   20:15
  4 file base:  main
  5 file ext:   cpp
  6 author:     Justme0 (http://blog.csdn.net/Justme0)
  7 
  8 purpose:
  9 判斷文法類型。
 10 輸入約定以S為開始符,大寫字母為非終結符,非大寫字母為終結符。
 11 
 12 *********************************************************************/
 13 
 14 #define _CRT_SECURE_NO_WARNINGS
 15 #include <iostream>
 16 #include <string>
 17 #include <vector>
 18 #include <set>
 19 #include <algorithm>
 20 #include <cassert>
 21 using namespace std;
 22 
 23 const int STRING_MAX_LENGTH = 10;
 24 
 25 /*
 26 ** 一條規則
 27 */
 28 struct Principle {
 29     string left;
 30     string right;
 31 
 32     Principle(const char *l, const char *r) : left(l), right(r) {}
 33 };
 34 
 35 /*
 36 ** 文法的四元組形式,同時將該文法類型也作為其屬性
 37 */
 38 struct Grammer {
 39     set<char> Vn;
 40     set<char> Vt;
 41     vector<Principle> P;
 42     char S;
 43 
 44     int flag;    // 文法類型
 45 
 46     Grammer(void) : flag(-1) {}
 47 };
 48 
 49 
 50 /*
 51 ** 輸入規則
 52 */
 53 void input(vector<Principle> &principleSet) {
 54     char left[STRING_MAX_LENGTH];
 55     char right[STRING_MAX_LENGTH];
 56     while (EOF != scanf("%[^-]->%s", left, right)) {
 57         getchar();
 58         principleSet.push_back(Principle(left, right));
 59     }
 60 }
 61 
 62 /*
 63 ** 得到S, Vn, Vt
 64 */
 65 void getGrammer(Grammer &G) {
 66     G.S = G.P.front().left.front();
 67     G.Vn.clear();
 68     G.Vt.clear();
 69 
 70     for (unsigned i = 0; i < G.P.size(); ++i) {
 71         const Principle &prcp = G.P[i];
 72 
 73         for (unsigned j = 0; j < prcp.left.size(); ++j) {
 74             char v = prcp.left[j];
 75             !isupper(v) ? G.Vt.insert(v) : G.Vn.insert(v);
 76         }
 77         for (unsigned j = 0; j < prcp.right.size(); ++j) {
 78             char v = prcp.right[j];
 79             !isupper(v) ? G.Vt.insert(v) : G.Vn.insert(v);
 80         }
 81     }
 82 }
 83 
 84 /*
 85 ** 判斷字符串(文法的左部)中是否存在一個非終結符。
 86 */
 87 bool hasUpper(string s) {
 88     return s.end() != find_if(s.begin(), s.end(), isupper);
 89 }
 90 
 91 /*
 92 ** 判斷文法類型。
 93 */
 94 void check(int &flag, const Principle &prcp) 
 95 {
 96     switch (flag) {
 97     case 3:
 98         if (
 99             1 == prcp.left.size() && isupper(prcp.left.front()) &&
100             (1 == prcp.right.size() && !isupper(prcp.right.front()) ||
101             2 == prcp.right.size() && !isupper(prcp.right.front()) && isupper(prcp.right.back()))
102             ) {
103                 break;
104         }
105 
106     case 2:
107         if (1 == prcp.left.size() && isupper(prcp.left.front())) {
108             flag = 2;
109             break;
110         }
111 
112     case 1:
113         if (hasUpper(prcp.left) && prcp.left.size() <= prcp.right.size()) {
114             flag = 1;
115             break;
116         }
117 
118     default :
119         // 所有的文法規則左部都必須至少含有一個非終結符,是否應放到最前面判斷?
120         // 用異常機制exit是否合適?
121         try {
122             if (!hasUpper(prcp.left)) {
123                 throw exception("輸入的文法錯誤!");
124             }
125         } catch (exception e) {
126             cout << e.what() << endl;
127             exit(-1);
128         }
129 
130         flag = 0;
131         break;
132     }
133 }
134 
135 
136 /*
137 ** 判別文法並生成四元組形式。
138 */
139 void solve(Grammer &G) {
140     G.flag = 3;    // 從正則文法開始判斷
141     for (unsigned i = 0; i < G.P.size(); ++i) {
142         check(G.flag, G.P[i]);
143     }
144     getGrammer(G);
145 }
146 
147 /*
148 ** 輸出文法
149 */
150 void output(const Grammer &G) {
151     cout << "G = (Vn, Vt, P, S)是" << G.flag << "型文法\n" << endl;
152 
153     cout << "Vn:" << endl;
154     for (auto ite = G.Vn.begin(); ite != G.Vn.end(); ++ite) {
155         cout << *ite << endl;
156     }
157     cout << endl;
158 
159     cout << "Vt:" << endl;
160     for (auto ite = G.Vt.begin(); ite != G.Vt.end(); ++ite) {
161         cout << *ite << endl;
162     }
163     cout << endl;
164 
165     cout << "P:" << endl;
166     for (auto ite = G.P.begin(); ite != G.P.end(); ++ite) {
167         cout << (*ite).left << "->" << (*ite).right << endl;
168     }
169     cout << endl;
170 
171     cout << "S:\n" << G.S << endl;
172 };
173 
174 int main(int argc, char **argv) {
175     freopen("cin.txt", "r", stdin);
176 
177     Grammer G;
178     input(G.P);
179     solve(G);
180     output(G);
181 
182     return 0;
183 }

 

 

2)實驗結果

(1)

輸入:

S->aSBE

S->aBE

EB->BE

aB->ab

bB->bb

bE->be

eE->ee

 

輸出:

 

(2)

輸入:

S->aB

S->bA

A->a

A->aS

A->bAA

B->b

B->bS

B->aBB

 

輸出:

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM