Как маркировать отступы в Coco/R (Python, Boo как отступ)

Это хорошо известный способ, как реализовать в Coco/R токенизацию отступов, как в Python / Boo?

Coco/R игнорирует пробелы, но мне нужно каким-то образом генерировать токены beginBlock/endBlock, основываясь на отступе следующей строки.

Прямо сейчас я использую препроцессор, который вставляет '{', '}' и ';' во входном потоке, сравнивая отступы между строками. В грамматике Coco/R я использую кривые скобки в качестве токенов beginBlock/endBlock. Это хорошо работает, если входной поток не имеет комментариев (которые также могут быть вложенными). Как только поступают неупорядоченные комментарии, логика сравнения намерений не работает.

Реализация препроцессора, который отслеживает комментарии, выглядит для меня как чрезмерная разработка.

Таким образом, вопрос в том, возможно ли вообще разбирать грамматику на основе отступа с Coco/R? Или я должен попробовать что-то еще?

2 ответа

Решение

Нашел идеальный способ сделать это.

  • Оберните GetNextToken методом, который сравнивает позиции потока следующего токена с последним.

  • если position.Y изменяется, но position.X увеличивает N вкладок, вводит N виртуальных токенов INDENT.

  • если position.Y изменилось, но position.X уменьшило N вкладок, введите N виртуальных DENDENT токенов.

  • если position.Y изменилось, а position.X нет, введите виртуальный токен SEPARATOR.

  • если position.Y не изменилось, верните оригинал следующего токена.

  • если предыдущий токен был мягким разрывом (в python \), игнорируйте логику выше.

Прежде всего, Coco/R по умолчанию игнорирует только пробелы (пробелы). Вкладки не игнорируются:

2.3.5 Пустое пространство
Такие символы, как пробелы, табуляторы или символы конца строки, обычно рассматриваются как пробелы, которые должны игнорироваться сканером. Пробелы по умолчанию игнорируются. Если нужно игнорировать и другие символы, пользователь должен указать их следующим образом:

WhiteSpaceDecl = "IGNORE" Set.

Пример IGNORE '\t' + '\r' + '\n'

Я не проверял это, но я думаю, что вы должны переписать поведение сканера по умолчанию:

Token NextToken() {
    while (ch == ' ' ||
        false
    ) NextCh();

Самый простой способ сделать это - сначала изменить сгенерированный код, пока он не заработает, а затем внести те же изменения в файлы фреймов (Scanner.frame а также Parser.frame), поэтому вы не потеряете изменения после того, как обновите код.

Другие вопросы по тегам