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