【编译原理】算符优先算法

1.项目要求

实现算符优先分析算法。

完成以下描述算术表达式的算符优先文法的算符优先分析过程。

G[E]:

E→E+T∣T  

T→T*F∣F

F→(E)∣i

构造该算符优先文法的优先关系矩阵或优先函数;

输入串应是词法分析的输出二元式序列,即某算术表达式“实验项目一”的输出结果。输出为输入串是否为该文法定义的算术表达式的判断结果。

算符优先分析过程应能发现输入串出错。

设计测试用例,并给出测试结果。

2.实验思路:

算符优先分析法是一种自底向上分析方法,也称移进-归约分析法,它的实现思想是对输入符号串自左向右进行扫描,并将输入符逐个移入一个后进先出栈中,边移入边分析,一旦栈顶符号串形成某个句型的句柄时,该句柄对应某产生式的右部,就用该产生式的左部非终结符代替相应右部的文法符号串,这称为一步归约。重复这一过程直到归约到栈中只剩文法的开始符号时则为分析成功,也就确认输入串是文法的句子。

算符优先分析的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系,不考虑非终结符之间的优先关系。在归约过程中只要找到可归约串就归约,并不考虑归约到那个非终结符名,算符优先分析的可归约串不一定是规范句型的句柄,所以算符优先归约不是规范归约。算符优先分析的可归约串是当前符号栈中的符号和剩余的输入符号构成句型的最左素短语。 

3.实验原理

本次实验给定了算术表达式,根据算术表达式给出优先关系表,因此主要实现的只是算符优先分析算法,firstvt和lastvt均没有进行构造。优先关系表如图

            

    +      

    *      

    i       

    (       

    )      

     #      

   +

    >

    <

    <

    <

   >

    >

   *

    >

    >

    <

    <

   > 

    >

   i  

    >

    >

 

 

   >

    > 

   (

    <

    <

    <

    <

   =

  

   )

    >

    >

 

 

   >

    >

   #

    <

    <

    <

    <

  

    =

 

4. 实验代码

