• 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

    输出:

  • 相关阅读:
    Java IO包装流如何关闭?
    Validator关于js,jq赋值不触发验证解决办法
    4 统计量&抽样分布
    3 概率的基本概念&离散型随机变量
    2 数据的概括性度量
    1 数据 & 图表
    Python 闭包
    一个自动修正数据时间和补全缺失数据的MapReduce程序
    MapReduce原理
    Hadoop MapReduce常用输入输出格式
  • 原文地址:https://www.cnblogs.com/jjtx/p/3110219.html
Copyright © 2020-2023  润新知