Чтение онлайн

на главную

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

В качестве примера рассмотрим реализацию следующей грамматики (листинг 4.10).

Листинг 4.10. Грамматика калькулятора с лексическим анализатором

<Expr> ::= <MathExpr> [<Comparison> <MathExpr>]

<Comparison> ::= '=' | '>' | '<' | '>=' | '<=' | '<>'

<MathExpr> ::= <Term> {<Operator1> <Term>}

<Operator1> ::= '+' | '-' | 'or' | 'xor'

<Term> ::= <Factor> {<Operator2> <Factor>}

<Operator2> ::= '*' | '/' | 'div' | 'mod' | 'and'

<Factor> ::= <UnaryOp> <Factor> | <Base> ['^' <Factor>]

<UnaryOp> ::= '+' | '-' | 'not'

<Base> ::= <Variable> | <Function> | <Number> | '(' <MathExpr> ')'

<Function> ::= <FuncName> '(' <MathExpr> ')'

<FuncName> ::= 'sin' | 'cos' | 'ln'

<Variable> ::= <Letter> {<Letter> | <Digit>}

<Letter> ::= 'A' | ... | 'Z' | 'a' | ... | 'z' | '_'

<Digit> ::= '0' | ... | '9'

<Number> ::= <Digit> {<Digit>} [<DecimalSeparator> <Digit> {<Digit>}]

 (('E' | 'e') ['+' | '-'] <Digit> {<Digit>)]

Примечание

Здесь

используется нетерминальный символ
<DecimalSeparator>
, который мы не определили. Он полагается равным точке или запятой в зависимости от системных настроек.

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

<DecimalSeparator>
) нетерминальных символов. Определение символа
<Number>
несколько изменено, но это касается только формы его представления — синтаксис числа остался без изменения. То, что раньше обозначалось как
<Expr>
, теперь называется
<MathExpr>
, а выражение
<Expr>
состоит из одного
<MathExpr>
, с которым, возможно, сравнивается другое
<MathExpr>
. Семантика
<Expr>
такова: если в выражении присутствует только обязательная часть, результатом будет число, которое получилось при вычислении
<MathExpr>
. Если же имеется необязательное сравнение с другим
<MathExpr>
, то результатом будет "
True
" или "
False
" в зависимости от результатов сравнения.

В новой грамматике также расширен набор операторов. Операторы

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

Лексический анализатор должен выделять из строки следующие лексемы:

1. Все знаки операций, которые используются в определении символов

<Comparison>
,
<Operator1>
,
<Operator2>
,
<UnaryOp>
, а также символ "
^
".

2. Открывающую и закрывающую скобки.

3. Имена функций.

4. Идентификаторы (т.е. переменные).

5. Числовые константы.

Напомним, что лексический анализатор не должен определять допустимость появления

лексемы в данном месте строки. Он просто сканирует строку, выделяет из нее последовательности символов, распознаваемые как отдельные лексемы, и сохраняет информацию о них в специальном списке, которым потом пользуется синтаксический анализатор. Так, например, встретив цифру, лексический анализатор выделяет числовую константу. Встретив букву, он выделяет последовательность буквенно-цифровых символов. Затем сравнивает эту последовательность с одним из зарезервированных слов (
and
,
div
и т.п.) и распознает лексему соответственно как идентификатор (переменную) или как зарезервированное слово. При этом выяснение, объявлена ли такая переменная, также не входит в обязанности лексического анализатора — это потом сделает синтаксический анализатор.

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

sin
,
cos
и
ln
в отличие от предыдущего примера, нельзя. Это само по себе не упрощает и не усложняет задачу, а сделано только в качестве демонстрации возможной альтернативы (просто если именами служат зарезервированные слова, то их распознает лексический анализатор, а если идентификаторы, то синтаксический).

Отдельные лексемы выделяются по следующему алгоритму: сначала, начиная с текущей позиции, пропускаются все разделители — пробелы и символы перевода строки. Затем по первому символу определяется лексема — знак, слово (которое потом может оказаться зарезервированным словом или идентификатором) или число. Дальше лексический анализатор выбирает из строки все символы до тех пор, пока они удовлетворяют правилам записи соответствующей лексемы. Следующая лексема ищется с позиции, идущей непосредственно за предыдущей лексемой.

