语法分析(算符优先文法)

/***************************************
*** 语法分析(算符优先文法)-头文件  *****
*** 输入文法格式-非终结符:其产生式 *****
*** 每个文法子句间用空格分隔       *****
*** 非终结符采用A--Z中字母         *****
*** 例E:E+T|T T:T*F|F F:P-F|P ...  *****
***************************************/
#include<iostream>
#include<string>
#include<vector>
using namespace std;

/
/// 语法分析(算符优先文法)类
class wpanalyse
{
public:
 wpanalyse(string s, string s1);// 构造函数
 ~wpanalyse(){}// 析构函数
 void firstvt(string s);// firstvt函数
 void lastvt(string s);// lastvt函数
 void analyse();// 语法分析函数

private:
 vector<string> vs;// 保存文法
 vector<char> fs[26];// 保存对应firstvt--由于vc6.0中string没有push_back()函数所以采用vector
 vector<char> ls[26];// 保存对应lastvt
 char vt[20];// 终结符集
 string st;// 输入句子
 bool iserror;// 是否出错记录变量
 int nvt;// 优先表大小
};

// 构造函数--实现算符文法判断、记录终结符集和产生式集并调用其他函数
wpanalyse :: wpanalyse(string s, string s1) : nvt(0),iserror(0)// 输入文法和判断是否是算符优先文法
{                                       // 并调用相关处理函数
 int i, j, k;
 bool f, flag, symbol;// 判断标志
 char tmp[20];// 文法中产生式中间变量
 string::iterator h;// 句子的迭代器--用于检测句子中的字符是否均是文法中的终结符
 vector<string>::iterator it;// 产生式集的迭代器

 st = s1;// 记录句子

 for(i=0; s[i]!='/0';)
 {
  j = 0;
  flag = 0;

  while(s[i]!=' '&&s[i]!='/0')// 将文法中产生式分离并保存在vs产生式集中
  {
   f = 0;
   tmp[j] = s[i];

   if(s[i]>='A'&&s[i]<='Z'&&
      s[i+1]>='A'&&s[i+1]<='Z')// 判断是否是算符文法
   {
    flag = 1;
    break;
   }
   
   if(!(tmp[j]>='A'&&tmp[j]<='Z')&&tmp[j]!=':'&&tmp[j]!='|')// 判断是否是终结符
   {
    for(k=0; k<nvt; ++k)// 检索该终结符是否已在终结符集合中
    {
     if(vt[k]==tmp[j])
     {
      f = 1;
     }
    }
   
    if(!f)// 由标志判断是否加入终结符集
    {
     vt[nvt] = tmp[j];
     ++nvt;
    }
   }

   ++i;
   ++j;
  }

  if(flag)
  {
   cout<<"This isn't a operational word!"<<endl;
   break;
  }
  else// 将该产生式存入产生式集
  {
   tmp[j] = '/0';
   vs.push_back(tmp);
  }

  if(s[i]==' ')// 进入下个产生式的首位
  {
   ++i;
  }
 }

 for(h=s1.begin(); h!=s1.end(); ++h)// 检测句子中的字符是否均是文法中的终结符
 {
  symbol = 0;

  for(i=0, j=0; i<nvt; ++i)
  {
   if(*h==vt[i])
   {
    symbol= 1;
   }
  }

  if(!symbol)
  {
   break;
  }
 }

 if(symbol)
 {
  for(it=vs.begin(); it!=vs.end(); ++it)// 分析每个非终结符的firstvt和lastvt
  {
   firstvt(*it);
   lastvt(*it);
  }

  analyse();// 分析句子

  if(iserror)// 根据前面分析函数给出的标志判断句子是否正确
  {
   cout<<"The sentence is wrong!"<<endl;
  }
  else
  {
   cout<<"The sentence is right!"<<endl;
  }
 }
 else
 {
  cout<<"The sentence is wrong!"<<endl;
 }
}

