2016-11-17 1 views
0

아래의 문법은 '작동합니다'. 그러나 작은주의가 지금은Bison 문법의 기초 계산기 문제

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

같은 물건을 할 수 있으며이 둘 사이의 플립 플롭 것이다 -2는 1 개 연산 2 다음 평가합니다 할 때까지이있다. bison에 대한 새로운 지식과 이에 대한 수정을 구현하는 것이 가장 좋은 방법에 대해 명확하지 않습니다. 나는 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

나에게 올바른 행동입니다. 이것이 문제가 확실합니까? 방금 파이썬 2.7에서 당신의 표현을 시도해 보았습니다. –

+0

문법에 따라 '올바른 동작', 실제로 ++ 또는 - 연산자가 아닌 경우입니다. 좀 더 복잡한 문법 규칙을 구현하는 방법을 알아보기위한 테스트와 같은 올바른 행동이 아닌 '올바른 행동'으로 만들고 싶습니다. 불행히도, 나의 새로운 점은이 간단한 작업조차도 성취하기가 어렵습니다. 나는 문법에 대해 합리성을 강요하고 싶습니다. 나는 실제로 렉서가 이것을하기 더 쉬울 수도 있다고 생각하기 시작했다. [+ -] {3} {return ERROR;}와 같은 것. – user2927848

+0

어떻게 들소에 실제로 오류가 발생합니까? – user2927848

답변

3

이 산술 평가를위한 정확하고 예상되는 동작이며, 당신은이 --를 구현하지 않는 언어에서 동일하게 작동하는 것을 발견 할 것이다 감소 연산자.

당신이 -- 연산자가있는 경우, 당신은 일반적으로 같은 규칙을 사용하여 렉서에서 그 구현하는 것이 : a---b는, "A"로 lexed되는 것을 보장합니다 그

"--" { return DECREMENT; } 

을 "-", "- ","b "및 a----b은"a ","- ","- ","b "로 표시됩니다. 후자는 문법 오류입니다. 이것은 대부분의 언어 표준에서 요구되고 대부분의 스캐너 생성기에서 구현되는 "최대 뭉크"규칙의 결과입니다. 그와 같은 코드를 작성하는 것은 일반적으로 권장되지 않지만 금지되지는 않습니다.

C에서는 사후 감소 표현식이 좌변 값이 아니기 때문에 두 개의 연속 사후 감소 연산자를 사용할 수 없습니다. 그것은 선행 및 사후 감소와 증가 연산자의 대립을 lvalue로 요구함으로써 문법에서 시행 될 수있다. 하지만 C++에서는 구문 적으로 정확성을 쉽게 판단 할 수 없습니다. 그것은 끔찍한 스타일 일 것이지만, 어떤 타입에 대해서는 참조를 반환하기 위해 오버로드하는 것을 막을 수 없습니다. 위의 암시로 당신이 감소 연산자가없는 언어를 가지고 있지만 당신이 원하는 경우

, 어떤 미적 이유로, 두 개의 연속 단항 연산자와 표현을 금지하는, 당신은

: 예를 들어, 같은 방법으로 그렇게 할 수 여기
value: NUMBER | '(' expr ')' 
term: value | '-' value | '+' value 
expr: term | expr '-' expr | expr '+' expr | expr '*' expr | expr '/' expr | ... 

, 당신은 단항 연산자 만 value에 적용 할 수 있기 때문에 --a (또는 -+a)을 가질 수 없습니다와 value는 단항 연산자로 시작할 수 없습니다. 따라서 최종 사용자는 괄호를 사용해야합니다. 그러나 적어도 제한을 가할 필요가 있다고 생각하는 이유를 알고 싶어하는 최종 사용자에게는 만족스러운 대답을 준비해야합니다.