2016-11-17 12 views
0

私の文法は以下の通りです。しかし、それは小さな注意点を持っている今、私はバイソンの文法の基本的な電卓の問題のため

1.0-----------------2.0 

のようなものを行うことができ、それが1個のオペアンプ2に到達するまで、それは2と-2の間でフリップフロップしますその後、評価します。 bisonにはまだまだ新しく、このための修正を実装するのが最善であるかどうかは不明です。私は1つのアイデアを念頭に置いて、3つのインクリメントで '+' ' - 'のすべての組み合わせでエラーを発生させていますが、それは8つの文法のルールであり、私はバイソンにエラーをスローする方法もわかりません。これを行うにはよりクリーンな方法があると思います。

フレックスレクサー

%option nounistd 
%option noyywrap 

%{ 
#include <io.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include "parser.tab.h" 
#define isatty _isatty 
#define fileno _fileno 
%} 

%% 
[ \t]+ 
\n {return '\n';} 
[0-9]+(\.[0-9]+)? {yylval.number=atof(yytext); return NUMBER;} 
. {return yytext[0];} 
%% 

バイソン文法

%{ 
    #include <stdio.h> 
    #include <math.h> 
    extern int yylex(void); 
    int yyerror(const char* c) { printf("%s\n",c); return 0;} 
%} 

%union 
{ 
    double number; 
} 

%type <number> exp 
%token <number> NUMBER 

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

%start commands 
%% 
commands 
    : /*empty*/ 
    | commands line 
    ; 

line 
    : '\n' 
    | exp '\n' {printf("=%f\n",$1);} 
    | error '\n' {printf("encountered an error!\n");} 
    ; 

exp 
    : NUMBER { $$ = $1;} 
    | exp '+' exp {$$ = $1 + $3;} 
    | exp '-' exp {$$ = $1 - $3;} 
    | exp '*' exp {$$ = $1 * $3;} 
    | exp '/' exp {$$ = $1/$3;} 
    | exp '^' exp {$$ = pow($1,$3);} 
    | '-' exp {$$ = -$2;} 
    | '+' exp {$$ = $2;} 
    | '(' exp ')' {$$ = $2;} 
    ; 
%% 
+0

これは私にとって正しい動作です。これが問題だと確信していますか?私はPython 2.7であなたの表現を試したところ、同じように動作します。 –

+0

実際には++や - 演算子ではなかったのは、文法に応じて '正しい動作'です。少し複雑な文法規則を実装する方法を見てみると、正しく動作しないようにしたいと思っています。残念なことに、私の新しさは、この単純な作業を達成することも困難でした。私は文法に合理性を施したいと思います。私は実際にレクサーがこれを行う方が簡単かもしれないと思っています。[+ - ] {3} {return ERROR;}のようなものです。 – user2927848

+0

実際にバイソンでエラーを起こす方法はありますか? – user2927848

答えて

3

この算術評価のために正しいと期待される動作であり、あなたはそれが--を実装していない任意の言語で同じように動作していることがわかります減分演算子。

あなたが--演算子を持っている場合は、通常のようなルールを使用して、レクサーでその実装します:a---bは、「A」としてレクサー処理されることを保証することを

"--" { return DECREMENT; } 

を「 - 」、「 - 「b」、a----bを「a」、「 - 」、「 - 」、「b」とする。 (後者は構文エラーです。)これは、ほとんどの言語標準で必要とされ、ほとんどのスキャナジェネレータで実装されている「最大マンク」ルールの結果です。

Cでは、ポストデクリメント式が左辺値ではないため、2つの連続する後置デクリメント演算子を使用することはできません。このようなコードは一般的には推奨されませんが、禁止されていません。これは文法の中で、プリ・デクリメントとポスト・デクリメントとインクリメント演算子の引数を左辺値にすることによって強制できます。しかし、C++では、構文的に正確さを簡単に判断できません。恐ろしいスタイルになりますが、参照を返すためにいくつかの型をオーバーロードするのを止めるものはありません。operator--(int)

あなたはデクリメント演算子なしで言語を持っていますが、あなたがしたい、いくつかの審美的な理由のために、二つの連続単項演算子と式を禁止する場合は上記の示唆したように、あなたは同じようにそれを行うことができ、例えば:

ここで
value: NUMBER | '(' expr ')' 
term: value | '-' value | '+' value 
expr: term | expr '-' expr | expr '+' expr | expr '*' expr | expr '/' expr | ... 

単項演算子のみvalueに適用することができ、valueは単項演算子で始めることはできませんので、あなたが--a(または-+a)を持つことができません。したがって、エンドユーザーは強制的にかっこを使用します。しかし、少なくとも制限を課す必要があると感じている理由を知りたいエンドユーザにとっては、満足のいく答えを出しておく必要があります。