#include<stdio.h>
int find(int a,int b)   //构造优先关系表
{
    int table[6][6] = {//数字1代表  > 数字-1代表  <  数字2代表空
                       1, -1, -1, -1, 1, 1,
                       1,  1, -1, -1, 1, 1,
                       1,  1,  2,  2, 1, 1,
                      -1,- 1, -1, -1, 0, 2,
                       1,  1,  2,  2, 1, 1,
                      -1, -1,- 1, -1, 2, 0
                      };
  return table[a-1][b-1];
}
int in_vt(char c)    //根据返回值到优先关系表里面查找优先关系
{
    int n;
   switch(c)//判断是否是非终结符,不是非终结符返回0
   {
       case '+': n = 1; break;  case '*': n = 2; break;
       case 'i': n = 3; break;  case '(': n = 4; break;
       case ')': n = 5; break;  case '#': n = 6; break;
       default : n = 0;
   }
   return n;
}
int judge(char *p,int k,char *psc)
{
        if(k == 1 && p[k] == '#' && (*psc == '+' || *psc == '*'))
        {
            printf("\n运算符前无操作数\n");
            return 0;
        }
        if((*psc == '+' || *psc == '*') && (*(psc + 1) == '+' || *(psc + 1) == '*'))
        {
            printf("\n运算符号不能相邻\n");
            return 0;
        }
        if(*psc == '#' && (*(psc - 1) == '+' || *(psc - 1) == '*'))
        {
            printf("\n运算符后无操作数\n");
            return 0;
        }
        return 1;
}
int main()
{
   int  k;                   //栈顶指针
   char s[30] = {'\0'};      //分析栈
   char *ss;
   char in_c[50] = {'\0'};   //输入串
   char *psc;                //指向当前输入符号
   int  j;
   char q;
   int  flag;
   int  n;
while(1)
{
   printf("请输入要归约的字符串(以‘#’结束)\n");
   printf("例如:(i+i)*i\n");
   scanf("%s",in_c);
   n = 1;          //记录步骤
   k = 1;
   s[k] = '#';
   s[k+1] = '\0';    //初始化
   ss = s + 1;       //指向栈底
   psc = in_c;
   printf("\n步骤\t符号栈S\t\t优先关系\t当前符号\t输入串Str\t\n");
   while(1)
   {
          if(judge(s,k,psc) == 0)
          {
                  printf("\n出错!\n");
                  break;
          }

          if(in_vt(s[k]))
              j = k;
          else
              j = k - 1;
          flag = find(in_vt(s[j]),in_vt(*psc));
          if(flag == 1)  //s[j] > 当前输入字符
          {
               do
               {
                   q = s[j];
                   if(in_vt(s[j-1]))
                        j--;
                   else
                        j = j - 2;
               }while(find(in_vt(s[j]),in_vt(q)) != -1);
               printf("(%d)\t%-24s>\t\t%c\t\t%-32s\n",n++,ss,*psc,psc+1);
               k = j + 1;
               s[k] = 'N';
               s[k+1] = '\0';
               continue;
          }
          else if(flag == -1)//s[j]<当前输入字符
               {
                   printf("(%d)\t%-24s<\t\t%c\t\t",n++,ss,*psc);
                   k++;
                   s[k] = *psc;
                   s[k+1] = '\0';
                   psc++;
                   printf("%-32s\n",psc);
                   continue;
               }
               else if(flag == 0)//s[j]=当前输入字符
                    {
                          if(s[j] == '#')
                          {
                               printf("(%d)\t%-24s=\t\t#\t\n",n,ss);
                               printf("\n归约成功!\n");
                               break;
                          }
                          else
                          {
                               printf("(%d)\t%-24s=\t\t%c\t\t",n++,ss,*psc);
                               k++;
                               s[k] = *psc;
                               s[k+1] = '\0';
                               psc++;
                               printf("%-32s\n",psc);
                               continue;
                          }
                     }
                     else
                     {
                          printf("(%d)\t%-24s无\t\t%c\t\t%-32s\\\n",n++,ss,*psc,psc+1);
                          printf("\n错误!\n");
                          break;
                     }
   }
}
 return 0;
}

实验输入及程序运行输出结果:


  • 16
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
算符优先分析算法是一种自底向上的语法分析算法,用于判断输入源程序是否符合语法规则。该算法的主要思想是利用算符优先关系来进行语法分析。 下面是算符优先分析算法的实验步骤: 1. 定义文法:首先需要定义待分析的文法,可以使用巴科斯范式(BNF)或扩展巴科斯范式(EBNF)来表示文法。 2. 构造算符优先关系表:根据文法中的终结符和运算符,构造算符优先关系表。其中,算符优先关系表是一个二维矩阵,行和列分别代表两个运算符,表中的值表示它们之间的优先关系。 3. 读入待分析的源程序:从文件中读入待分析的源程序,可以使用词法分析器将源程序转换成一个个单词。 4. 进行算符优先分析:根据算符优先关系表和输入的单词序列,利用栈来进行算符优先分析。具体过程如下: - 初始化栈,将结束符号 $ 和文法的开始符号压入栈中。 - 从输入的单词序列中读入一个单词。 - 判断栈顶符号和当前读入的单词之间的优先关系,如果栈顶符号的优先级高于当前单词,则进行规约操作,即将栈顶符号和它的子树弹出,然后根据规约产生式将它们替换成非终结符号。 - 如果栈顶符号和当前单词之间的优先级低于或等于当前单词,则进行移进操作,即将当前单词压入栈中。 - 重复上述步骤,直到栈中只剩下结束符号 $,并且输入的单词序列已经分析完毕。 5. 输出分析结果:如果分析成功,则输出“分析成功”;否则,输出“分析失败”。 以上就是算符优先分析算法的实验步骤,希望对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老北京的热干面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值