编译原理第五单元习题

获得更多资料欢迎进入我的网站或者 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
原文地址:https://www.cnblogs.com/onepeace/p/4649425.html