Трансляция оператора cases |
Как уже объяснялось ранее, оператор cases представляет собой односекци-онную альтернативу описанию серии стопочных case-операторов. Он транслируется функцией cases (), приведенной далее. // Транслирует оператор cases, void cases О { string token; int start, end; skipspaces(); // Получает начальное значение* gettoken(token); if(isdigit(token[0])) { // получена константа int * start = atoi(token.c_str()); } else if(token[0] == '\ ' ') { // получена константа char gettoken(token); start = (int) token[0]; // Отбрасывает закрывающий • (апостроф) gettoken(token); if (token [0] != 'V ') throw SyntaxExcC" expected in cases."); ) else throw SyntaxExc("Constant expected in cases."); skipspaces(); // Читает и отбрасывет "to", gettoken(token); if(token != "to") throw SyntaxExc("to expected in cases."); skipspaces(); // Получает конечное значение. gettoken(token); if(isdigit(token[0])) { // Получена константа int end = atoi(token.c_str()); } else if (token[0] == •V) { // Получена константа char gettoken(token); end = (int) token[0]; // Отбрасывает закрывающий ' gettoken(token); if(token[0] != *V ' ) throw SyntaxExc("' expected in cases .") ; } else throw SyntaxExc("Constant expected in cases.") skipspaces(); // Читает и отбрасывает ":" gettoken(token); if(token != ":") throw SyntaxExc(": expected in cases.") ; // Генерирует стопочные case-операторы, fout « "case " « start « ":\n"; for(int i = start+1 ; i <= end; i++) { fout « indent « "case " « i « ":"; if(i != end) fout « endl; } } Хотя функция содержит большой объем кода, она описывает действительно простой вариант трансляции. Напомню, что оператор cases позволяет вам задать диапазон значений, удовлетворяющих условному выражению оператора switch. Транслятор просто преобразует этот диапазон в набор стопочных case-операторов. Например, следующий оператор switch: switch (val) { cases 0 to 3: cout « "val is 0, 1, 2, or 3\n"; break; case 4: cout « "val is 4\n"; } транслируется в приведенный далее эквивалентный код на языке С++, switch (val) { case 0: case 1: case 2: case 3 : cout « "val is 0, 1, 2, or 3\n" break; case 4 : cout « "val is 4\n"; } Как видите, создаются отдельные case-операторы для каждого значения из диапазона, заданного в операторе cases. ^Ункция cases о действует следующим образом. Сначала считывается на-''альное значение диапазона. Оно может быть целым или символьной кон-^Нтой. Если это целое число, то оно начинается с цифры. Если же это символьная константа, то она начинается с апострофа. В любом случае полученное значение запоминается в целочисленной переменной start. Далее читается лексема to и отбрасывается. Потом считывается конечное значение диапазона. Оно также может быть целым числом или символьной константой. Считанное значение запоминается в целочисленной переменной end. В конце формируется серия case-операторов, по одному для каждого значения из диапазона.
|