Как это обозначить?

#lexical-analysis

#лексический анализ

Вопрос:

Я пытаюсь передать код токенизатора. Я продолжаю читать символы, которые могут быть частью токена. Например, целое число может содержать только цифры. Итак, в приведенном ниже тексте я продолжаю читать символы, пока не найду нецифровый символ. Итак, я получаю 123 в качестве токена. Затем я получаю (в качестве токена, а затем abc в качестве идентификатора. Это нормально, поскольку ( является разделителем.

 123(abc
 

Однако в приведенном ниже тексте я получаю 123 как целое число, а затем abc как идентификатор. Но на самом деле это недопустимо, поскольку между ними нет разделителя.

 123abc(
 

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

Или токенизатор должен просто возвращать 123 как целое число и abc в качестве идентификатора и позволять анализатору обнаруживать ошибки?

Ответ №1:

Обычно токенизатор (или лексер) не выполняет проверку допустимого синтаксиса.

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

Ответ №2:

Это своего рода серая область, но большинство лексеров с ручным кодированием просто выполняют маркировку и позволяют анализатору решать, имеет ли смысл поток токенов.

Комментарии:

1. В таком случае вы можете выдать лексическую ошибку, поскольку 123abc это не токен.

Ответ №3:

Если «123abc» является недопустимым токеном, то вы должны обработать его, как только обнаружите, поскольку это напрямую связано с тем, как определяются токены, а не с тем, как они взаимодействуют друг с другом (что было бы задачей лексера). Это скорее орфографическая ошибка, чем ошибка, связанная с грамматикой.

Для этого есть несколько способов:

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

    Пример: соответствующий синтаксический анализатор XML может использовать это для фатальных ошибок, если нет необходимости обрабатывать искаженную разметку, просто выплюните основную ошибку и завершите работу.

  • В качестве альтернативы вы можете вставить токен «ошибка» с соответствующими метаданными о характере ошибки и перейти к следующему допустимому токену.

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

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

Ответ №4:

Вы можете подумать о создании своего токенизатора или лексера. Такие инструменты, как Flex или ANTLR, должны помочь. И вы также можете сгенерировать свой анализатор с помощью ANTLR или Bison

Если вы настаиваете на ручном кодировании своего лексера (и вашего синтаксического анализатора), на практике чрезвычайно полезно заглянуть вперед. Например, вы можете читать свои входные данные построчно и помечать внутри текущей строки (с возможностью просмотра следующих нескольких символов).