Previous Entry Share Next Entry
MSL FL (SP) - Компилятор своими руками. Шаг 6. Покончить с общей логикой
mikelsv
"Проект качать отсюда: anon:anon@svn://svn.loglist.org/usr/svn/opensource/msl-fl/ и anon:anon@svn://svn.loglist.org/usr/svn/opensource/msvlib . Исходный код будет тут: http://pastebin.com/QG3Kn9gr . Версия: #define USE_MSLFL_VER 6 "


У нас похоже сдох ЖЖ и я уже не помню, что обещал сделать в следующей серии.  For,  если не ошибаюсь. С него и продолжим. Реализуем выполнение вот этого нехитрого кода <? print('Hello World!!!'); for($i=55; $i; $i--){ print('1'); } ?>

Не стану переписывать if() и while(), они и так хорошо работают. Лучше вынесу обработку параметров в отдельную функцию DoCodeFunctionArgs();  И перед вызовом этой функции добавляем  обработчик for if(name=="for"){ DoCodeFunctionFor(line, to); }

Пишем обработчик аргументов функции, проверяем, что их 3. Не забыв отключить внесение изменений  do_opt_active=0; Теперь анализируем код цикла.
Дальше выполняем код  первого параметра. И в цикле крутим выполнение второго параметра с проверкой на false, выполняем код цикла, выполняем третий параметр.
Не кажется ли вам, что у нас слишком много анализаторов кода, в if(), в while(), третий раз писать для for() совсем не улыбается. Но все-таки похоже они разные, оставим пока так.
Код готов:
       int DoCodeFunctionFor(unsigned char *&line, unsigned char *to){
          // save values
          int old_active=do_opt_active; do_opt_active=0;
          // for args
          VString a[4]; int as=0;

          while(!do_opt_stopit && as<4){
                 msl_value val;
                 a[as].data=line;
                 DoCode(line, to, val, ';', ')');
                 a[as].sz=line-a[as].data; as++;

                 if(line>=to){ SetError("not found ')'. EOF"); return 0; }
                 if(*line==')') break;
                    line++;
          }
          line++;

             if(as!=3){
                 SetError("for(args!=3)."); return 0;
             }

          // Do {}
             msl_value val; unsigned char *lline, *elline, *tline, *eline; unsigned char endcode;

             lline=line;
             if(*(line)=='{'){ endcode='}'; line++; } else endcode=';';
          DoCodeMulti(line, to, val, endcode); line++;
          elline=line;

          // load old value
          do_opt_active=old_active;

          // Go or Nooo...
          if(old_active){
                 // do for(1)
                 tline=a[0].data; eline=a[0].endu()+1;
                 DoCode(tline, eline, val, ';');

                 while(1){
                        // do for(2), test
                        tline=a[1].data; eline=a[1].endu()+1;
                        DoCode(tline, eline, val, ';');
                        if(!val.val || val.val=="0") break;
                
                        // do {}
                        tline=lline; eline=elline;
                        if(*(tline)=='{'){ endcode='}'; tline++; } else endcode=';';                 
                        DoCodeMulti(tline, eline, val, endcode);

                        // cbr
                        if(do_opt_cbr){
                               if(do_opt_cbr==MSLCBR_CONT){ do_opt_cbr=MSLCBR_NULL; }
                               if(do_opt_cbr==MSLCBR_BREAK){ do_opt_cbr=MSLCBR_NULL; break; }
                               if(do_opt_cbr==MSLCBR_RET){ break; }
                        }

                        // set value
                        do_opt_active=old_active;

                        // do for(3)
                        tline=a[2].data; eline=a[2].endu()+1;
                        DoCode(tline, eline, val, ')');                      
                 }
          }

          // load old value
          do_opt_active=old_active; do_opt_ifw=0;
             return 1;
    }


Поехали отлаживаться.

Вывод:  Hello World!!!1111111111111111111111111111111111111111111111111111111

Ок. Done.

И чтобы два раза не вставать напишем continue, break и return ; Для этого нам понадобится одна переменная в msl,  int do_opt_cbr; по первым буквам этих слов.
Занчаения:
#define MSLCBR_NULL 0
#define MSLCBR_CONT 1
#define MSLCBR_BREAK 2
#define MSLCBR_RET  3

Еще, помнится в прошлых версиях msl была IBREAK, писалась как ibreak; и выходила только из if.

В месте, где мы ругаемся на отсутствие открывающей скобки у функции:
                                        if(*line==';'){
                                            if(name=="continue"){ do_opt_cbr=MSLCBR_CONT; do_opt_active=0; return ; }
                                            if(name=="break"){ do_opt_cbr=MSLCBR_BREAK; do_opt_active=0;  return ; }
                                            if(name=="return"){ do_opt_cbr=MSLCBR_RET; do_opt_active=0;  return ; }
                                        }
Ставим флаги.  Очевидно, упускаем вариант, где return; может содержать значение.

Дописываем в while() и for() реакции на эти значения.
При выходе из функции Do()  проверяем, не осталось ли за нами долгов:
             if(do_opt_cbr){
                 if(do_opt_cbr==MSLCBR_CONT) SetError("for/while for continue; not found");
                 if(do_opt_cbr==MSLCBR_BREAK) SetError("for/while for break; not found");
                 if(do_opt_cbr==MSLCBR_RET) do_opt_cbr=MSLCBR_NULL;
             }

Все.  Тестировать увы не на чем. Операций == и других пока нет. Они и станут нашей следующей темой.
С общей логикой в принципе покончено. Добавить операции и можно пользоваться как вполне полноценным языком. Без функций и классов, но уже язык.

ЗЫ. Спасибо ЖЖ за падение и чудесное открытие, что копируясь из word'а код не теряет своего цвета.

?

Log in

No account? Create an account