Наверх

Пред. След.

 

 

Метки и оператор GOTO.

 

Как-то в Интернете я наткнулся на диаграмму Вирта для языка, похожего на Паскаль. Этот документ натолкнул меня на мысль, как можно «обработать» метки. Введем не просто оператор, а «Общий оператор». Общий оператор может быть либо помеченным оператором, либо просто оператором. Помеченный же оператор состоит из метки на первом месте, потом двоеточия и, наконец, оператора. Вот БНФ:

 

            <Программа>:=<Поток операторов>

            <Поток операторов>:=[<Общий оператор><;>]

            <Общий оператор>:=<Помеч.оператор>|<Оператор>

            <Помеч.оператор>:=<Метка><:><Оператор>

            <Оператор>:=<Присваивание>|<Вывод>

            <Присваивание>:=<Переменная>=<Вычисленное выражение>

            <Вывод>:=<PRINT>(<Вычисленное выражение>)

            <Вычисленное выражение>:=<Expr2>

<expr2> := <expr1> {<бинарная, логическая><expr1>}

<expr1> := <expr> {<операция сравнения><expr>}

<expr> := <term> {<add_op><term>}

<term> := <signed_factor>{<mul_op><signed_factor>}

<signed_factor> := [<add_op или лог-е отрицание>]<factor>

<factor> := <float>|”<string>”|(<expr2>)|<funcname>([<expr2>{,<expr2>}])

|<Переменная>

 

            А как быть с оператором безусловного перехода? Модифицируем форму еще:

            <Программа>:=<Поток операторов>

            <Поток операторов>:=[<Общий оператор><;>]

            <Общий оператор>:=<Помеч.оператор>|<Оператор>

            <Помеч.оператор>:=<Метка><:><Оператор>

            <Оператор>:=<Присваивание>|<Вывод>|<jump>|<пустой>

            <jump>:=<GOTO><Метка><;>

             <Пустой>:=<;>

            <Присваивание>:=<Переменная>=<Вычисленное выражение>

            <Вывод>:=<PRINT>(<Вычисленное выражение>)<;>

            <Вычисленное выражение>:=<Expr2>

<expr2> := <expr1> {<бинарная, логическая><expr1>}

<expr1> := <expr> {<операция сравнения><expr>}

<expr> := <term> {<add_op><term>}

<term> := <signed_factor>{<mul_op><signed_factor>}

<signed_factor> := [<add_op или лог-е отрицание>]<factor>

<factor> := <float>|”<string>”|(<expr2>)|<funcname>([<expr2>{,<expr2>}])

|<Переменная>

 

            Если вы внимательно посмотрите, то увидите, что операторы вывода и перехода (и пустой тоже ) отличаются от оператора присваивания тем, что строку формы БН для первых завершает точка с запятой. И в программе происходит проверка на наличие точки с запятой. Без этого, как я пришел к выводу при экспериментах еще с первоначальным сканером (см.ранее), отлавливается меньше ошибок. Причина этого, скажу честно, сейчас мне не ясна. На этот счет см. также постскриптум к главе 9 (он дописан позже).

            При дальнейшем программировании пришлось пойти на серьезное изменение программы – ввести глобальный параметр ToDo. Если он равен 0, то лексемы во время анализа в строку  с обратной польской записью Res не вставляются, поиск переменных в таблицах не происходит, не запускается PostFix для вычисления значений формул. То-есть не выполняются никакие реальные полезные действия. В чем идея, спросите. В том, чтобы при безусловном переходе вперед, когда метка еще не найдена, отключать реальные действия (ToDo=0) , а когда метка найдена, снова включать. Можно было сперва просмотреть всю программу без выполнения (первый проход) и запомнить все метки, но мне хотелось сделать однопроходный транслятор.

            Пришлось также ввести таблицу меток (также в виде 2-х списков – в первом имена меток, во втором «значени», то-есть смещения относительно начала строки с программой).

По правде говоря, с безусловными переходами пришлось долго повозиться.

 

Теперь –  основные функции программы (те, которые в конце). Всю программу не привожу, так как она уже «разбухла» в достаточной степени.

 

 

