(编译原理)简单优先分析方法

#include<stdio.h>
 
int find(int a,int b)   //优先关系表
{
    int table[6][6] = {
                       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)    //可以根据返回的数值去优先关系表里面查找优先关系
{                    //还可以判断是否是非终结符,不是非终结符返回0
   int n;
 
   switch(c)
   {
       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************************************\n");
   printf("请输入要归约的字符串(以‘#’结束):");
   scanf("%s",in_c);
 
   n = 1;          //记录步骤
   k = 1;
   s[k] = '#';
   s[k+1] = '\0';    //初始化
   ss = s + 1;       //指向栈底
   psc = in_c;
 
 
   printf("\n步骤\t栈内字符\t\t优先关系\t当前符号\t剩余输入串\t\t\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)
               {
                   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)
                    {
                          if(s[j] == '#')
                          {
                               printf("(%d)\t%-24s=\t\t#\t\t\t\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;
}

在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算符优先分析文法是一种工具,在编译的过程中,隶属于语法分析环节,却又与中间代码的生成息息相关,编译可以分为五个阶段:词法分析、语法分析、语义分析(中间代码的生成)、代码优化、目标代码生成。语法分析是指:在词法分析基础上,将单词符号串转化为语法单位(语法范畴)(短语、子句、句子、程序段、程序),并确定整个输入串是否构成语法上正确的程序。也就是说语法分析是检验输入串的语法是否正确,注意这里的语法正确,只是简单地符合自己定义的规范,而不能检测出运行时错误,比如"X/0",空指针错误,对象未初始化等错误。在这一个实验中,我将通过算符优先分析文法这一个工具,在语法分析的时候,顺便进行语义分析,也就是识别出语法单位,同时简要的将识别出的中间代码进行计算(目标代码的生成+运行),得到相应的结果,来检验自己设计的正确性。可以说题目虽然叫做算符优先分析文法,其实却是一个贯穿了“词法分析+语法分析+语义分析+中间代码优化+目标代码生成+运行”全过程的一个极具概括性的程序。如果能将这个程序得心应手的完成出来,我相信诸位对编译原理的掌握也算是炉火纯青了。时隔将近两年再来整理自己以前写过的实验报告,还是挺有感慨的,对一件东西感兴趣,原来影响还会如此深远,还记得自己当时连续六个小时全神贯注写出的实验报告,现在看看竟然写了五六十页,核心内容也有三四十页,不觉的感慨当年充满热情的时代慢慢的竟走出许久
摘 要 编译程序的工作过程通常是词法分析、语法分析、语义分析、代码生成、代码优化。编译程序的这些过程的执行先后就构成了编译程序的逻辑结构,但是这些逻辑结构不一定是按照某一个固定顺序的,也有可能是按照平行或者互锁的方式执行的。 本次课程设计是就简单优先文法原理来做一个简单优先分析器。简单优先分析文法的基本思想是对一个文法按一定的原则求出该文法所有符号包括终结符和非终结符之间的优先关系,按照这种关系确定规约过程中的句柄,它的规约过程实际上是规范规约。在算法实现过程中,主要使用visual C++进行编程。 关键字 简单优先关系 大于关系 小于关系 等于关系 Abstract Compiler of the process is usually lexical analysis, grammar analysis, semantic analysis, code generation, code optimization. Compiler of the implementation of these processes have posed a compiler on the logical structure, but these may not necessarily be in accordance with the logical structure of a fixed order, may also be in accordance with the parallel or interlocking approach to the implementation of the. This course is designed on the simple principle of priority to do a simpegrammar priority Analyzer。Simple grammar priority of the basic idea of a grammar obtained by certain principles of the grammar, including all the symbos at the end and at the end of the non-priority, according to this relationship in the process of determining the statute handler, it is actually the process of regulating the Statute of the Statute. In the algorithm process, the main use of visual C programming. Key Words Simple priority relations Over relations Less than relations Equal relations 目 录 摘要…………………………………………………………………………………………2 一、概述……………………………………………………………………………………4 (一)实验环境与开发工具 ………………………………………………………‥4 (二)简单优先文法简介 ……………………………………………………………4 (三)基本概念 ………………………………………………………………………4 (四)优先关系 ………………………………………………………………………4 二、需求分析 ……………………………………………………………………………5 (一)总体功能需求 …………………………………………………………………5 (二)系统的主要功能函数 …………………………………………………………5 (三)系统的设计思想 ………………………………………………………………6 三、详细设计 ……………………………………………………………………………7 (一)等于关系模块 …………………………………………………………………7 (二)小于关系模块 …………………………………………………………………8 (三)大于关系模块 …………………………………………………………………10 (四)句子识别模块 …………………………………………………………………12 四、测试结果………………………………………………………………………………16 五、小结……………………………………………………………………………………19 六、参考文献 ……………………………………………………………………………20 附录 源程序 ………………
算符优先分析法是一种自下而上的语法分析方法,它可以用于分析和处理算术表达式、布尔表达式等。下面是算符优先分析法的实现步骤: 1. 定义终结符和非终结符:终结符是指不能再分解的基本符号,如数字、运算符等;非终结符是指可以分解成其他符号的符号,如表达式、语句等。 2. 定义运算符之间的优先关系和结合性质:将运算符按照优先级从高到低排列,相同优先级的运算符再按照结合性质(左结合或右结合)进行排列。 3. 构造算符优先关系表:根据定义的运算符优先关系和结合性质,构造算符优先关系表。表中的行和列分别表示两个相邻的运算符,表中的元素表示它们之间的优先关系(“<”表示优先级低,“>”表示优先级高,“=”表示优先级相等)。 4. 进行语法分析:将输入的表达式转换成一个个终结符和非终结符的序列,然后根据算符优先关系表进行分析。具体地,从左到右扫描输入序列,将扫描到的符号压入栈中,同时比较栈顶符号和下一个输入符号之间的优先关系,如果栈顶符号的优先级低于或等于下一个输入符号的优先级,则将下一个输入符号压入栈中;否则,从栈中弹出一个或多个符号进行归约,直到栈顶符号的优先级低于或等于下一个输入符号的优先级。 5. 进行表达式求值:在进行归约时,如果遇到两个相邻的终结符之间有一个运算符,则可以对它们进行求值,并将结果压入栈中。最终,栈中只剩下一个值,即为表达式的值。 下面是一个简单的算符优先分析法的实现例子,用于分析和处理四则运算表达式: ```python # 定义终结符和非终结符 terminals = ['+', '-', '*', '/', '(', ')', 'num'] non_terminals = ['E', 'T', 'F'] # 定义运算符之间的优先关系和结合性质 precedence = { '+': {'+': '>', '-': '>', '*': '<', '/': '<', '(': '<', ')': '>', 'num': '<'}, '-': {'+': '>', '-': '>', '*': '<', '/': '<', '(': '<', ')': '>', 'num': '<'}, '*': {'+': '>', '-': '>', '*': '>', '/': '>', '(': '<', ')': '>', 'num': '<'}, '/': {'+': '>', '-': '>', '*': '>', '/': '>', '(': '<', ')': '>', 'num': '<'}, '(': {'+': '<', '-': '<', '*': '<', '/': '<', '(': '<', ')': '=', 'num': '<'}, ')': {'+': '>', '-': '>', '*': '>', '/': '>', '(': ' ', ')': '>', 'num': ' '}, 'num': {'+': '>', '-': '>', '*': '>', '/': '>', '(': ' ', ')': '>', 'num': ' '} } # 构造算符优先关系表 table = {} for i in range(len(terminals)): table[terminals[i]] = {} for j in range(len(terminals)): table[terminals[i]][terminals[j]] = precedence[terminals[i]][terminals[j]] # 进行语法分析 def parse(expr): stack = ['#'] tokens = expr.split() for token in tokens: while table[stack[-1]][token] == '>': op = stack.pop() if op in ['+', '-', '*', '/']: b = stack.pop() a = stack.pop() stack.append(str(eval(a + op + b))) else: stack.pop() if table[stack[-1]][token] == '<' or table[stack[-1]][token] == '=': stack.append(token) else: raise ValueError('Invalid expression') while stack[-1] != '#': op = stack.pop() if op in ['+', '-', '*', '/']: b = stack.pop() a = stack.pop() stack.append(str(eval(a + op + b))) else: raise ValueError('Invalid expression') return stack[0] # 进行表达式求值 expr = '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3' result = parse(expr) print(result) # 输出:3.0001220703125 ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值