// firstvt函数--分析每个非终结符的firstvt并保存在fs中
void wpanalyse :: firstvt(string s)
{
 int i=2;
 bool flag;// 终结符是否压入fs的标志
 vector<string>::iterator j;// 产生式集的迭代器
 vector<char>::iterator h;// fs集的迭代器
 vector<char>::iterator k;// fs集的迭代器
 string p;

 while(s[i]!='/0')// 判断产生式是否结束
 {
  flag = 0;

  if(!(s[i]>='A'&&s[i]<='Z'))// 产生式右部首位是终结符时
  {
   for(h=fs[s[0]-'A'].begin(); h!=fs[s[0]-'A'].end(); ++h)// 检索终结符是否已经在ls集中
   {
    if(s[i]==*h)
    {
     flag = 1;
    }
   }

   if(!flag)// 终结符不在ls集则加入
   {
    fs[s[0]-'A'].push_back(s[i]);
   }
  }
  else if(s[i]>='A'&&s[i]<='Z'&&s[i]!=s[0])// 产生式右部首位是非终结符时
  {
   for(j=vs.begin(); j!=vs.end(); ++j)
   {
    p = *j;

    if(p[0]==s[i])// 判断产生式的首位(产生式左部)是否是此非终结符
    {
     firstvt(p);// 分析此非终结符的firstvt集

     for(k=fs[s[i]-'A'].begin(); k!=fs[s[i]-'A'].end(); ++k)
     {
      for(h=fs[s[0]-'A'].begin(); h!=fs[s[0]-'A'].end(); ++h)// 检索终结符是否已经在fs集中
      {
       if(*k==*h)
       {
        flag = 1;
       }
      }
      if(!flag)// 终结符不在fs集则加入
      {
       fs[s[0]-'A'].push_back(*k);
      }
     }
    }
   }
  }

  while(s[i]!='|'&&s[i]!='/0')
  {
   ++i;
  }

  if(s[i]=='|')
  {
   ++i;
  }
 }
}

// lastvt函数--分析每个非终结符的lastvt并保存在ls中
void wpanalyse :: lastvt(string s)
{
 int i=2;
 bool flag;// 终结符是否压入ls的标志
 vector<char>::iterator h;// ls集的迭代器
 vector<char>::iterator k;// ls集的迭代器
 vector<string>::iterator j;// 产生式集的迭代器
 string p;// 辅助变量

 while(s[i]!='/0')// 判断产生式是否结束
 {
  flag = 0;

  while(s[i]!='|'&&s[i]!='/0')// 找到产生式末尾
  {
   ++i;
  }

        --i;

  if(!(s[i]>='A'&&s[i]<='Z'))// 最后字符是终结符时
  {
   for(h=ls[s[0]-'A'].begin(); h!=ls[s[0]-'A'].end(); ++h)// 检索终结符是否已经在ls集中
   {
    if(s[i]==*h)
    {
     flag = 1;
    }
   }

   if(!flag)// 终结符不在ls集则加入
   {
    ls[s[0]-'A'].push_back(s[i]);
   }
  }
  else // 找非终结符的lastvt集
  {
   for(j=vs.begin(); j!=vs.end(); ++j)
   {
    p = *j;// 记录产生式

    if(p[0]==s[i])// 判断产生式的首位(产生式左部)是否是此非终结符
    {
     lastvt(p);// 分析此非终结符的lastvt集

     for(k=ls[s[i]-'A'].begin(); k!=ls[s[i]-'A'].end(); ++k)
     {
      for(h=ls[s[0]-'A'].begin(); h!=ls[s[0]-'A'].end(); ++h)// 检索终结符是否已经在ls集中
      {
       if(*k==*h)
       {
        flag = 1;
       }
      }
      if(!flag)// 终结符不在ls集则加入
      {
       ls[s[0]-'A'].push_back(*k);
      }
     }
    }
   }
  }
       
  ++i;

  if(s[i]=='|')
  {
   ++i;
  }
 }

}

