-1

次のyaccコードを試していますが、shift/reduceエラーが発生しています。私はこれにかなり新しいです

The Purpose of the code is to prepare the syntax for if - else with logical operators also incorporated

           %{
               #include<stdio.h>
               #include"lex.yy.c"
               int syntax_status=0;
           %}
           %token IF ELS id EE LE GE closep openp num openb closeb SP logicop 
           %start S
           %%
           S : S SP IF SP openp SP EXP SP closep SP openb SP closeb SP ELS SP openb SP closeb SP {syntax_status=1;}
             | S SP IF SP openp SP EXP SP closep SP openb SP closeb SP {syntax_status = 1;}
             | 
             ;
         EXP : EXP CMP logicop CMP
             | EXP CMP
             |
             ;
         CMP : CMP id EE id 
             | CMP id LE id
             | CMP id GE id
             | CMP id EE num
             | CMP id GE num
             | CMP id LE num
             | CMP num EE id
             | CMP num GE id
             | CMP num LE id
             | 
             ;
         %%
         int main()
         {
              printf("\n\n\n Enter the Syntax :  ");
              yyparse();
              if(syntax_status==1)
              {
                     printf("\n\n\n The Syntax is Correct ");
              }
              else
              {
                     printf("\n\n\n The Syntax is Imcorrect");
              }
              return 0;
          }
          yyerror(char *s)
          {
              syntax_status=0;
          }

この対応するyaccコードのLexプログラムは次のとおりです。

           %{
              #include<stdio.h>
              #include"y.tab.h"
           %}
           IF (if)
           ELS (else)
           iden [a-zA-Z][a-zA-Z0-9]*
           num [0-9]+
           space [ ]* 
           %%
           {IF} { return IF; }
           {ELS} {return ELSE;}
           {iden} {return id;}
           (==) {return EE;}
           (<=) { return LE;}
           (>=) { return GE;}
           ")" { return closep;}
           "(" { return openp;}
          {num} { return num;}
          {space} { return SP; }
          "{" { return openb;}
          "}" { return closeb;}
          "||"|"&&"|"!=" {return logicop;}

%%

4

2 に答える 2

2

演算子の優先順位と結合性を指定する必要があります。たとえば、ここを参照してください。私は宗派から引用します。6

これらの宣言の動作の例として、説明

    %right  '='
    %left  '+'  '-'
    %left  '*'  '/'

    %%

    expr    :       expr  '='  expr
            |       expr  '+'  expr
            |       expr  '-'  expr
            |       expr  '*'  expr
            |       expr  '/'  expr
            |       NAME
            ;

入力を構造化するために使用される可能性があります

    a  =  b  =  c*d  -  e  -  f*g

次のように:

    a = ( b = ( ((c*d)-e) - (f*g) ) )

CMP演算子は同様の方法で定義する必要があり、分割する必要がありますlogicop。ブール式で通常の読みを取得するには、通常、単項マイナスのように動作せず、*のように動作し、+のように動作します。

HTH

于 2012-10-15T10:53:06.810 に答える
2

CMPルールとEXPルールはどちらも非常に問題があるように見えます。この右端の派生を例にとってみましょう。

 EXP ==> (by EXP -> CMP)
 EXP CMP ==>  (by CMP -> CMP id EE id)
 EXP CMP id EE id ==> (by CMP -> CMP id EE id)
 EXP CMP id EE id id EE id ==> (by CMP -> epsilon)
 EXP id EE id id EE id ==> (by EXP -> epsilon )
 id EE id id EE id ==>
 id == id id == id

私はこれがあなたが望むものではないとかなり確信しています。また、文法にあいまいさを導入します。同じ文字列の端末を、この異なる右端の派生によって派生させることができます。

 EXP ==> (by EXP -> CMP)
 EXP CMP ==> (by CMP -> CMP id EE id)
 EXP CMP id EE id ==> (by CMP -> epsilon)
 EXP id EE id ==> (by EXP -> CMP)
 EXP CMP id EE id ==> (by CMP -> CMP id EE id)
 EXP CMP id EE id id EE id ==> (by CMP -> epsilon)
 EXP id EE id  id EE id ==> (by EXP-> epsilon)
 id EE id  id EE id ==>
 id == id id == id

id == id id == idほら、yaccは本当にexp expかどうかを知る方法がありませんexp。また、exp-> epsilonルールでは、のような式を使用できますがif(){}、これはあまり適切ではありません。

ここで、次の文法について考えてみましょう。

 exp -> exp logicop cmp | cmp
 cmp -> rvalue < rvalue | rvalue > rvalue ...
 rvalue -> id | num

しかし、次のようにすることもできます。

exp -> exp op exp | rvalue
op -> "||" | "&&" | "<" | ">" ...

後者はそれを行う従来の方法ですが、オペランドが正しいタイプであることを確認するためにセマンティックチェックが必要ですが、前の文法は構文レベルでそれを確認します。長期的には(ブール変数を導入した後)、型の安全性は構文ではなくセマンティクスの問題であるため、2番目のアプローチがはるかに望ましいです。

別の注意点:スペースはあなたの言語には関連していないようですが、lexはそれらをyaccに渡します。次のように言うことで、lexに字句レベルのスペースを破棄させることができます

{space} //nothing after a pattern discards the matched characters

これにより、yaccでこれらすべてのSPを書き出すという頭痛の種を減らすことができます。

于 2012-10-15T11:45:27.727 に答える