内容目录
编译原理lab8
1. 有如下的bison描述文件:
%{
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#define YYSTYPE double
void yyerror(char *s);
int yylex(void);
%}
%token DIGIT
%left '+'
%left '*'
%%
line: line expr '\n' {printf("%lf\n",$2);}
|
;
expr: expr '+' expr {$$=$1+$3;}
|expr '*' expr {$$=$1*$3;}
| '(' expr ')' {$$=$2;}
|DIGIT {$$=$1;}
;
%%
int main()
{
yyparse();
return 0;
}
int yylex(void){
int c = 0;
while ((c=getchar())==' ');
if (isdigit(c)){
ungetc(c,stdin);
scanf("%lf",&yylval);
return(DIGIT);
}
return c;
}
void yyerror(char *s)
{
fprintf(stderr,"%s\n",s);
}
(1)当输入(5+4+2)*5和8-4+2时,对应的输出是什么?请附上执行输出截图。
当输入(5+4+2)*5,输出是:55.000000
输出截图如下:

当输入为8-4+2,输出是:syntax error
输出截图如下:

(2)改进这个描述文件,使之可以接收和处理减法、除法(如果除数为0则报语法错)和幂(power,使用的符号可以自行定义)。请给出改进后的.y文件内容,并附上执行输出截图。
规定幂的符号为"^",
则改进后.y文件内容如下:
%{
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#define YYSTYPE double
void yyerror(char *s);
int yylex(void);
%}
%token DIGIT
%left '+'
%left '-'
%left '*'
%left '/'
%left '^'
%%
line: line expr '\n' {printf("%lf\n",$2);}
|
;
expr: expr '+' expr {$$=$1+$3;}
|expr '-' expr {$$=$1-$3;}
|expr '*' expr {$$=$1*$3;}
|expr '/' expr {if ($3==0) yyerror("error,divisor can not be 0!\n"); else $$=$1/$3;}
|expr '^' expr {$$=pow($1,$3);}
| '(' expr ')' {$$=$2;}
|DIGIT {$$=$1;}
;
%%
int main()
{
yyparse();
return 0;
}
int yylex(void){
int c = 0;
while ((c=getchar())==' ');
if (isdigit(c)){
ungetc(c,stdin);
scanf("%lf",&yylval);
return(DIGIT);
}
return c;
}
void yyerror(char *s)
{
fprintf(stderr,"%s\n",s);
}
输出截图如下:

2. 下面的FLEX描述文件binaToDeci.l和BISON描述文件binaToDeci.y实现了无符号二进制整数到十进制整数的转换,执行效果如附图。请改进.l和.y文件,使之实现无符号定点二进制数到十进制小数的转换,请给出改进后的.l和.y文件内容,并附上执行输出截图。

binaToDeci.l:
%{
#include "stdio.h"
#include<stdlib.h>
#include "binaToDeci.tab.h"
void yyerror(char *);
int yywrap(void);
%}
%%
0 {yylval=0;return B;}
1 {yylval=1;return B;}
\.|\n {return *yytext;}
. {yyerror("Unknown character!");}
%%
int yywrap(void)
{
return 1;
}
binaToDeci.y:
#include<stdio.h>
#include<stdlib.h>
#include <math.h>
void yyerror(char * );
%}
%token B
%%
N: N S '\n' {printf("%d\n", $2);}
|
;
S: S B {$$=$1*2+$2;}
| B {$$=$1;}
%%
int main()
{
yyparse();
return 0;
}
void yyerror(char* msg ) {
printf("%s\n",msg);
}
改进后.l文件如下:
%{
#include "stdio.h"
#include<stdlib.h>
typedef struct{
double v;
int l;
}vl;
#define YYSTYPE vl
#include "binaToDeci.tab.h"
void yyerror(char *);
int yywrap(void);
%}
%%
0 {yylval.v = 0; return B;}
1 {yylval.v = 1; return B;}
\.|\n {return *yytext;}
. {yyerror("Unknown character!");}
%%
int yywrap(void)
{
return 1;
}
改进后.y文件如下:
%{
#include<stdio.h>
#include<stdlib.h>
#include <math.h>
typedef struct{
double v;
int l;
}vl;
#define YYSTYPE vl
void yyerror(char * );
%}
%token B
%%
input: input newline
|
;
newline: '\n'
| N '\n'
;
N: S '.' S {$3.l = $3.l + 1; printf("%f\n",$1.v + $3.v*pow(2,-$3.l));}
| S {printf("%f\n",$1.v);}
S: S B {$$.v = $1.v*2 + $2.v; $$.l = $1.l + 1;}
| B {$1.l = 1;}
%%
int main()
{
yyparse();
return 0;
}
void yyerror(char* msg ) {
printf("%s\n",msg);
}
输出截图如下:

注:
- 在macos下链接汇编文件时会出现错误,暂未排查出具体原因,但在windows环境下可正常运行
- 对于换行符的不当处理可能导致语法错误或程序提前终止,相关处理参考了https://blog.csdn.net/weixin_43899640/article/details/109355510
代码链接
https://gitee.com/WilliamSamShen/complier-concepts/tree/master/Lab/lab8