EnglishРусский  

   ..

   alias.c

   alias.h

   bcodes.c

   bcodes.h

   body.c

   compile.c

   compile.h

   define.c

   define.h

   desc.c

   expr.c

   extern.c

   for.c

   foreach.c

   func.c

   func.h

   global.c

   global.h

   goto.c

   if.c

   ifdef.c

   ifdef.h

   import.c

   import.h

   include.c

   include.h

   jump.c

   lexem.c

   lexem.h

   macro.c

   macro.h

   operlist.txt

   out.c

   out.h

   subfunc.c

   switch.c

   type.c

   type.h

   vars.c

   while.c

   with.c

Реклама

Инсталлятор CreateInstall
Бесплатные и коммерческие инсталляторы

  1 /******************************************************************************
  2 *
  3 * Copyright (C) 2006, The Gentee Group. All rights reserved.
  4 * This file is part of the Gentee open source project - http://www.gentee.com.
  5 *
  6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
  7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
  8 * ACCEPTANCE OF THE AGREEMENT.
  9 *
 10 * ID: switch 08.02.07 0.0.A.
 11 *
 12 * Author: Alexander Krivonogov ( algen )
 13 *
 14 * Summary: The switch statement
 15 *
 16 ******************************************************************************/
 17 
 18 #include "func.h"
 19 #include "bcodes.h"
 20 
 21 /*-----------------------------------------------------------------------------
 22 *
 23 * ID: c_if 08.02.07 0.0.A.
 24 *
 25 * Summary: The switch processing
 26 *
 27 -----------------------------------------------------------------------------*/
 28 //Состояния для обработки switch
 29 #define SWITCH_STFIRST    0x01 //Начальное состояние
 30 #define SWITCH_STCASE     0x02 //Обработано условие очередного case
 31 #define SWITCH_STBODY     0x04 //Обработано тело case
 32 #define SWITCH_STDEFAULT  0x08 //Обработан default
 33 plexem STDCALL c_switch( plexem curlex )
 34 {
 35    uint      state;    //Текущее состояние функции SWITCH_*
 36 
 37    uint      jmpnext;// Ссылка переход на следующий case
 38    uint      jmpbody;// Cсылка переход на начало блока
 39    uint      jmpend; // Ссылка переход на конец
 40 
 41    pvmfunc   pfunc;    //Указатель на структуру операции ==
 42    uint      parsc[4]; //Параметры для получения кода операции ==
 43    uint      ltype;    //Тип левой части выражения
 44    uint      dwsize;   //Размер типа левой части выражения
 45 
 46    //Инициализация
 47    state = SWITCH_STFIRST;
 48    jmpnext = -1;
 49    jmpbody = -1;
 50    jmpend = -1;
 51 D( "Switch start\n" );
 52 
 53    //Значение выражения
 54    curlex = f_expr( curlex, EXPR_NONULL, <ype, &parsc[1] );
 55    parsc[0] = ltype;   
 56    dwsize = (( povmtype )PCMD( ltype ))->stsize; //Получаем размер типа левой части выражения
 57 
 58    //Главный блок switch
 59    curlex = lexem_next( curlex, LEXNEXT_SKIPLINE );
 60    if ( curlex->type != LEXEM_OPER ||
 61         curlex->oper.operid != OpLcrbrack )//Открывающая фигурная скобка
 62       msg( MLcurly | MSG_LEXERR, curlex );// Ошибка Ожадается открывающая фигурная скобка
 63    //Главный цикл
 64    while ( 1 )
 65    {
 66       if ( jmpnext != -1 )
 67       {
 68          //Корректировка последнего перехода
 69          j_correct( jmpnext, j_label( LABT_LABELVIRT, -1) );
 70          jmpnext = -1;
 71       }
 72       curlex = lexem_next( curlex, LEXNEXT_IGNLINE  );
 73       if ( !(state & SWITCH_STDEFAULT ) && curlex->type == LEXEM_KEYWORD )
 74       {
 75          switch ( curlex->key )
 76          {
 77             case KEY_CASE:
 78                D( "Case\n" );
 79                curlex = lexem_next( curlex, 0 );
 80                //Цикл проверок условий для текущего Case
 81                while ( 1 )
 82                {  //Удаление из стэка результата сравнения
 83                   if ( !( state & SWITCH_STFIRST ) &&
 84                         !( state & SWITCH_STCASE ))
 85                      out_adduint( CPop );
 86 
 87                   state = SWITCH_STCASE;
 88                   // Добавляем в стэк команду дублирования последнего значения
 89                   out_adduint( dwsize == 1 ? CDup : CDuplong );
 90 
 91                   //Обрабатываем условие
 92                   curlex = f_expr( curlex, EXPR_COMMA | EXPR_NONULL, &parsc[2], &parsc[3]);
 93 
 94                   //Получаем операцию равенства
 95                   pfunc = bc_funcname( curlex, "#==", 2, parsc );
 96                   out_adduint( pfunc->vmo.id );
 97                   if ( (( povmtype )PCMD( pfunc->ret->type ))->stsize == 2 )
 98                      out_adduint( CLoglongtrue );
 99                   
100                   if ( curlex->type == LEXEM_OPER && curlex->oper.operid == OpComma )
101                   {
102                      D( "Comma\n" );
103                      curlex = lexem_next( curlex, LEXNEXT_IGNLINE );                     
104                   }
105                   else
106                   {
107                      //Устанавливаем переход на следующий Case
108                      jmpnext = j_jump( CIfznocls, LABT_GTVIRT, -1 );
109                      break;
110                   }
111                   //Устанавливаем переход на тело текущего Case
112                   jmpbody = j_jump( CIfnznocls, LABT_GTVIRT, jmpbody );
113                }
114                state = SWITCH_STBODY;
115                //Корректировка меток на текущее тело
116                j_correct( jmpbody, j_label( LABT_LABELVIRT, -1) );
117                jmpbody = -1;
118                
119                //Цикл обработки дополнительных меток
120                curlex = lexem_next( curlex, LEXNEXT_SKIPLINE );
121                while ( curlex->type == LEXEM_KEYWORD && curlex->key == KEY_LABEL )
122                {
123                   curlex = lexem_next( curlex, 0 );
124                   curlex = c_label( curlex );
125                   curlex = lexem_next( curlex, LEXNEXT_SKIPLINE );
126                }               
127                //Обработка тела
128                curlex = f_body( curlex );
129                //Перход на конец
130                jmpend = j_jump( CGoto, LABT_GTVIRT, jmpend );
131                break;
132 
133             case KEY_DEFAULT:
134                //Корректировка последнего перехода
135                state = SWITCH_STDEFAULT;
136                //Цикл обработки дополнительных меток
137                while ( 1 )
138                {
139                   curlex = lexem_next( curlex, LEXNEXT_IGNLINE  );
140                   if ( curlex->type == LEXEM_KEYWORD && curlex->key == KEY_LABEL )
141                      curlex = c_label( curlex );
142                   else
143                      break;
144                }               
145                curlex = f_body( curlex );
146                break;
147             default:
148                msg( MNokeyword | MSG_LEXERR, curlex );// Ошибка Неправильное использование ключевого слова
149          }
150          continue;
151       }
152       else
153       {
154          if ( curlex->type == LEXEM_OPER && curlex->oper.operid == OpRcrbrack )
155          {
156             //Корректировка переходов на конец
157             j_correct( jmpend, j_label( LABT_LABELVIRT, -1) );
158             break;//Выйти из тела switch
159          }
160          msg( MRcurly | MSG_LEXERR, curlex );// Ошибка Ожадается закрывающая фигурная скобка
161       }
162    }
163 
164 D( "Switch stop\n" );
165    return curlex;
166 }
Редактировать