2

こんにちは良いプログラマー、

私は幸せな(haskell)で次の文法を構築しました:

P  :  program  C             {Prog $2}


E  :  int            {Num $1}
   |  ident           {Id $1}
   |  true           {BoolConst True}
   |  false          {BoolConst False}
   |  read           {ReadInput}
   |  '(' E ')'              {Parens $2}
   |  E '+' E                { Add $1 $3 }
   |  E '-' E                { Sub $1 $3 }
   |  E '*' E                { Mult $1 $3 }
   |  E '/' E                { Div $1 $3 }
   |  E '=' E                { Eq $1 $3 }
   |  E '>' E                { Gt $1 $3 }
   |  E '<' E                { Lt $1 $3 }


C  :   '(' C ')'             {$2}
   |  ident assign E         {Assign $1 $3}
   |  if E then C else C     {Cond $2 $4 $6}  
   |  output E               {OutputComm $2}
   |  while E do C           {While $2 $4 }
   |  begin D ';' C end      {Declare $2 $4}
   |  C ';' C                {Seq $1 $3 }


D  :  D ';' D                {DSeq $1 $3 } 
   |  '(' D ')'              {$2}
   |  var ident assign E     {Var $2 $4} 

これで、While ループには、「do」の後に続くすべてのコマンドが含まれます。この動作を変更するにはどうすればよいですか? 私はすでに %left、%right を試しました... :(

4

2 に答える 2

2

Cシーケンスを許可するものと許可しないものの2種類を発明します。このようなもの、おそらく:

Cnoseq : '(' Cseq ')'
       | ident assign E
       | while E do Cnoseq

Cseq : Cnoseq ';' Cseq
     | Cnoseq
于 2012-05-28T21:47:30.260 に答える
2

このコードフラグメントを考えてみましょう。

while True do output 1 ; output 2

これは、次のいずれかとして解析できます。

(while True do output 1) ; (output 2)

また

while True do (output 1 ; output 2)

この種のあいまいさは、対立の原因です。

@DanielWagnerが提案したように文法を変更したくない場合は、優先順位ルールを使用してあいまいさを解決できます。正確には、優先順位がどうあるべきかによって異なりますが、おそらく次のようになります。

%right do
%right then else
%right ';'

優先順位は低いものから高いものへとリストされているため、この場合、上記の例は後者の方法で解析されます。トークンの下、行の前に優先順位ルールを追加するだけ%%です。

于 2012-05-29T10:38:05.913 に答える