Как решить бизон уменьшить / уменьшить конфликт в моем коде? - PullRequest
0 голосов
/ 12 мая 2018

Я новичок в бизоне. Я написал грамматическое правило для оператора if, else if и else. Я перепробовал все, что нашел, но, как я уже сказал, я новичок, и я точно не понимаю, что происходит ..

Вот мой код:

ifinstr: KW_IF expr_decl KW_THEN statements elseifinstr elseinstr KW_END  
;
elseifinstr : %empty {$$ = "";}
            | elseifinstr KW_ELSE KW_IF expr_decl KW_THEN statement 
;
elseinstr : %empty {$$ = "";}
          | KW_ELSE statement
;

Я тоже пробовал это решение, но вместо этого получил конфликт сдвиг / уменьшение:

ifinstr: KW_IF expr_decl KW_THEN statements elseifinstr KW_END  
;
elseifinstr : %empty {$$ = "";}
            | elseifinstr KW_ELSE KW_IF expr_decl KW_THEN statement 
            | KW_ELSE statement 
;

1 Ответ

0 голосов
/ 12 мая 2018

Проблема в том, что предлагаемая вами грамматика неоднозначна.(Я имею в виду первую грамматику. Предлагаемое второе решение - это другой язык.)

Языки, которые используют конструкцию «else if» для сокращения вложенности скобок «if… end», используютспециальный токен:

Ruby               Python                VB                  Shell
----------------   -------------------   -----------------   --------------------
if n > 0           if n > 0:             If n > 0 Then       if ((n>0)); then
  puts "Greater"     print ("Greater")     Print "Greater"     echo Greater
elsif n == 0       elif n == 0:          ElseIf n = 0 Then   elif ((n==0)); then
  puts "Equal"       print ("Equal")       Print "Equal"       echo Equal
else               else:                 Else                else
  puts "Less"        print ("Less")        Print "Less"        echo Less
end                                      End                 fi

Без слияния "else if" эти выражения были бы намного более громоздкими:

Ruby               Python                VB                  Shell
----------------   -------------------   -----------------   --------------------
if n > 0           if n > 0:             If n > 0 Then       if ((n>0)); then
  puts "Greater"     print ("Greater")     Print "Greater"     echo Greater
else               else:                 Else                else 
  if n == 0          if n == 0:            If n = 0 Then       if ((n==0)); then
    puts "Equal"       print ("Equal")       Print "Equal"       echo Equal
  else               else:                 Else                else
    puts "Less"        print ("Less")        Print "Less"        echo Less
  end                end                   End                 fi
end                                      End                 fi

Это контрастирует с такими языками, как C, Java и многими другими, которыене требуйте, чтобы операторы «если» были прекращены, и, таким образом, демонстрировали конфликт «свисающий еще», сдвиг-уменьшение, который всегда разрешался в пользу сдвига.В этих языках, так как предложение «else» просто присоединяется к ближайшему несогласованному предложению «if», нет необходимости предоставлять специальный токен «else-if».

Теперь вы пытаетесь объединить этидва подхода с использованием слитного «else-if» без слияния, и это просто приводит к той же висячей проблеме else, которую пытался исправить явный брекетинг.Рассмотрим, например:

 if C1 then S1 else if C2 then S2 else if C3 then S3 else S4 end S5 end

Теперь, что из следующих двух это представляет?

 if C1 then                       if C1 then
   S1                               S1
 else if C2 then                  else
   S2                               if C2 then
 else                                 S2
   if C3 then                       else if C3 then
     S3                               S3
   else                             else
     S4                               S4
   end                              end
   S5                               S5
 end                              end   

(Со временем я мог бы найти более простой пример. Выше две интерпретацииразличаются обстоятельствами, в которых выполняется S5.)

Самое простое решение - использовать какой-то перегруженный токен «else if», как в приведенных выше примерах различных языков.(Или придумай свое :-))

...