2014-02-02 3 views
2

Я пытался сделать простой синтаксический анализ общих html-кодов.Shift/Уменьшить конфликт в bison

Вот мой весь файл бизона (пример4.y).

%{ 
#include <iostream> 
#include <cstring> 
using namespace std; 

extern "C" int yylex(); 
extern "C" int yyparse(); 
extern "C" FILE *yyin; 

void yyerror(const char *str) 
{ 
    cout<<"Error: "<<str<<"\n"; 
} 

int yywrap() 
{ 
    return 0; 
} 

main() 
{ 
    yyparse(); 
} 

%} 

%token NUMBER LANGLE CLOSERANGLE RANGLE SLASH ANYTHING 

%union 
{ 
    int intVal; 
    float floatVal; 
    char *strVal; 
} 

%% 

tag: | 
     opening_tag anything closing_tag 
     { 
      if(strcmp($<strVal>1,$<strVal>3)==0){ 
       cout<<"\n[i] Tag Matches: "<<$<strVal>1; 
       cout <<"\n[!] The text: "<<$<strVal>2; 
      } else { 
       cout<<"\n[!] Tag Mismatch: "<<$<strVal>1<<" and "<<$<strVal>3; 
      } 
      $<strVal>$ = $<strVal>2; 
     } 
     | 
     opening_tag tag closing_tag 
     { 
      if(strcmp($<strVal>1,$<strVal>3)==0){ 
       cout<<"\n[i] Tag Matches: "<<$<strVal>1; 
       cout <<"\n[!] The text: "<<$<strVal>2; 
      } else { 
       cout<<"\n[!] Tag Mismatch: "<<$<strVal>1<<" and "<<$<strVal>3; 
      } 
     } 
     ; 
opening_tag: 
     LANGLE ANYTHING RANGLE 
     { 
      $<strVal>$ = $<strVal>2; 
     } 
     ; 
anything: 
     ANYTHING 
     { 
      $<strVal>$ = $<strVal>1; 
     } 
     ; 
closing_tag: 
     LANGLE SLASH ANYTHING RANGLE 
     { 
      $<strVal>$= $<strVal>3; 
     }   
%% 

Ошибка я получаю: example4.y: conflicts: 1 shift/reduce

Я думаю, что он должен сделать что-то с opening_tag tag closing_tag, но я не мог думать, что здесь происходит? Любая помощь?

+0

Как определяется «что-то»? Кстати, вы можете опустить семантические действия, они не имеют отношения к конфликтам и создают только шум. –

ответ

2

Это из-за двух правил, которые начинаются с opening_tag. Парсер должен решить между правилами, глядя на большинство маркеров, но он не может. <FOO> может привести к одному из правил, и для этого требуется еще два токена.

Вы можете сделать это:

tag  : /* nothing */ 
     | opening_tag contents closing_tag 
     ; 
contents: tag 
     | anything 
     ; 

UPDATE Эта новая грамматика имеет различный сдвиг/свёртка конфликт. (UPDATE2: или, возможно, это одно и то же). Поскольку тег может быть пустым, синтаксический анализатор не может решить, что делать на этом входе:

<Foo> <... 
    ^
    | 
    input is here 

Если следующий символ косых черт, то есть закрывающий тег, а пустое правило тега должно быть согласовано. Если следующий символ не является косой чертой, то у нас есть открывающий тег, а не пустое правило тега должно быть сопоставлено. Но синтаксический анализатор не может знать, разрешено смотреть только на <.

Решение должно заключаться в создании нового токена LANGLE_SLASH для комбинации </.

+0

Пробовал это, но все та же ошибка:/ – cipher

+0

А, соры. Я смотрел на упрощенную грамматику. Ваша новая ошибка имеет другую природу, обновляющуюся мгновенно. –

+0

+1 за предложение токена LANGLE_SLASH – phlogratos

2

Проблема в том, что tag может быть пустым, так что <x>< может быть началом opening_tag tag closing_tag или opening_tag opening_tag. Следовательно, бизон не может определить, следует ли уменьшить пустой tag перед тем, как сдвинуть <.

Вы должны уметь исправить это, удалив пустую продукцию для tag и добавив явное производство для opening_tag closing_tag.

Смежные вопросы