• 编译原理第五单元习题


    获得更多资料欢迎进入我的网站或者 csdn或者博客园

    (10分)
    在这个题目中,你将实现一个简单的台式计算器。这个台式计算器的功能像在最后一个讲义中演示的例子一样:即用户可以在控制台上交互输入算术表达式,你的程序判断该表达式是否合法,不合法的话报错并退出运行。
    你的程序涉及表达式的部分要支持如下的表达式:
    E -> n
    | E + E
    | E - E
    | E * E
    | E / E
    | (E)
    其中n是任意的非负整数

    bison工具介绍:

    Bison 工具将把 Bison 语法文件作为输入。语法文件的扩展名为.y。Bison 语法文件内容的分布如下(四个部分):

    %{

    序言

    序言部分可定义 actions 中的C代码要用到的类型和变量,定义宏,用 #include 包含头文件等等
    要在此处声明词法分析器 yylex 和错误输出器 yyerror 。还在此处定义其他 actions 中使用到的全局标识符。

    %}

    Bison 声明

    Bison声明部分可以声明终结符和非终结符的名字,也可以描述操作符的优先级,以及各种符号的值语义的数据类型。各种非单个字符的记号(节点)都必须在此声明。

    %%

    语法规则

    语法规则部分描述了如何用组件构造出一个非终结符。

    %%
    结尾

    结尾部分可以包含你希望使用的任何的代码。通常在序言部分声明的函数就在此处定义。在简单程序中所有其余部分都可以在此处定义。

    语法规则简介:

     可替换规则之间用竖线“|”连接,读作“或”。在花括号内部的是用于已经识别出来的非终结符的动作(action),用C代码写成。
    比如如下的简单计算器用bison写
    简答的例子:

    //空串用在冒号与第一个竖线之间没有任何字符
    
    input: /* empty */
    
    | input line
    
    ;
    
    //第二个选择的含义是在读入了任意数量的行以后,可能的情况下再读入一行。左边的递归使本规则进入到一个循环,由于第一个选择是空,所以循环可以被执行0次或多次。
    
    line: ’
    ’
    
    | exp ’
    ’ { printf ("	%.10g
    ", $1); }
    
    ;
    
    exp: NUM
       | exp'+'exp
       | exp'-'exp
       | exp'*'exp
       | exp'/'exp
       |'('exp')'
    ;
    

    简单计算器用bison实现 .test.y

    //序言部分
    %{
      #include<stdio.h>
      #include<stdlib.h>
      int yylex();
      void yyerror(char *s);
     %}
    //bison声明
    %left '-' '+'
    %left '*' '/'
    %token NUM
    //语法规则
    %%
    /*swith line*/
    lines:line
         |line lines
    ;
    line:exp '
    ';
    /*exp */
    exp: NUM
       | exp'+'exp
       | exp'-'exp
       | exp'*'exp
       | exp'/'exp
       |'('exp')'
    ;
    
    %%
    //结尾
    int yylex()
    {
     int c;
    //跳过空格和制表符
     /*skip white space */
     while((c=getchar())==' '||c=='	');
    /*is digit*/
    //将数字转换为非负整数
    if(c>'0'&&c<'9')
    {
    /*rewrite c*/
    ungetc(c,stdin);
    /*yylval give exp*/
    scanf("%d",&yylval);
    return NUM;
    }
    if(c==EOF)
       return 0;
    
     return c;
    }
    void yyerror(char *s)
    {
     fprintf(stderr,"%s
    ",s);
    return;
    }
    int main(int argc,char**argv)
    {
      yyparse();
    return 0;
    }
    

    解析与编译

    peace@peace:~/workspace/compiler/编译器题目/005$ ls
    test.y
    //解析通过 bison test.y  产生test.tab.c
    peace@peace:~/workspace/compiler/编译器题目/005$ bison test.y 
    peace@peace:~/workspace/compiler/编译器题目/005$ ls
    test.tab.c  test.y
    //编译通过gcc 产生a.out
    peace@peace:~/workspace/compiler/编译器题目/005$ gcc test.tab.c 
    test.y:45:6: warning: conflicting types for ‘yyerror’
     void yyerror(char *s)
          ^
    test.tab.c:1248:7: note: previous implicit declaration of ‘yyerror’ was here
           yyerror (YY_("syntax error"));
           ^
    //运行./a.out
    peace@peace:~/workspace/compiler/编译器题目/005$ ./a.out 
    syntax error
    peace@peace:~/workspace/compiler/编译器题目/005$ ls
    a.out  test.tab.c  test.y
    //此去实现的只是简单的计算器,并没有实现结果;
    peace@peace:~/workspace/compiler/编译器题目/005$ ./a.out 
    1+2
    1+2*3/4
    1++
    syntax error
    
  • 相关阅读:
    Python-函数
    Python-运数符
    Python-条件判断
    Python-变量
    移动端页面布局的那些事儿
    关于ie7下display:inline-block;不支持的解决方案
    SuperSlidev2.1 轮播图片和无缝滚动
    解决xmapp中Apache端口号占用问题
    npm 常用命令详解
    python函数总结
  • 原文地址:https://www.cnblogs.com/onepeace/p/4649425.html
Copyright © 2020-2023  润新知