[ Содержание ] [ Предыдущая ] [ Следующая ]

Глава 9. Рекомендации по подготовке спецификаций

    Эта глава содержит разнообразные подсказки по подготовке эффективных, легкоизменяемых и ясных спецификаций. Каждая секция более или менее независима.

Входной стиль

    Сложно предоставить реальные действия правилам, сохраняя читаемый файл спецификаций. Hижеследующий рекомендации по стилю во многом следуют Брайану Кернигану.

  1. Используйте заглавные буквы для имен токенов, строчные для нетерминальных имен. Это правило называется "знать кого винить в случае проблем".
  2. Помещайте грамматические правила и действия на различных строках. Это позволяет изменять одно без необходимости изменять другое.
  3. Помещайте все правила с одной и той же левой частью вместе. Пишите левую часть только один раз и разделяйте все последующие правила вертикальной чертой.
  4. Помещайте точку с запятой только после последнего правила с данной левой частью и на отдельной строке. Это позволяет легко добавлять новые правила.
  5. Выравнивайте тела правил двумя табуляциями, а тела действий - тремя.

    Пример в Приложении A написан в этом стиле, так же как и примеры в тексте статьи (где позволяет место). Пользователь должен сам решить эти стилистические вопросы; однако, центральной проблемой является читабельность правил невзирая на трясину кода действий.

Левая рекурсия

    Алгоритм, используемый парсером Yacc-а поощряет к так называемым лево-рекурсивным грамматическим правилам: правила формы

name : name rest_of_rule ;

    Эти правила часто появляются при написании спецификаций последовательностей и списков:

list : item | list ',' item ;

    и

seq : item | seq item ;

    В каждом из этих случаев первое правило может быть понижено только для первого предмета, а второе - только для второго и всех последующих.

    С право-рекурсивными правилами, такими как

seq : item | item seq ;

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

    Стоит обсудить, имеет ли какой-нибудь смысл последовательность из нуля элементов, и если имеет, обсудим написание спецификации последовательности с пустым правилом:

seq : /* empty */ | seq item ;

    Повторяем, первое правило всегда будет понижаться ровно один раз, перед тем, как прочитан первый предмет, а затем понижается первое правило один раз для каждого предмета. Разрешение пустыъ последовательностей часто ведет к увеличивающейся общности. Однако могут возникнуть конфликты, если Yacc-y зададут вопрос, какая пустая последовательность была увидена, когда он видел недостаточно, чтобы это знать.

Лексический "принудительный ассортимент"

    Hекоторые лексические решения зависят от контекста. Hапример, лексический анализатор может захотеть удалить пустые пространства, но только не внутри строк в кавычках. Или имена могут записываться в таблицу символов в объявлениях, но не в выражениях.

    Одним из способов обработки такой ситуации является создание глобального флага, опрашиваемого лексическим анализатором и устанавливаемый действиями. Hапример, предположим, что программа состоит из нуля или более объявлений, за которыми следуют ноль или более операторов. Рассмотрим:

%{ int dflag; %} ... other declarations ... %% prog : decls stats ; decls: /* empty */ { dflag = 1; } | decls declaration ; stats: /* empty */ { dflag = 0; } | stats statement ; ... other rules ...

    Флаг dflag при чтении операторов стал 0, а при чтении объявлений - 1, за исключением первого токена в первом операторе. Этот токен должен быть увиден парсером перед тем, как он может сказать, что секция объявлений закончилась и начались операторы. Во многих случаях, это единственное исключение не затрагивает лексическое сканирование.

    Этот прием "черного хода" может быть использован во вред. Тем не менее, он преставляет собой способ, которым можно сделать вещи, которые сложно, если не совсем невозможно сделать по другому.

Зарезервированные слова

    Hекоторые языки программирования позволяют пользователю использовать такие слова, как "if", которые обычно резервируются, как метки или имена переменных, при условии того, что такое использование не конфликтует с легальным использованием этих имен в языке программирования. Это крайне сложно сделать в рамках Yacc-а; сложно передать лексическому анализатору информацию о том, что "это появление 'if' есть ключевое слово, а это - переменная". Пользователь может совершить это, используя механизм, описанный в последней подсекции, но это трудно.

    Hекоторое количество способов для облегчения этого обсуждаются. До тех пор, лучше, чтобы ключевые слова были зарезервированны; то есть запрещены для использования в качестве имен переменных. В любом случае, есть сильные стилистические причины, чтобы предпочесть именно это.

[ Содержание ] [ Предыдущая ] [ Следующая ]



c 1998-2000 SoloTony (Antonio Solo) solotony@mail.ru