编译器实践三 之 针对算术表达式的语法分析器

编译器实践三 之 针对算术表达式的语法分析器

大家好,又见面了,我是全栈君。

该算术表达式的上下文无关文法是:

E -> E + T

   | E – T

   | T

T -> T * F

   | T / F

   | F

F -> num

   | (E)

部分代码来自MOOC

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>

void parse_F();
void parse_T();
void parse_E();
void error (char *want, char got);

int i;
char *str = 0;

void error (char *want, char got)
{
  fprintf (stderr, "Compling this expression:\n%s\n", str);
  int j = i;
  while (j--)
    fprintf (stderr, " ");
  fprintf (stderr, "^\n");
  fprintf (stderr, "Syntax error at position: %d\n"
           "\texpecting: %s\n"
           "\tbut got  : %c\n",
           i, want, got);
  exit (0);
  return;
}

void parse_F()
{
  char c = str[i];
  if (isdigit(c)){
    i++;
    return;
  }
  if (c=='('){
    i++;
    parse_E();
    c = str[i];
    if (c==')'){
      i++;
      return;
    }
    error ("\')\'", c);
    return;
  }
  error ("\'0-9\' or \'(\'", c);
  return;
}


void parse_T()
{
  parse_F();
  char c = str[i];
  while (c=='*' || c =='/'){
    i++;
    parse_F();
    c = str[i];
  }
  return;
}

void parse_E()
{
  parse_T();
  char c = str[i];
  while (c=='+' || c == '-'){
    i++;
    parse_T();
    c = str[i];
  }
  return;
}

void parse (char *e)
{
  str = e;
  i = 0;
  parse_E();
  if (str[i]=='\0')
    return;
  error ("\'+\' or '\\0\'", str[i]);
  return;
}
///////////////////////////////////////////////
// Your job:
// Add some code into the function parse_E() and
// parse_T to parse "-" and "/" correctly.
// When you finish your task, NO error message
// should be generated.
// Enjoy! :-P
int main (char argc, char **argv)
{
  // There are the following rules on an expression:
  //   1. Every expression is represented as a string;
  //   2. integers are non-negative;
  //   3. integers are between 0-9.
  char *e;

  e = "(2)";
  parse(e);

  e = "(3+4*5))";
  parse(e);

  e = "(8-2)*3";
  parse(e);

  e = "(8-2)/3";
  parse(e);
  
  return 0;
}


与君共勉

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116060.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • python 函数嵌套和nonlocal关键字

    python 函数嵌套和nonlocal关键字python函数可以嵌套使用,使用也比较简单,举个栗子:defouter():print("outer")definner():print("inner")inner()outer()##运行结果:outerinnernonlocal关键字:与global关键字有点相似,可以对比着理解。nonlocal关键字只能作用域局…

  • java数组反转,Java数组反转

    java数组反转,Java数组反转本篇文章帮大家学习java数组反转,包含了Java数组反转使用方法、操作技巧、实例演示和注意事项,有一定的学习价值,大家可以用来参考。以下实例中我们使用Collections.reverse(ArrayList)将数组进行反转:importjava.util.ArrayList;importjava.util.Collections;publicclassMain{publicst…

  • windows DLL注入之注册表注入

    windows DLL注入之注册表注入windows下的注入之注册表注入:1.概念介绍:注入与Hook:注入与hook经常被人们混淆,其实注入和hook是两种windows下的编程技术(当然,其他平台也有相关的技术),由于在安全编程中,两项技术经常被同时结合起来使用,所以常常导入混淆。今天我们就谈谈windows下的注入技术。1.1Hook:hook的中文名叫钩子,hook是程序设计中最为灵活多变的技巧之一,hook对指…

  • C++虚析构函数和纯虚析构函数

    C++虚析构函数和纯虚析构函数1、为什么要使用虚析构函数我们知道析构函数是在对象生命周期结束时自动被调用,用来做一些清理工作(如释放句柄,释放堆内存等),防止出现内存泄漏。那怎么还有虚析构函数呢?使用虚析构函数的类一般是要作为基类,被其他类继承。通过把基类的析构函数声明为虚函数,就可以通过父类指针来释放子类对象,从而完成子类的一些清理工作,防止出现内存泄漏。案例1:基类析构函数为非虚函数//test.hclassParent{public:Parent();~Parent

  • 常用的web漏洞扫描工具_十大常用管理工具

    常用的web漏洞扫描工具_十大常用管理工具Webscantool推荐10大Web漏洞扫描程序Nikto这是一个开源的Web服务器扫描程序,它可以对Web服务器的多种项目(包括3500个潜在的危险文件/CGI,以及超过900个服务器版本,还有250多个服务器上的版本特定问题)进行全面的测试。其扫描项目和插件经常更新并且可以自动更新(如果需要的话)。Nikto可以在尽可能短的周期内测试你的Web服务器,这在其日志文件中…

  • C++结构体和类的区别_c++有结构体吗

    C++结构体和类的区别_c++有结构体吗这是对多个博客的总结————————————————————————————区别:1.结构体是一种值类型,而类是引用类型。值类型用于存储数据的值,引用类型用于存储对实际数据的引用。那么结构体就是当成值来使用的,类则通过引用来对实际数据操作。2.结构使用栈存储(Stac…

    2022年10月30日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号