-1

다음 yacc 코드를 시도하고 m/shift 오류 수신 중입니다. 나는이 해당 yacc를 코드에 대한이Shift Shift YACC의 충돌 감소

The Purpose of the code is to prepare the syntax for if - else with logical operators also incorporated

  %{ 
       #include<stdio.h> 
       #include"lex.yy.c" 
       int syntax_status=0; 
      %} 
      %token IF ELS id EE LE GE closep openp num openb closeb SP logicop 
      %start S 
      %% 
      S : S SP IF SP openp SP EXP SP closep SP openb SP closeb SP ELS SP openb SP closeb SP {syntax_status=1;} 
      | S SP IF SP openp SP EXP SP closep SP openb SP closeb SP {syntax_status = 1;} 
      | 
      ; 
     EXP : EXP CMP logicop CMP 
      | EXP CMP 
      | 
      ; 
     CMP : CMP id EE id 
      | CMP id LE id 
      | CMP id GE id 
      | CMP id EE num 
      | CMP id GE num 
      | CMP id LE num 
      | CMP num EE id 
      | CMP num GE id 
      | CMP num LE id 
      | 
      ; 
     %% 
     int main() 
     { 
       printf("\n\n\n Enter the Syntax : "); 
       yyparse(); 
       if(syntax_status==1) 
       { 
        printf("\n\n\n The Syntax is Correct "); 
       } 
       else 
       { 
        printf("\n\n\n The Syntax is Imcorrect"); 
       } 
       return 0; 
      } 
      yyerror(char *s) 
      { 
       syntax_status=0; 
      } 

렉스 프로그램에 대한 아주 새로운 M은 다음과 같다 :

  %{ 
       #include<stdio.h> 
       #include"y.tab.h" 
      %} 
      IF (if) 
      ELS (else) 
      iden [a-zA-Z][a-zA-Z0-9]* 
      num [0-9]+ 
      space [ ]* 
      %% 
      {IF} { return IF; } 
      {ELS} {return ELSE;} 
      {iden} {return id;} 
      (==) {return EE;} 
      (<=) { return LE;} 
      (>=) { return GE;} 
      ")" { return closep;} 
      "(" { return openp;} 
      {num} { return num;} 
      {space} { return SP; } 
      "{" { return openb;} 
      "}" { return closeb;} 
      "||"|"&&"|"!=" {return logicop;} 

%%

답변

2

CMP 및 EXP 규칙은 모두 매우 문제가있는 것처럼 보입니다. 이 가장 오른쪽 파생을 예로 들면 다음과 같습니다.

EXP ==> (by EXP -> CMP) 
EXP CMP ==> (by CMP -> CMP id EE id) 
EXP CMP id EE id ==> (by CMP -> CMP id EE id) 
EXP CMP id EE id id EE id ==> (by CMP -> epsilon) 
EXP id EE id id EE id ==> (by EXP -> epsilon) 
id EE id id EE id ==> 
id == id id == id 

나는 이것이 당신이 원하는 것이 아니라고 확신합니다. 또한 문법에 모호함을 소개 : 터미널의 동일한 문자열이 다른 맨 오른쪽 유도에 의해 유도 될 수있다 : id == id id == id 정말 exp exp 또는 exp 경우

당신이 볼
EXP ==> (by EXP -> CMP) 
EXP CMP ==> (by CMP -> CMP id EE id) 
EXP CMP id EE id ==> (by CMP -> epsilon) 
EXP id EE id ==> (by EXP -> CMP) 
EXP CMP id EE id ==> (by CMP -> CMP id EE id) 
EXP CMP id EE id id EE id ==> (by CMP -> epsilon) 
EXP id EE id id EE id ==> (by EXP-> epsilon) 
id EE id id EE id ==> 
id == id id == id 

는, yacc를가 알 방법이 없습니다. 또한, exp-> 엡실론 규칙은 if(){}과 같은 표현식을 허용합니다. 이는 그리 좋지 않습니다. 이제

다음 문법 고려 :

exp -> exp logicop cmp | cmp 
cmp -> rvalue < rvalue | rvalue > rvalue ... 
rvalue -> id | num 

을 그러나 그것은 또한 다음과 같이 할 수있다 :

exp -> exp op exp | rvalue 
op -> "||" | "&&" | "<" | ">" ... 

후자는 그 일의 전통적인 방법이지만, 당신이 의미 필요할 것 피연산자가 올바른 유형인지 확인하고 이전 문법은 구문 수준에서이를 보장합니다. 장기적으로 (일단 부울 변수를 도입하면) 두 번째 접근 방식이 훨씬 바람직합니다. 유형 안전은 구문론이 아니라 의미론의 문제이기 때문입니다.

또 다른주의 사항 : 공란은 당신의 언어와 관련이없는 것 같지만, 렉스는 그들을 yacc에게 넘깁니다.당신은

{space} //nothing after a pattern discards the matched characters 

이 당신에게 yacc에있는 모든 사람들의 SP를 작성하는 두통을 절약 할 말을함으로써 렉스는 어휘 수준에서 공간을 취소 할 수 있습니다.

1

을 수행해야 운영자의 우선 순위 및 연관성을 지정하십시오 :참조 예를 들어. 나는 교단에서 인용한다. 이러한 선언의 동작의 예로서 6

, 다음

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

    %% 

    expr :  expr '=' expr 
      |  expr '+' expr 
      |  expr '-' expr 
      |  expr '*' expr 
      |  expr '/' expr 
      |  NAME 
      ; 

입력을

a = b = c*d - e - f*g 

를 구성하는 데 사용될 수있는 설명 :

a = (b = (((c*d)-e) - (f*g))) 

CMP 연산자는 비슷한 방법으로 정의해야하며 logicop을 나누어야합니다. 부울 식에서 일반적인 읽기를 얻으려면 대개 NOT은 단항 빼기처럼 작동하고 *와 같거나 +와 유사합니다.

HTH