次: Simple Error Recovery, 前: RPN Calc, 上: Examples
calc後置記法演算子に代わって中間記法演算子を扱うように rpcalcを変更します。 中間記法には、演算子の優先順位の概念と、 適切な深さに入れ子できるかっこが必要です。 中間記法電卓を作るためのBisonソースファイル calc.yを示します。
/* 中間記法電卓 -- calc */
%{
#define YYSTYPE double
#include <math.h>
%}
/* BISON宣言 */
%token NUM
%left '-' '+'
%left '*' '/'
%left NEG /* negation--単項マイナス */
%right '^' /* べき乗関数 */
/* 文法規則が続く */
%%
input: /* 空文字列 */
| input line
;
line: '\n'
| exp '\n' { printf ("\t%.10g\n", $1); }
;
exp: NUM { $$ = $1; }
| exp '+' exp { $$ = $1 + $3; }
| exp '-' exp { $$ = $1 - $3; }
| exp '*' exp { $$ = $1 * $3; }
| exp '/' exp { $$ = $1 / $3; }
| '-' exp %prec NEG { $$ = -$2; }
| exp '^' exp { $$ = pow ($1, $3); }
| '(' exp ')' { $$ = $2; }
;
%%
yylex、yyerror、main関数は、
前の例のものと同じです。
このプログラムには、2つの重要な特徴があります。
第2の部分(Bison宣言部)では、
%leftがトークンの型とそれが左結合演算子であると宣言します。
宣言%leftと%right(右結合演算子)は、
結合性を持たないトークン型名を宣言するために使われる%tokenの代わりに
なります
(1文字のリテラルであるトークンは、通常、宣言する必要がありません。
ここでは、結合性を宣言します)。
演算子の優先順位は、宣言が書かれる行の順序で決まります。
後から宣言された演算子ほど、高い優先順位を持ちます。
したがって、べき乗の優先順位がもっとも高く、
単項の負(NEG)、「`*'」と「`/'」と続きます。
See Operator Precedence。
もう1つの重要な特徴は、単項の負の演算子のために文法部分にある
%precです。
%precは、単純にBisonに対して、規則`| '-' exp'は
NEGと同じ優先順位を持つように指示し、
この例ではどちらも2番目に高い優先順位を持ちます。
以下はcalc.yの実行例です。
% calc
4 + 4.5 - (34/(8*3+-3))
6.880952381
-56 + 2
-54
3 ^ 2
9