Приоритет выражений и неоднозначность

В настоящее время я работаю над тем, чтобы Rust-lang можно было анализировать с помощью Rascal. Первоначально используемый синтаксис создан для Bison, поэтому я перевожу его, чтобы его можно было использовать. Камнем преткновения, которого я достиг, являются выражения. В файле Bison Rust есть четыре типа выражений: nonblock_expr, expr, nonparen_expr и expr_nostruct. Мои существующие переводы полны неясностей, но даже после прочтения документации Rascal по теме и доступного синтаксиса для Rascal и Java я не уверен, как решить эту проблему. Я хотел бы исправить неясности и лучше понять, как эта проблема может быть устранена в дальнейшем.

Вот пример моего перевода:

syntax Expression
    = Literal
    > Path_expression
    | "self"
    | Macro_expression
    | Path_expression "{" Structure_expression_fields "}"
    | Expression "." Path_generic_args_with_colons
    //> left Expression "." Literal_integer
    | Expression "[" Expression? "]"
    | Expression "(" (Expressions ","?)? ")"
    | "(" (Expressions ","?)? ")"
    | "[" Vector_expression "]"
    | "continue"
    | "continue" Identifier
    | "return"
    | "return" Expression
    | "break"
    | "break" Identifier
    > left  ( Expression "*" Expression
            | Expression "/" Expression
            | Expression "%" Expression
            )
    > left  ( Expression "+" Expression
            | Expression "-" Expression
            > Expression "\<\<" Expression
            | Expression "\>\>" Expression
            > Expression "&" Expression
            > Expression "^" Expression
            > Expression "|" Expression
            > Expression "\<" Expression
            | Expression "\>" Expression
            | Expression "\<=" Expression
            | Expression "\>=" Expression
            > Expression "==" Expression
            | Expression "!=" Expression
            > Expression "||" Expression
            > Expression "&&" Expression
            )
    > right Expression "\<-" Expression
    > right ( Expression "=" Expression
            | Expression "\<\<=" Expression
            | Expression "\>\>=" Expression
            | Expression "-=" Expression
            | Expression "&=" Expression
            | Expression "|=" Expression
            | Expression "+=" Expression
            | Expression "*=" Expression
            | Expression "/=" Expression
            | Expression "^=" Expression
            | Expression "%=" Expression
            )
    | Expression ".."
    | Expression ".." Expression
    | ".." Expression
    | ".."
    | Expression "as" Type
    | "box" Nonparen_expression
    > "box" "(" Expression? ")" Expression
    | Expression_qualified_path
    | Block_expression
    | Block
    | Nonblock_prefix_expression
    ;

Источники:

Файл Rust Bison: Github Rust

Файл Oxidize Rascal: Github Oxidize

Добавлен пример неоднозначности Это пример входного файла (только неоднозначная часть файла находится в параметрах синтаксического анализа).

fn main() {
    let mut config = Config::parse(&flags.build, flags.config.clone());
}

Выходное дерево синтаксического анализа, как показано ниже, кажется запутанным в конструкции выражения с префиксом (&). Эта двусмысленность не может решить между Nonblock_prefix_expression и Expression "." Path_generic_args_with_colons. Я ожидаю, что он проанализирует файл Nonblock_prefix_expression. введите здесь описание изображения


person Adrian Z.    schedule 11.04.2017    source источник
comment
Привет, Адриан, вопрос очень широкий. Я дам очень конкретный ответ, чтобы сделать следующий шаг, но мы также должны обменяться мыслями об общих идеях устранения неоднозначности. См. meta-environment.org/doc/books. /syntax/sdf-disambiguation/ для пошагового обзора с пояснениями.   -  person Jurgen Vinju    schedule 12.04.2017
comment
Я вижу некоторую двусмысленность в этой грамматике, когда ключевые слова не резервировались бы от идентификаторов, таких как box и self.   -  person Jurgen Vinju    schedule 12.04.2017
comment
@jurgenv Я почитаю о неоднозначности. Что вы имеете в виду под не зарезервировано? Ключевые слова Rust исключены из области действия идентификатора (Идентификатор \ Rust_keywords). Этого нет в этом примере, но я мог бы обновить его.   -  person Adrian Z.    schedule 12.04.2017
comment
Может быть, неплохо было бы привести пример небольшого выражения, которое многозначно? И как вы ожидаете, что это будет проанализировано?   -  person Davy Landman    schedule 12.04.2017
comment
Я обновил вопрос с примером.   -  person Adrian Z.    schedule 12.04.2017


Ответы (1)


  • Взгляните на http://www.meta-environment.org/doc/books/syntax/sdf-disambiguation/sdf-disambiguation.pdf для общей концепции устранения неоднозначности и пошагового подхода к устранению неоднозначности. Это руководство было написано для SDF2, который имеет много общего с Rascal. Однако обратите внимание на различия, {prefer} и {avoid} отсутствуют в Rascal, но их можно смоделировать с помощью библиотеки (не рекомендуется).
  • Инструмент DrAmbiguity может помочь автоматизировать диагностику неоднозначности: import analysis::grammars::Ambiguity; и diagnose(yourAmbiguousTree), он довольно грубо объясняет, в чем различия и общие черты между разными альтернативными деревьями синтаксического анализа для одной и той же подстроки. Различия являются причиной двусмысленности: правила и порядок применения правил, которые используются в одном варианте, но не используются в другом. Причина может быть устранена путем применения фильтров устранения неоднозначности, которые удаляют только одну из двух альтернатив (поэтому они фокусируются на различиях).
  • Если у вас есть конкретные неясности с примером входного предложения и выходных деревьев (как можно меньше), мы можем помочь на stackoverflow.com
person Jurgen Vinju    schedule 12.04.2017
comment
Я использовал DrAmbiguity, но результат его работы не всегда ясен. Я попытаюсь использовать его снова с несколькими примерами. Через несколько минут я добавлю пример двусмысленности. - person Adrian Z.; 12.04.2017
comment
Вы можете упростить это до следующего неоднозначного примера: &flags.build. Грамматика сильно стратифицирована, что делает ее немного запутанной. Непосредственная проблема заключается в том, что неясно, следует ли анализировать это как (&(flags.build)) или (&flags).build, поскольку оба варианта разрешены грамматикой и оба имеют одинаковый приоритет. - person Mark Hills; 13.04.2017
comment
Это было решено путем более эффективного использования функциональности Rascal, объединения всех упомянутых выражений и просмотра одиночных операторов, которые могут иметь версию с двойным оператором (пример & и &&). github.com/zborowa/ оксидировать/блоб/мастер/источник/язык/ржавчина/синтаксис/ - person Adrian Z.; 19.06.2017