// 语法分析函数--构建优先表和分析句子
void wpanalyse :: analyse()
{
 int i, x, y, k, pre;
 char r[20];
 string p;
 vector<char>::iterator z;
 vector<string>::iterator j;
 char **table = new char*[nvt];

 for(i=0; i<nvt; ++i)
 {
  table[i] = new char[nvt];
 }

                  // 构建优先表
 for(j=vs.begin(); j!=vs.end(); ++j)
 {
  p = *j;

  for(i=2; p[i]!='/0'; ++i)
  {
   if(p[i+1]!='/0'&&p[i]!='|'&&p[i+1]!='|'&&
      !(p[i]>='A'&&p[i]<='Z')&&
      !(p[i+1]>='A'&&p[i+1]<='Z'))// 两终结符相邻时
   {
    for(x=0; vt[x]!=p[i]; ++x);// 找到table中的行位置
    for(y=0; vt[y]!=p[i+1]; ++y);// 找到table中的列位置

    if(table[x][y]!='>'&&
       table[x][y]!='<')// table[x][y]原无其他状态时
    {
     table[x][y] = '=';
    }
    else
    {
     iserror = 1;
    }
   }

   if(p[i+2]!='/0'&&p[i]!='|'&&p[i+2]!='|'&&
      !(p[i]>='A'&&p[i]<='Z')&&
      p[i+1]>='A'&&p[i+1]<='Z'&&
      !(p[i+2]>='A'&&p[i+2]<='Z'))// 两终结符间隔一个非终结符时
   {
    for(x=0; vt[x]!=p[i]; ++x);// 找到table中的行位置
    for(y=0; vt[y]!=p[i+2]; ++y);// 找到table中的列位置

    if(table[x][y]!='>'&&
       table[x][y]!='<')// table[x][y]原无其他状态时
    {
     table[x][y] = '=';
    }
    else
    {
     iserror = 1;
    }
   }

   if(!(p[i]>='A'&&p[i]<='Z')&&p[i+1]!='/0'&&
      p[i+1]>='A'&&p[i+1]<='Z')// 终结符和其后非终结符时
   {
    for(x=0; vt[x]!=p[i]; ++x);// 找到行位置

    for(z=fs[p[i+1]-'A'].begin(); z!=fs[p[i+1]-'A'].end(); ++z)
    {
     for(y=0; vt[y]!=*z; ++y);// 找到列位置

     if(table[x][y]!='>'&&
           table[x][y]!='=')// table[x][y]原无其他状态时
     {
      table[x][y] = '<';
     }
     else
     {
      iserror = 1;
     }
    }
   }

   if(p[i]>='A'&&p[i]<='Z'&&p[i+1]!='|'&&p[i+1]!='/0'&&
      !(p[i+1]>='A'&&p[i+1]<='Z'))// 非终结符和其后终结符时
   {
    for(y=0; vt[y]!=p[i+1]; ++y);// 找到列位置

    for(z=fs[p[i]-'A'].begin(); z!=fs[p[i]-'A'].end(); ++z)
    {
     for(x=0; vt[x]!=*z; ++x);// 找到行位置

     if(table[x][y]!='='&&
           table[x][y]!='<')// table[x][y]原无其他状态时
     {
      table[x][y] = '>';
     }
     else
     {
      iserror = 1;
     }
    }
   }
  }
 }
             // 分析句子
 for(x=0; vt[x]!=st[0]; ++x);

 for(i=1; st[i]!='/0'; ++i)// 根据table对句子两两关系判断并记录
 {
  for(y=0; vt[y]!=st[i]; ++y);

  r[i] = table[x][y];

  x = y;
 }

 r[i] = '/0';
 pre = -1;
 i = 0;

 while(r[i]!='/0')
 {
  for(i=1; r[i]!='>'&&r[i]!='/0'; ++i)// 找到最左素短语 // bug:a?dbcde=>S:aAcBe A:Bb|b B:d
  {
   if(r[i]=='<')
   {
    pre = i;
   }

   if(pre==-1&&r[i+1]=='>')
   {
    ++i;
   }
  }

  for(j=vs.begin(); pre!=-1&&j!=vs.end(); ++j)// 检索该最左素短语能否归约--若能则归约否则报错
  {
   k = 2;
   p = *j;
   x = pre;
   
   while(p[k]!='/0')// 判断产生式是否结束
   {
    while(p[k]==st[x]&&p[k]!='/0')// 产生式与最左素短语比较
    {
     ++x;
     ++k;
    }

    if(x==i)// 判断最左素短语是否与某产生式一一对应
    {
     if(r[i]=='/0')
     {
      --x;
     }

     r[x] = '=';// 消除原大于或小于关系-即去除当前最左素短语

     for(y=x+1; r[y]!='/0'&&r[y]!='<'&&r[y]!='>'; ++y);// 检索下一个非'='关系--当关系为'>'时
                                                       // 说明可继续归约不能去除原归约项左边'<'关系
     if(r[y]=='>')// 可进一步归约时-对归约后的st和r进行相应处理
     {
      if(x-pre==1)// 归约项为一位时仅改变一位st
      {
       st[pre] = p[0];
      }
      else// 归约项为多位时归约一位后空余归约位补上后面字符并对r进行相同处理(同步对应)
      {
       st[pre] = p[0];

       for(y=pre+1; st[y]!='/0'; ++y)
       {
        st[y] = st[y+x-pre-1];
        r[y] = r[y+x-pre-1];
       }
      }
     }
     else// 不可进一步归约则去除原归约项左边'<'关系
     {
      r[pre] = '=';
     }

     pre = -1;

     break;
    }
    else
    {
     while(p[k]!='|'&&p[k]!='/0')// 移到下条产生式
     {
      ++k;
     }

     if(p[k]=='|')
     {
      ++k;
     }
    }
   }
  }

  if(pre!=-1)
  {
   iserror = 1;
   break;
  }
 }

 for(i=1; r[i]!='/0'; ++i)// 判断是否全部归约
 {
  if(r[i]=='<'||r[i]=='>')
  {
   iserror = 1;
   break;
  }
 }

 for(i=0; i<nvt; ++i)// 释放申请空间
 {
  delete[] table[i];
 }

 delete[] table;
}

 