/********************************/

            void Expr2_Res() /* Не только разбор, но и вычисление выражения */

            {

                        expr2();

                        /* Это если в конце разбора осталась лишняя

                                                             лексема (но не знак) */

                        if(*Lex!=0&&*Lex!=59) /* (null и ;) Попытка отловить если строка завершается на "левый" символ */

                        {

                        *Res=0;

                        ErrorLex(10);

                        /*WrStr("Unnecessary.txt",End,Lex,1); */

                        }

                        if(*Lex==0) /* Попытка отловить, если строка не завершается ; */ 

                        {

                        *Res=0;

                        ErrorLex(10);

                /*WrStr("Unnecessary.txt",End,Lex,1);*/

                        }

 

                        if(ToDo!=0)

        { 

        PostFix(Res,dest);

                        }

 

                        /**Res=0;*/

 

            }

 

            void Assignment()  /* Это - (оператор) присваивания */

            {

                        int N;  /* Номер переменной в таблице */

                        int er;

 

                        if(*Lex>=65&&*Lex<=90) /* Если начинается с бол.лат.буквы */

                        {

                        if(ToDo!=0)

            {

                                    N=SEARCHlistP(pL1,Lex,0);

                                    if(N<0)

                                    {

                                                er=ADDendStrP(pL1,Lex);

                                                if(er!=1)

                                                {

                                                            ErrorList(2);

                                                            return;

                                                }

                                                er=ADDendStrP(pL2,"N");

                                                if(er!=1)

                                                {

                                                            ErrorList(2);

                                                            return;

                                                }

                                                er=ADDendStrP(pL3,"Empty");

                                                if(er!=1)

                                                {

                                                            ErrorList(2);

                                                            return;

                                                }

                                                N=LenStrP(pL1)-1; /* Узнаем номер добавленной переменной в списке */

                                                if(N<1)

                                                {

                                                            ErrorList(3);

                                                            return;

                                                }

                                    }

                                    }

 

                                    NextLexema();

                                    if(*Lex==61)

                                    {

                                    NextLexema();

                                    Expr2_Res();

                                    /* Результат теперь находится в dest */

                                    if(*dest==0)

                                    {

                                                ErrorStack(-14);

                                                return;

                                    }

 

                if(ToDo!=0)

        {

                                    if(*dest==34)

                                    {  /* Если строка */

                                    REPStrP(pL2,"S",N);  /* Меняем тип на строковый */

                                    REPStrP(pL3,dest,N); /* Помещаем результат в табл. пер-х */

                                    }

                                    else

                                    {

            if(testnum_p(dest)==0)

                                    {

                                    REPStrP(pL2,"D",N);  /* Меняем тип на числовой (Double) */

                                    REPStrP(pL3,dest,N); /* Помещаем результат в табл. пер-х */

                                    }

                                    else

                                    {

                                                ErrorStack(-15);

                                                return;

                                    }

                                    }

                        }

                                    *dest=0;

                                    /**Res=0;*/

                                    }

                                    else

                                    {

                        *Res=0;

                                    ErrorLex(11);

            /*WrStr("Error.txt",End,"ERROR - No = after var !!!  ",1); */

                                    return;

                                    }

 

                        }

                        else

                        {

                        *Res=0;

                                    ErrorLex(12);

            /*WrStr("Error.txt",End,"ERROR - No var in beginning of string !!!  ",1); */

                                    return;

                        }

 

            }

 

            void OutPut()

            {

                        NextLexema();

                        /***************/

                if(*Lex==40)  /* Если скобка */

                        {

                        NextLexema();

 

                        expr2();

 

                        if(ToDo!=0)

        {

        PostFix(Res,dest);

                        }

 

                        if(*Lex!=41)

                        {

                        *Res=0;

                        ErrorLex(14);

        /*WrStr("Error.txt",End,"ERROR - No 2-nd bracket in PRINT",1); */

                        return;

                        }

                        else

                        {

        /*WrStr("ResultPRINT.txt",End,dest,1);*/ /* Это - главное действие оператора */

                        if(ToDo!=0)

        {

                        if(*dest==34)

                        {

                                    printf("%s\n",dest+1);

                        }

                        else

                        {

                                    printf("%s\n",dest);

                        }

                        }

                        *dest=0;

                        /**Res=0;*/

                        NextLexema();

                        if(*Lex!=59)

                        {

        ErrorLex(15);

                        return;

        /*WrStr("Error.txt",End,"No ; after PRINT(...)",1); */

                        /*NextLexema();*/

                        }

 

                        }

                        }

            }

 

 

            void GoTo()

            {

                        int N;

                        char S[20];

                        int J1;

                        char Lex1[50];

                        int er;

 

                        NextLexema();

                        if(ToDo!=0)

                        {

                        CpStr(Lex,Lex1);

                        }

/*WrStr("TEST.txt",End,"t 1",1);*/

                        NextLexema();

                        if(*Lex!=59)

                        {

        WrStr("Error.txt",End,"No ; after GOTO ...",1);

                        NextLexema();

                        }

/*WrStr("TEST.txt",End,"t 2",1);*/

 

                        /***************/

                        if(ToDo!=0)

                        {

                                    N=SEARCHlistP(pLa1,Lex1,0);

                                    if(N<0)

                                    {

                        CpStr(Lex1,WaitLabel); /* Не найденную в табл. метку записываем как ожидаемую (в будущем) */

                                    ToDo=0;

                                    }

                                    else

                                    {

                        er=READonPosStrP(pLa2,N,S);

                        if(er!=1)

                                                {

                                                            ErrorList(4);

                                                            return;

                                                }

            J1=atoi(S);

                                    /*J=J1+1;*/

            /*  *Lex=0;*/

                                    pProg=Prog+J1;

                                    }

                        }

            }

 

    void Operators()  /* Это - собственно оператор (присваивания и др) */

            {

                        if(COMPstr(Lex,"PRINT")==0)

                        {

                                    OutPut();

                                    return;

                        }

                        if(COMPstr(Lex,"GOTO")==0)

                        {

                                    GoTo();

                                    return;

                        }

                        if(COMPstr(Lex,";")==0) /* Обработка пустого оп-ра */

                        {

                                    return;

                        }

                        Assignment();

            }

 

 

            void Labeled()

            {

                        int N1;

                        char sL[50];

                        int er;

 

                        if(!(*Lex>=65&&*Lex<=90))

                        {

                        *Res=0;

                        ErrorLex(16);

        /*WrStr("Error.txt",End,"Bad name of label ",1); */

                        /*goto EndLabeled;*/

                        return;

                        }

 

        N1=SEARCHlistP(pLa1,Lex,0);

                        if(N1<0)

                        {

                        er=ADDendStrP(pLa1,Lex);  /* Заносим метку в таблицу */

                if(er!=1)

                                                {

                                                            ErrorList(2);

                                                            return;

                                                }

                        /*sprintf(sL,"%d%",(int)(pProg-Prog-lenstr(Lex)));*/

                        sprintf(sL,"%d%",pLab);   /* Заносим, куда прыгать */

                        er=ADDendStrP(pLa2,sL);

                        if(er!=1)

                                                {

                                                            ErrorList(2);

                                                            return;

                                                }

 

                        if(COMPstr(Lex,WaitLabel)==0&&ToDo==0)

                        {

                                    ToDo=1;

                                    WaitLabel[0]=0; /* Очищаем ожидаемую метку - никуда не хотим идти */

                        }

 

                        NextLexema();

                        NextLexema();

                        Operators();

                        }

                        else

                        {

                        ErrorLex(17);

 

                        NextLexema();

                        NextLexema();

                        return;

                        /*goto EndLabeled;*/

                        }

/*EndLabeled:*/  ;

 

            }

 

    void GenOperators()  /* Это - общий оператор (может быть помеченный, т.е. с меткой) */

            {

                        char Lex1[150];

 

                        CpStr(Lex,Lex1);

                        NextLexema();

                        if(*Lex==58)

                        {

                                    CpStr(Lex1,Lex);

                                    pLab=(int)(pProg-Prog);  /* Вычисляем, куда прыгать */

            /*J--;*/

                                    pProg=pProgLast;

                                    Labeled();

                        }

                        else

                        {

                                    CpStr(Lex1,Lex);

            /*J--;*/

                                    pProg=pProgLast;

                                    Operators();

                        }

 

            }

 

 

            /*****/

    void StreamOp()  /* Это - поток операторов */

            {

                        while(*Lex!=0)

                        {

                                    GenOperators();

                                    /*NextLexema();*/

                                    if(*Lex!=59) /* не нашли (;)  */

                                    {

                        *Res=0;

                                    ErrorLex(13);

            /*WrStr("Error.txt",End,"ERROR - No ; in the end of string !!!  ",1); */

                                    return;

                                    }

                                    else

                                    {

            NextLexema();

                                    }

 

                        }

 

            }

 

            void Prog0()  /* Эта ф-я соответствует программе в целом */

            {

                        int er;

                        ToDo=1;

                        /*pSt=CreateStack(10000);*/

                        /* Заводим во все списки первое,пустое значение */

                        pL1=CRbegStrP("");  /* Здесь имена переменных */

                        if(pL1==NULL)

                        {

                                    ErrorList(1);

                                    return;

                        }

                        pL2=CRbegStrP("");  /* Здесь их типы */

                        if(pL2==NULL)

                        {

                                    ErrorList(1);

                                    return;

                        }

                        pL3=CRbegStrP("");  /* А здесь их значения */

                        if(pL3==NULL)

                        {

                                    ErrorList(1);

                                    return;

                        }

 

                        pLa1=CRbegStrP("");

                        if(pLa1==NULL)

                        {

                                    ErrorList(1);

                                    return;

                        }

                        pLa2=CRbegStrP("");

                        if(pLa2==NULL)

                        {

                                    ErrorList(1);

                                    return;

                        }

 

                        StreamOp();

                        /*DeleteStack(pSt);*/

 

              DELallStrP(pL1);

              DELallStrP(pL2);

              DELallStrP(pL3);

 

              DELallStrP(pLa1);           

              DELallStrP(pLa2);           

 

            }

 

            /*******************/

 

 

 

    void main(void)

 

    {

                        Lex[0]=0;

 

                        Res[0]=0;

 

                        End[0]=13;

                        End[1]=10;

                        End[2]=0;

                        DelimPol[0]=4; /* Задаем разделитель в стеке */

                        DelimPol[1]=0;

 

 

/*  Чтение файла с программой   */

/*****/

FILE *f1;

int Ch;

char ch;

int jc,J;

int er;

 

pProg=Prog;

 

pProgLast=Prog;

/*pProgLast2=Prog;*/

 

f1=fopen("pr_str.txt","rb");

 

if(f1==NULL)

{

    return;

}

 

jc=0;

J=0;

/* Чтение программы из файла в строку */

while(jc>-1)

{

    Ch=fgetc(f1);

    if(Ch==EOF)

    {

        fclose(f1);

        break;

    };

 

    ch=(char)Ch;

            *(pProg+J)=ch;

            J++;

}

 

/*****/

 

 

/*  Конец чтения файла с программой   */

 

                        NextLexema();

                        Prog0();

 

 

/*           er=CpListToFileP(pL1,"ListVar.txt");

              if(er!=0)

              {

                          ErrorList(5);

                          return;

              }

              er=CpListToFileP(pL3,"ListVar_Val.txt");

              if(er!=0)

              {

                          ErrorList(5);

                          return;

              }*/

/*           er=CpListToFileP(pL2,"ListVar_Type.txt");

              if(er!=0)

              {

                          ErrorList(5);

                          return;

              }*/

 

/*           er=CpListToFileP(pLa1,"ListLab.txt");

              if(er!=0)

              {

                          ErrorList(5);

                          return;

              }

              er=CpListToFileP(pLa2,"ListLab_Val.txt");

              if(er!=0)

              {

                          ErrorList(5);

                          return;

              }*/

 

 

              return;

            }

Это все – из папки Gramm94_002.

 

 

 

Хостинг от uCoz