2012-02-01 3 views
3

Как я могу заставить конфликт shift \ reduce разрешить методом GLR?
Предположим, что я хочу, чтобы анализатор разрешал конфликт между оператором правой смены и двумя скобками угла закрытия аргументов шаблона для себя. Я делаю lexer пропускать два последовательных символа «>» в ​​виде отдельных токенов, не объединяя их в один единственный токен «>>». Затем я помещаю эти правила в грамматику:Bison, C++ GLR синтаксический анализ: как заставить shift уменьшить конфликт?

operator_name: 
    "operator" ">" 
    | "operator" ">" ">" 
; 

Я хочу, чтобы это было конфликтом перехода/уменьшения. Если у меня есть объявление токена для «>» с левой ассоциативностью, это не будет конфликтом. Поэтому мне нужно удалить объявление приоритета токена \ ассоциативность, но это приводит ко многим другим конфликтам, которые я не хочу решать вручную, указав контекстуальный приоритет для каждого конфликтующего правила. Итак, есть ли способ заставить shift \ уменьшить конфликт при объявлении маркера?

+0

«+1» для рассмотрения «>» как отдельный токен, чем оператор сдвига или тег закрытия тега.То же самое происходит и для «-», «отрицательный знак» или «оператор замещения». – umlcat

+0

Да, я помню, используя эту технику для C# и Java, но эти синтаксические анализаторы были ANTLR-based, и это было немного проще, хотя и не без хакеров. – slavasav

ответ

2

Я считаю, что использование правил для operator_name будет работать с использованием context-dependent precedence.

Грамматика C++, как указано в обновленном стандарте, фактически модифицирует грамматику, чтобы принять >> токен как закрытие двух открытых объявлений шаблонов. Я бы рекомендовал следовать за ним, чтобы получить стандартное поведение. Например, вы должны быть осторожны, чтобы «x>> y» не анализировался как «x >> y», и вы также должны убедиться, что «foo < bar < 2 >> 1 >>» недействителен, а «foo < бар < (2 >> 1) >> ".

+0

Оказывается, бизоны считают конфликт решаемым, когда вы указываете зависящее от контекста приоритет. То есть, если я явно укажу, что я хочу, чтобы приоритет первого правила был таким же, как и для второго правила, чтобы иметь конфликт shift \ reduce, бизон решает перейти вместо того, чтобы оставить конфликт разрешенным glr в во время выполнения. – slavasav

0

Я работал в Yacc (аналогично Bison), с похожим сценарием.

Стандартные грамматики иногда называются «синтаксический разбор по синтаксису».

Этот случай иногда называется чем-то вроде «синтаксический анализ, ориентированный на семантику».

Пример:

... 
// shift operator example 
if ((x >> 2) == 0) 
... 
// consecutive template closing tag example 
List<String, List<String>> MyList = 
... 

Давайте помнить, наш разум работает как компилятор. Человеческий ум может скомпилировать это, но предыдущие грамматики не могут. Mhhh. Давайте посмотрим, как человеческий разум скомпилирует этот код.

Как вы уже знаете, «x» перед последовательными токенами «>» и «>» указывает выражение или значение lvalue. Разум думает, что «два последовательных символа больше, чем символы, после выражения, должны стать одним символом оператора сдвига».

И для токена «строка»: «два последовательных символа большего размера, после идентификатора типа, должны стать двумя последовательными тегами для закрытия тегов».

Я думаю, что этот случай не может быть обработан обычным приоритетом, сдвигом или сокращением оператора или просто грамматиками, но с использованием («взлома») некоторых функций, предоставляемых самим парсером.

Я не вижу ошибки в вашем правиле грамматики примера. Символ «оператора» позволяет избежать путаницы двух случаев, о которых вы говорите. Части, которые должны быть связаны с его грамматиками, в которых используется оператор сдвига, и последовательные метки закрытия шаблона.

operator_expr_example: 
    lvalue "<<" lvalue | 
    lvalue ">>" lvalue | 
    lvalue "&&" lvalue | 
; 

template_params: 
    identifier | 
    template_declaration_example | 
    array_declaration | 
    other_type_declaration 
; 

template_declaration_example: 
    identifier "<" template_params ">" 
; 

Cheers.

+0

Хорошо, я использовал пример оператора, чтобы прояснить этот случай. Учитывая, что «наш ум работает, как компилятор», я согласен, и есть способ, которым мы можем влиять на синтаксический анализ, используя бесконечный просмотр. Но в этом случае с glr, bison деферирует все семантические действия всякий раз, когда он разбивает стеки синтаксического анализа, чтобы разрешить конфликт, и выполняет эти действия, когда он возвращается в детерминированное состояние, поэтому слишком поздно влиять на анализ синтаксиса в то время. – slavasav

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