0

我在使用这个 Bison 程序时遇到了问题。它必须通过将它们乘以 2^n 来接收带有句点“101.101”的 1 和 0 的字符串。例如:

"101.101" = (1*2^2)+(0*2^1)+(1*2^0)+(1*2^-1)+(0*2^-2)+(1*2^-3)=5.625

该点告诉 pow 何时为正或负。我有以下语义动作:

S→ L.R 
 S→ L  
 L → L1 B   
 L → B  
 R → R1 B  
 R → B   
 B→ 0  
 B → 1  
 Sematic Rules  
 L.pos=0;R.pos=-1;S.val=L.val+R.val  
 L.pos=0;S.val=L.val;  
 L1.pos = L.pos + 1; B.pos = L.pos; L.val = L1.val + B.val;  
 B.pos = L.pos; L.val = B.val;  
 R1.pos = R.pos - 1; B.pos = R.pos; L.val = L1.val + B.val;
 B.pos = R.pos; L.val = B.val;  
 B.val=0;  
 B.val = 1*2^B.pos;  

我现在遇到的问题是我不知道为什么 .pos 变量不起作用,它们总是被赋值为 0。我的野牛代码是:

%{
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
void yyerror (char *string);

%}
%union {
    struct named_for_discussion_below {
        int pos;
        int val;
    } pair;
}

%token DOT
%token ZERO
%token ONE
%token l1
%token r1
%type <pair> b l r s;


%%
x: s {/*printf(" the number is %d \n",$1);*/}
 ;

s: l DOT r {$1.pos=0;$3.pos=-1;$$.val=$1.val+$3.val;/*printf(" the both numbers are %d and       %d\n",$1,$3);*/}
| l {$1.pos=0;$$.val=$1.val;/*printf(" the numbers is %d \n",$1);*/}
 ;

 l: l b {$1.pos = $$.pos + 1; $2.pos = $$.pos; $$.val = $1.val + $2.val;printf(" the   number is left,  l pos is %d and l val is %d \n", $$.pos, $$.val);}
| b   {$1.pos = $$.pos; $$.val = $1.val;printf(" the number is left,  l pos is %d and l  val is %d \n", $$.pos, $$.val);}
 ;

r: r b {$1.pos = $$.pos - 1; $2.pos = $$.pos; $$.val = $1.val + $2.val;printf(" the number     is right, r pos is %d and r val is %d \n", $$.pos, $$.val);}
| b   {$1.pos = $$.pos; $$.val = $1.val; printf(" the number is right, r pos is %d and r val is %d \n", $$.pos, $$.val);}

 ;

b: ZERO {$$.val = 0; printf(" the number is 0, val is %d and pos is %d \n",$$.val,$$.pos);}
| ONE {$$.val = 1*2^($$.pos); printf(" the number is 1, val is %d and pos is %d  \n",$$.val,$$.pos);}
 ;

%%
#include "lex.yy.c"

void yyerror (char *string){
  printf ("%s",string);
}

int main (){

    yyparse();
}

lex文件是:

%{
#include <stdio.h>
#include <math.h>
#include "y.tab.h"
%}
BINARY [0-1]
%%
"1" {return ONE;}
"0" {return ZERO;}
"." {return DOT;}
%%
4

3 回答 3

1

yacc 中的属性始终是合成属性,其值从叶子向上传播到解析树的根,而不是向下传播。

如果要使用继承属性,则需要使用btyacc 之类的工具(您可以在此处获取更新版本)。这使您可以编写如下代码:

%{
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
%}
%union {
    double  val;
    int     pos;
}

%token DOT
%token ZERO
%token ONE
%token l1
%token r1
%type <val> b(<pos>) l(<pos>) r(<pos>) s;


%%
x: s {printf(" the number is %f \n",$1);}
 ;

s: l(0) DOT r(-1) {$$=$1+$3; /*printf(" the both numbers are %f and %f\n",$1,$3);*/}
 | l(0) {$$=$1; /*printf(" the numbers is %f \n",$1);*/}
 ;

l($pos): l($pos+1) b($pos) { $$ = $1 + $2; printf(" the   number is left,  l pos is %d and l val is %f \n", $pos, $$);}
       | b($pos)   { $$ = $1; printf(" the number is left,  l pos is %d and l  val is %f \n", $pos, $$);}
       ;

r($pos): b($pos) r($pos-1) { $$ = $1 + $2; printf(" the number     is right, r pos is %d and r val is %f \n", $pos, $$);}
       | b($pos)   { $$ = $1; printf(" the number is right, r pos is %d and r val is %f \n", $pos, $$);}
       ;

b($pos): ZERO { $$ = 0; printf(" the number is 0, val is %f and pos is %d \n",$$,$pos);}
       | ONE { $$ = pow(2.0, $pos); printf(" the number is 1, val is %f and pos is %d  \n",$$,$pos);}
       ;

%%
#include "lex.yy.c"

void yyerror (const char *string, ...){
  printf ("%s",string);
}

int main (){
    yyparse();
}

请注意,我也更改valdoubleasint只能容纳整数。我还将它更改为pow用于求幂(^在 C 中是 xor)。

于 2013-10-11T04:41:41.253 回答
0

在您的操作中,您希望从 $1 和 $2 分配给 $$。所以,$$应该在'='的左边,$1和$2在右边。所以...

l: l b {$1.pos = $$.pos + 1; $2.pos = $$.pos; $$.val = $1.val + $2.val;printf(" the   number is left,  l pos is %d and l val is %d \n", $$.pos, $$.val);}
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    | b   {$1.pos = $$.pos; $$.val = $1.val;printf(" the number is left,  l pos is %d and l  val is %d \n", $$.pos, $$.val);}
           ^^^^^^^^^^^^^^^^ 
     ;

还有其他几个相同品种的。

r: r b {$1.pos = $$.pos - 1; $2.pos = $$.pos; $$.val = $1.val + $2.val;printf(" the number     is right, r pos is %d and r val is %d \n", $$.pos, $$.val);}
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| b   {$1.pos = $$.pos; $$.val = $1.val; printf(" the number is right, r pos is %d and r val is %d \n", $$.pos, $$.val);}
        ^^^^^^^^^^^^^^^

我不清楚你的表达式到底应该是什么,但 $$ 应该是 $1 和 $2 的函数。

于 2013-10-11T03:15:46.910 回答
0

$$是语义操作的结果,因此将其作为赋值的源是没有意义的。此外,您不能将值沿链传递,您必须使用其他方法将值传递给更基本的规则(如全局变量)。

于 2013-10-11T03:31:04.473 回答