#include "prioranalyse_h.h"

int main()
{
 string s, s1;

 cin>>s;
 cin.clear();// 清除缓冲流
 cin.ignore();
 getline(cin, s1);//第三参数默认为'/n'

 //s = "adbcde";
 //s1 = "S:aAcBe A:Bb|b B:d";

    wpanalyse a(s1, s);

 return 0;
}

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
优先文法是一种用于语法分析的方法,其主要思想是根据运优先级和结合性来判断表达式的正确性。在Java编程中,可以通过实现优先文法分析器来实现表达式的语法分析。下面是一个简单的优先文法分析器的设计与实现。 1. 优先文法分析器的设计 优先文法分析器的设计主要包括以下几个方面: - 根据优先级和结合性,定义终结和非终结的关系; - 根据文法规则,设计分析表,并使用分析表对输入的表达式进行分析; - 实现GUI界面,通过文本框和按钮等控件,实现用户输入表达式和分析结果的输出。 2. 优先文法分析器的实现 优先文法分析器的实现主要包括以下几个步骤: - 定义终结和非终结的关系 在优先文法中,将运分为三类:左括号、右括号和运。其中,左括号可以看作是最高优先级的运,右括号可以看作是最低优先级的运,而其他的运根据优先级和结合性确定优先级大小。根据这些规则,可以定义终结和非终结的关系,如下所示: - E → E + T | E - T | T - T → T * F | T / F | F - F → ( E ) | i 其中,E、T、F、+、-、*、/、(、)、i 分别表示非终结和终结。 - 设计分析表 根据优先文法的规则,可以设计分析表。分析表的设计主要包括以下几个步骤: - 构造号表,将终结和非终结按照优先级从高到低排序,并将左括号和右括号放在最高和最低位置; - 定义关系矩阵,将号表中的号两两组合,根据优先文法的规则定义它们之间的关系; - 根据关系矩阵,构造分析表,包括移进表、归约表和出错表。 例如,对于上述优先文法,其分析表如下所示: | | + | - | * | / | ( | ) | i | $ | |----|----|----|----|----|----|----|----|----| | + | > | > | < | < | < | > | < | > | | - | > | > | < | < | < | > | < | > | | * | > | > | > | > | < | > | < | > | | / | > | > | > | > | < | > | < | > | | ( | < | < | < | < | < | = | < | | | ) | > | > | > | > | | > | | > | | i | > | > | > | > | | > | | > | | $ | < | < | < | < | < | | < | = | 其中,>表示移进,<表示归约,并且表格中的空格表示出错。 - 实现GUI界面 在Java编程中,可以使用Swing或JavaFX等GUI库来实现优先文法分析器的GUI界面。具体实现步骤如下: - 使用JFrame类或Stage类创建主窗口; - 使用JPanel类或Group类创建布局,添加文本框、按钮等控件; - 实现按钮的事件处理程序,获取用户输入的表达式,进行语法分析,输出分析结果。 3. 优先文法分析器的注意事项 在实现优先文法分析器时,需要注意以下几个问题: - 优先文法分析器只能处理文法规则的表达式,对于不合法的表达式,需要进行出错处理; - 分析表的构造需要根据具体的文法规则进行设计,构造出来的分析表在处理其他文法规则的表达式时可能会出现错误; - GUI界面的设计需要考虑用户的交互体验,包括布局、控件的大小和位置等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值