В зависимости от типа лексем разделители между ними могут быть обязательными или необязательными. Например, в выражении "2+3" разделители между лексемами "2", "+" и "5" не нужны, потому что они могут быть отделены друг от друга и без этого. А в выражении

6 div 3
разделитель между "div" и "3" необходим, потому что в противном случае эти лексемы будут восприняты как идентификатор div3. А вот разделитель между "6" и "div" не обязателен, т.к.
6div
не является допустимым идентификатором, и анализатор сможет отделить эти лексемы друг от друга и без разделителя. Вообще, если подстрока, получающаяся в результате слияния двух лексем, может быть целиком интерпретирована как какая-либо другая лексема, разделитель между ними необходим, в противном случае — необязателен. Разделитель внутри отдельной лексемы не допускается (т.е. подстрока "a 1" будет интерпретироваться как последовательность лексем "а" и "1", а не как лексема "а1").

Чтобы продемонстрировать возможности лексического анализатора, добавим поддержку комментариев. Комментарий — это последовательность символов, начинающаяся с "{" и заканчивающаяся "}", которая может содержать внутри себя любые символы, кроме "}". Комментарий считается разделителем, он допустим в любом месте, где возможно появление других разделителей, т.е. в начале и в конце строки и между лексемами.

Пример калькулятора с лексическим анализатором также находится на компакт-диске и называется LexicalSample.

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

Листинг 4.11. Тип
TLexeme
для хранения информации об одной лексеме

TLexemeType = (

 ltEqual, ltLess, ltGreater, ltLessOrEqual,

 ltGreaterOrEqual, ltNotEqual, ltPlus, ltMinus,

 ltOr, ltXor, ltAsterisk, ltSlash, ltDiv, ltMod,

Поделиться:
Популярные книги

На границе тучи ходят хмуро...

Кулаков Алексей Иванович
1. Александр Агренев
Фантастика:
альтернативная история
9.28
рейтинг книги
На границе тучи ходят хмуро...

Кодекс Охотника. Книга III

Винокуров Юрий
3. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Кодекс Охотника. Книга III

Последний попаданец 11. Финал. Часть 1

Зубов Константин
11. Последний попаданец
Фантастика:
фэнтези
юмористическое фэнтези
рпг
5.00
рейтинг книги
Последний попаданец 11. Финал. Часть 1

Книга пяти колец

Зайцев Константин
1. Книга пяти колец
Фантастика:
фэнтези
6.00
рейтинг книги
Книга пяти колец

Поступь Империи

Ланцов Михаил Алексеевич
7. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Поступь Империи

Купидон с топором

Юнина Наталья
Любовные романы:
современные любовные романы
7.67
рейтинг книги
Купидон с топором

Наследник в Зеркальной Маске

Тарс Элиан
8. Десять Принцев Российской Империи
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник в Зеркальной Маске

Совок 5

Агарев Вадим
5. Совок
Фантастика:
детективная фантастика
попаданцы
альтернативная история
6.20
рейтинг книги
Совок 5

Аномальный наследник. Том 1 и Том 2

Тарс Элиан
1. Аномальный наследник
Фантастика:
боевая фантастика
альтернативная история
8.50
рейтинг книги
Аномальный наследник. Том 1 и Том 2

Теневой путь. Шаг в тень

Мазуров Дмитрий
1. Теневой путь
Фантастика:
фэнтези
6.71
рейтинг книги
Теневой путь. Шаг в тень

Попаданка в академии драконов 2

Свадьбина Любовь
2. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
6.95
рейтинг книги
Попаданка в академии драконов 2

Гром над Империей. Часть 2

Машуков Тимур
6. Гром над миром
Фантастика:
фэнтези
попаданцы
5.25
рейтинг книги
Гром над Империей. Часть 2

Ритуал для призыва профессора

Лунёва Мария
Любовные романы:
любовно-фантастические романы
7.00
рейтинг книги
Ритуал для призыва профессора

Измена. Осколки чувств

Верди Алиса
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Осколки чувств