Читаем Программирование полностью

Итак, как же выразить идею о паре (вид, значение) в программе? Для этого определим тип Token, представляющий лексемы. Почему? Вспомните, почему мы вообще используем типы: они хранят данные, которые нам нужны, и предоставляют возможность выполнять полезные операции над этими данными. Например, тип int позволяет хранить целые числа и выполнять операции сложения, вычитания, умножения и вычисления остатка, в то время как тип string позволяет хранить последовательности символов и выполнять конкатенацию и доступ к символу по индексу. В языке С++ и его стандартной библиотеке определено много типов, например char, int, double, string, vector и ostream, но не тип Token. На самом деле существует огромное количество типов — тысячи и сотни тысяч, — которые мы хотели бы иметь, но которых нет в языке и в стандартной библиотеке.

Среди наших любимых типов, которых нет в библиотеке, — классы Matrix (см. главу 24), Date (см. главу 9) и целые числа с бесконечной точностью (поищите в веб класс Bignum). Если вы еще раз поразмыслите над этим, то поймете, что язык не может поддерживать десятки тысяч типов: кто их определит, кто их реализует, как их найти и какое толстое руководство по использованию языка при этом получится? Как и большинство современных языков программирования, язык С++ решает эту проблему, позволяя программисту при необходимости определять свои собственные типы (типы, определенные пользователем).

<p id="AutBody_Root094"><strong>6.3.3. Реализация лексем</strong></p>

Как должна выглядеть лексема в нашей программе? Иначе говоря, как должен выглядеть тип Token? Класс Token должен предусматривать выполнение операторов, например + и , а также представлять числа, такие как 42 и 3.14. В самой простой реализации нужно придумать, как задать вид лексемы и как хранить числа.

Существует много способов реализации этой идеи в программе на языке С++. Вот ее простейший вариант:

class Token { // очень простой тип, определенный пользователем

public:

  char kind;

  double value;

};

Класс Token — это тип (такой же, как int или char), поэтому его можно использовать для определения переменных и хранения значений. Он состоит из двух частей (членов): kind и value. Ключевое слово class означает “тип, определенный пользователем”; это значит, что он содержит члены (хотя в принципе может их и не содержать). Первый член, kind, имеет тип char и представляет собой символ. С его помощью удобно хранить символы '+' и '*', чтобы представить операции * и +. Рассмотрим пример использования этого типа.

Token t;       // t — объект класса Token

t.kind = '+';  // t представляет операцию +

Token t2;      // t2 — другой объект класса Token

t2.kind = '8'; // цифра 8 означает, что "вид" является числом

t2.value = 3.14;

Для доступа к члену класса используется обозначение имя_объекта.имя_члена. Выражение t.kind читается как “член kind объекта t”, а выражение t2.value — как “член value объекта t2”. Объекты класса Token можно копировать так же, как и переменные типа int.

Token tt = t;    // копирование при инициализации

if (tt.kind != t.kind) error("невозможно!");

t = t2;          // присваивание

cout << t.value; // вывод числа 3.14

Имея класс Token, можно выразить выражение (1.5+4)*11 с помощью семи лексем.

Обратите внимание на то, что для простых лексем значение не требуется, поэтому мы не используем член value. Нам нужен символ для обозначения чисел. Мы выбрали символ '8' просто потому, что он явно не оператор и не знак пунктуации. Использование символа '8' для обозначения чисел немного загадочно, но это лишь на первых порах.

Класс Token представляет пример типа, определенного пользователем. Тип, определенный пользователем, может иметь функции-члены (операции), а также данные члены. Существует много причин для определения функций-членов. В данном примере мы описали две функции-члена для того, чтобы инициализация объекта класса Token стала проще.

class Token {

public:

  char kind;     // вид лексемы

  double value;  // для чисел: значение

  Token(char ch) // создает объект класса Token

                 // из переменной типа char

    :kind(ch), value(0) { }

  Token(char ch, double val)   // создает объект класса Token

    :kind(ch), value(val) { }  // из переменных типа

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже