Главная arrow С++ (часть 3) arrow Трансляция оператора typeof

Трансляция оператора typeof

Оператор typeof предлагает альтернативную синтаксическую конструкцию для сравнения двух типов данных. Ее обычная форма записи приведена далее, typeof opl same as op2
Обозначения opl и op2 можно заменить идентификаторами типов (такими как int или Myciass) или именами объектов. Таким образом, оператор typeof можно использовать для сравнения типов двух объектов, типа объекта и известного типа данных или двух типов данных. Результат выполнения оператора равен true, если типы одинаковы, и false в противном случае. Оператор typeof преобразуется в выражение на языке С++, в котором сравниваются результаты применения оператора typeid к каждому операнду.
Трансляция оператора typeof выполняется функцией typeof о, приведенной далее.
// Транслирует оператор typeof. void typeof()  {
string token;
string temp;
fout « "typeid(";
skipspaces();
gettoken(token);
do {
temp = token;
if(Igettoken(token))
throw SyntaxExc("Unexpected EOF encountered.");
if(token != "same")  fout « temp; } while(token != "same");
skipspaces () ; gettoken(token);
if (token != "as") throw SyntaxExc("as expected."); fout « ") == typeid("; skipspaces () ; do {
if(!gettoken(token))
throw SyntaxExc("Unexpected EOF encountered.");
fout « token; ) while(token !=")"); fout « ")  " ;
}
Следить за действиями функции typeof () очень легко. Она считывает первый операнд и записывает в выходной файл оператор typeid, примененный к этому операнду. Далее функция читает и отбрасывает ключевые слова same и as. Затем считывается второй операнд и записывается оператор typeid, примененный к этому операнду. Таким образом, оператор typeof (): if (typeof obj same as Myclass) cout « "obj is a MyClass object.\n";
Транслируется в следующий код на языке С++: if (typeid (obj) == typeid (Myclass)) cout « -obj is a MyClass object.\n";
Трансляция цикла repeat/until
Как уже упоминалось ранее, транслятор обрабатывает цикл repeat/until Равным образом для иллюстрации, несмотря на то, что проще использовать Макрос, чем преобразовывать эту конструкцию. Тем не менее, имея трансля-
способный преобразовать этот тип цикла, мы избавлены от необходимости описывать макросы repeat и until во всех программах, использую-
их. Кроме того, предложенная трансляция служит моделью, которую м°Жно адаптировать для других типов цикла.
Ключевое  слово  repeat  транслируется  приведенной  далее  функцией repeat (), которая просто заменяет его ключевым словом do: // Транслирует repeat, void repeat() { fout « и do" ;
}
Ключевое слово until обрабатывается функцией until о, код которой приведен далее // Транслирует until, void until()  {
string token;
int parencount = 1;
fout « "while"; skipspaces();
// Читает и запоминает "(" gettoken(token); if(token != "(")
throw SyntaxExc("( expected in typeof ."); fout « "  (" ;
// Начинает цикл while, заменяя на противоположное //и заключая в скобки условное выражение, fout « "!(";
// Теперь читает выражение, do {
i f(!gettoken(token))
throw SyntaxExc("Unexpected EOF encountered.");
if(token == "(") parencount++; i f(token == ")") parencount—;
fout « token; } while(parencount > 0); fout « ")";
}
функция until о подставляет ключевое слово while вместо until и меняет условие выполнения на противоположное (напоминаю, цикл repeat/until выполняется до тех пор, пока условие не станет равно true, а цикл do/whiie — пока условие не будет равно false).
Хотя концептуально это выглядит просто, разработка кода, меняющего условие на противоположное, требует усилий. Причина состоит в том, что транслятор не может просто добавить операцию ! в начало выражения. Он должен сначала заключить в скобки выражение, перед которым следует поставить !. Для иллюстрации рассмотрим следующий цикл repeat/until:
int i=0; repeat {
cout « i « " " ;
i++;
} until (i==10) ;
Он транслируется в приведенный далее цикл do/while: int   i=0;
do {
cout «    i <<      "  " ; i++;
} while(!(i==10)) ;
Скобки в условном выражении для while гарантируют, что цикл будет выполняться до тех пор, пока переменная i не равна ю. Если же скобки удалить, как показано далее: } while(!i==10);
Цикл будет продолжаться пока выражение ! i равно ю, а это совсем другое Условие!
Для заключения в скобки выражения для until транслятор должен добавить врывающуюся скобку в начало выражения и закрывающуюся — в конец. Но как транслятор определит конец условного выражения? Ответ — подсчетом пар скобок. Напоминаю, что выражение Для until заключено в скобки. Число встретившихся скобок хранится в переменной parencount, начальное значение которой равно I (что соответствует открывающейся скобке выражения для until). Во время копирования условного выражения транслятор Увеличивает на единицу значение переменной parencount каждый раз, когда ВстРетилась открывающаяся скобка, и уменьшает его на 1 при обнаружении врывающейся скобки. Таким образом, когда переменная parencount ста-Нет равна 0, достигнут конец выражения и можно добавить последнюю забывающуюся скобку.