2016-11-17 68 views
0

所以我的語法低於'有效'。然而,它具有體積小告誡我現在可以做的東西一樣基本計算器的野牛語法問題

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

,它會翻轉2之間翻牌-2直到它到達1個OP 2,然後將評估。對野牛來說還是一個新的問題,並且不清楚如何最好地爲此實施解決方案。我有一個想法,提出一個錯誤'+'''的增量爲3,但是這是8個語法規則,我甚至不知道如何拋出一個錯誤的野牛。我想有一個更清晰易懂的方法來做到這一點。

的Flex詞法

%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

這是算術評估正確和期望的行爲,你會發現它同樣工作在不執行任何--語言遞減運算符。

如果你有一個--運營商,你通常會實現,在與規則的詞法分析器,如:

"--" { return DECREMENT; } 

這將保證a---b被lexed爲 「A」, 「 - 」,「 - 「,」b「和a----b分別爲」a「,」 - 「,」 - 「,」b「。 (後者是語法錯誤。)這是「最大蒙克」規則的結果,這是大多數語言標準所要求的,並且由大多數掃描生成器實現。 (編寫這樣的代碼通常是不鼓勵但不禁止的。)

在C中,由於後減量表達式不是左值,因此不能使用兩個連續的後減法運算符。這可以通過要求前後遞減和遞增運算符爲左值的論點在語法中強制執行。但是在C++中,你無法輕鬆地從句法上判斷正確性;雖然它會是可怕的風格,但是沒有什麼能阻止你爲某些類型重載operator--(int)以返回參考。

如果你有沒有減量運算符的語言,但你想,對於一些美學原因,禁止連續兩元運算符表達式,那麼你可以做的是,在相同的方式,上面所暗示的,例如:

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

在這裏,你不能有--a(或-+a),因爲一元運算符只能應用於valuevalue不能以一元運算符開始。所以最終用戶將被迫使用括號。但是你至少應該爲最終用戶準備好令人滿意的答案,他們想知道爲什麼你覺得有必要施加這種限制。