Маркирование чисел для синтаксического анализатора

Я пишу свой первый синтаксический анализатор и имею несколько вопросов conerning токенизатор.

В основном мой токенизатор выставляет a nextToken() функция, которая, как предполагается, возвращает следующий маркер. Эти маркеры отличает тип маркера. Я думаю, что имело бы смысл иметь следующие типы маркера:

  • СИМВОЛ (такой как <, :=, ( и т.п.
  • ПРОБЕЛ (вкладка, новые строки, располагает с интервалами...),
  • КОММЕНТАРИЙ (комментарий между/*... */или после//через новую строку)
  • ЧИСЛО
  • IDENT (такой как название функции или переменной)
  • СТРОКА (Что-то включенное между "....")

Теперь, Вы думаете, что это имеет смысл?

Кроме того, я борюсь с NUMBER тип маркера. Вы думаете, что имеет больше смысла далее разделять его на a NUMBER и a FLOAT тип маркера? Без a FLOAT тип маркера, я получил бы NUMBER (например, 402), a SYMBOL (.) сопровождаемый другим NUMBER (например, 203), если я собирался проанализировать плавание.

Наконец, что Вы думаете, имеет больше смысла для токенизатора возвращаться, когда он встречается с a -909? Если это возвращается SYMBOL - во-первых, сопровождаемый NUMBER 909 или если это возвращает a NUMBER -909 сразу же?

5
задан René Nyffenegger 11 June 2010 в 13:14
поделиться

5 ответов

Это зависит от вашего целевого языка.

Смысл лексера - возвращать токены, которые упрощают написание синтаксического анализатора для вашего языка. Предположим, ваш лексер возвращает ЧИСЛО , когда видит символ, соответствующий «[0-9] +». Если он видит нецелое число, например «3,1415926», он вернет ЧИСЛО . НОМЕР . Хотя вы можете справиться с этим в своем синтаксическом анализаторе, если ваш лексер выполняет соответствующую работу по пропуску пробелов и комментариев (поскольку они не имеют отношения к вашему синтаксическому анализатору), вы можете в конечном итоге неправильно проанализировать такие вещи, как "123 / * comment " /. \ n / другой комментарий * / 456 "как числа с плавающей запятой.

Что касается лексирования "- [0-9] +" как НОМЕР против МИНУС НОМЕР снова, это зависит от вашего целевого языка, но я обычно иду с МИНУС НОМЕР , иначе вы бы лексировали «A = 1-2-3-4» как СИМВОЛ = НОМЕР НОМЕР НОМЕР НОМЕР вместо СИМВОЛ = НОМЕР МИНУС НОМЕР МИНУС НОМЕР МИНУС НОМЕР .

Пока мы обсуждаем эту тему, я настоятельно рекомендую книгу Шаблоны реализации языка , написанную Терренсом Парром, автором ANTLR .

4
ответ дан 18 December 2019 в 14:42
поделиться

Исходя из моего опыта работы с реальными лексерами:

  1. Не забудьте проверить, действительно ли вам нужны маркеры комментариев / пробелов. Компиляторам они обычно не нужны, в отличие от IDE (например, для окрашивания комментариев в зеленый цвет).
  2. Обычно нет единого токена «оператора»; вместо этого есть токен для каждого отдельного оператора. Итак, есть токен PLUS, токен AMPERSAND, токен LESSER_THAN и т. Д. Это означает, что вы заботитесь только о лексеме (фактическом сопоставлении текста), когда токен является идентификатором или каким-то литералом.
  3. Избегайте разделения литералов. Если "hello world" является строковым литералом, проанализируйте его как одиночный токен. Если -3.058e18 является литералом с плавающей запятой, проанализируйте его также как отдельный токен. Лексеры обычно полагаются на регулярные выражения, которые достаточно выразительны для всего этого и многого другого. Конечно, если литералы достаточно сложные, у вас есть для их разделения (например, блочный литерал в Smalltalk).
3
ответ дан 18 December 2019 в 14:42
поделиться

Думаю, что ответ на ваш вопрос строго привязан к семантике ЧИСЛА. Каким должен быть НОМЕР? Всегда положительное целое число, число с плавающей запятой ...

Я хотел бы предложить вам поискать инструменты flex и yacc (также известные как lex & bison) операционных систем U ** x: это мощные парсеры и генераторы сканеров. которые берут грамматику и выводят компилируемую и легко используемую программу.

2
ответ дан 18 December 2019 в 14:42
поделиться

Это зависит от того, как вы принимаете токены, если вы делаете это посимвольно, то это может быть немного сложно, но если вы делаете это слово за словом, т.е.

int a = a + 2.0

то токены будут (отбрасывая пробельные символы)

int
a
=
a
+
2.0

Таким образом, вы не столкнетесь с ситуацией, когда вы интерпретируете . как лексему, а воспринимаете всю строку целиком - именно здесь вы можете определить, является ли она ПЛОСКОСТЬЮ, ЧИСЛОМ или чем угодно.

0
ответ дан 18 December 2019 в 14:42
поделиться

Лучше всего сделать так, чтобы типы ваших токенов были точно такими же, как терминальные символы вашей грамматики.

Не зная языка / грамматики, я полагаю, вам было бы лучше, если бы вы имели типы токенов для "LESS_THAN", "LESS_THAN_OR_EQUAL", а также "FLOAT", "DOUBLE", "INTEGER" и т. Д.

4
ответ дан 18 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: