|
|
|
| |
Главная С++ (часть 3) Трансляция оператора 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, достигнут конец выражения и можно добавить последнюю забывающуюся скобку.
|
|
|
|
|