跳至正文

编译原理lab8

内容目录

编译原理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

输出截图如下:

img

当输入为8-4+2,输出是:syntax error

输出截图如下:

img

(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);

}

输出截图如下:

img

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

img

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);
}

输出截图如下:

img

注:

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

代码链接

https://gitee.com/WilliamSamShen/complier-concepts/tree/master/Lab/lab8