24.8.1.2 Грамматики прецедента операторов

Грамматики прецедента SMIE просто присваивают каждому токену пару прецедентов: левый прецедент и правый прецедент. Мы говорим, что T1 < T2 если правый прецедент токена T1 меньше левого прецедента токена T2. Хороший способ прочитать этот < — как своего рода скобка: если мы находим ... T1 что-то T2 ..., то это должно быть разобрано как ... T1 (что-то T2 ..., а не как ... T1 что-то) T2 .... Последняя интерпретация была бы верна, если бы у нас было T1 > T2. Если у нас есть T1 = T2, это означает, что токен T2 следует за токеном T1 в той же синтаксической конструкции, поэтому обычно у нас есть "begin" = "end". Такие пары прецедентов достаточны для выражения левой или правой ассоциативности бинарных операторов, вложенности токенов, таких как скобки, и многих других случаев.

Функция: smie-prec2->grammar table

Эта функция принимает грамматику prec2 table и возвращает alist, подходящий для использования в smie-setup. prec2 table сама по себе должна быть построена одной из функций ниже.

Функция: smie-merge-prec2s &rest tables

Эта функция принимает несколько prec2 tables и объединяет их в новую таблицу prec2.

Функция: smie-precs->prec2 precs

Эта функция строит таблицу prec2 из таблицы прецедентов precs. precs должна быть списком, отсортированным по прецеденту (например, "+" будет идти перед "*"), элементов вида (assoc op ...), где каждый op — это токен, который действует как оператор; assoc — это его ассоциативность, которая может быть либо left, либо right, либо assoc, либо nonassoc. Все операторы в заданном элементе имеют одинаковый уровень прецедента и ассоциативность.

Функция: smie-bnf->prec2 bnf &rest resolvers

Эта функция позволяет вам указать грамматику с использованием нотации BNF. Она принимает описание грамматики bnf вместе с набором правил разрешения конфликтов resolvers и возвращает таблицу prec2.

bnf — это список определений нетерминалов вида (nonterm rhs1 rhs2 ...), где каждый rhs — это (непустой) список терминалов (также токенов) или нетерминалов.

Не все грамматики принимаются:

  • Нетерминал rhs не может быть пустым списком (пустой список никогда не нужен, поскольку SMIE позволяет всем нетерминалам соответствовать пустой строке).
  • Нетерминал rhs не может содержать 2 последовательных нетерминала: каждая пара нетерминалов должна быть разделена терминалом (также токеном). Это фундаментальное ограничение грамматик прецедента операторов.

Кроме того, могут возникать конфликты:

  • Возвращаемая таблица prec2 содержит ограничения между парами токенов, и для любой заданной пары может присутствовать только одно ограничение: T1 < T2, T1 = T2 или T1 > T2.
  • Токен может быть opener (что-то похожее на открывающую скобку), closer (как закрывающая скобка) или neither (ни то, ни другое (например, бинарный оператор или внутренний токен, такой как "else")).

Конфликты прецедента могут быть разрешены с помощью resolvers, который является списком таблиц precs (см. smie-precs->prec2): для каждого конфликта прецедента, если эти таблицы precs указывают на определенное ограничение, то конфликт разрешается с использованием этого ограничения, иначе сообщается о конфликте, и одно из конфликтующих ограничений выбирается произвольно, а остальные просто игнорируются.