Наверх

Пред. След.

 

 

Оператор IF.

 

Ввел еще один параметр, отключающий при нулевом значении полезные действия (ToDoif), аналогичный  ToDo. С его помощью отключается выполнение внутри IF. Я решил не задействовать для этого ToDo, так как возникло подозрение, что IF и безусловные переходы GOTO начинают «мешать» друг другу.

Приведу отрывок программы – функции IfOp и Operators (из проекта папки Gramm95_003).

 

/*** If  **/

            void IfOp()

            {

                        int Result;

                        int ToDoif1;

                        char Lex2[20];

 

 

                        NextLexema();

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

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

                        {

                        *Res=0;

                        ErrorLex(18);

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

                        return;

                        }

                        ToDoif1=ToDoif;

 

                        NextLexema();

 

                        expr2();

 

                        if(ToDo!=0&&ToDoif!=0)

                        {

        PostFix(Res,dest);

        Result=atoi(dest); 

                        }

 

                        if(*Lex!=41)

                        {

                        *Res=0;

                        ErrorLex(19);

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

                        return;

                        }

 

                        if(ToDo!=0&&ToDoif!=0)

                        {

                        if(Result!=0)

                        {

                                    ToDoif=1;

                        }

                        else

                        {

                                    ToDoif=0;

                        }

                        /*ToDoif1=ToDoif;*/

                        }

 

                        NextLexema();

                        while(1==1)

                        {

        GenOperators();

                        NextLexema();

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

                        {

                                    ToDoif=ToDoif1;

                                    break;

                        }

                        if(*Lex==0)

                        {

                        /**Res=0;*/

                                    /*ErrorLex(20);*/

            /*WrStr("Error.txt",End,"Cannot find ENDIF",1);*/

                                    break;

                        }

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

                        {

                                    break;

                        }

                        }

/****ELSE******/

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

                        {

        if(ToDo!=0&&ToDoif!=0)

                        {

                        if(Result!=0)

                        {

                                    ToDoif=0;

                        }

                        else

                        {

                                    ToDoif=1;

                        }

                        }

 

                        NextLexema();

                        while(1==1)

                        {

        GenOperators();

                        NextLexema();

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

                        {

                                    ToDoif=ToDoif1;

                                    break;

                        }

                        if(*Lex==0)

                        {

                        /**Res=0;*/

                                    /*ErrorLex(20);*/

            /*WrStr("Error.txt",End,"Cannot find ENDIF",1);*/

                                    break;

                        }

                        }

 

                        }

/*****конец обр-ки ELSE*******/

                        /*ToDoif=ToDoif1;*/

 

                        NextLexema();

 

                        /*if(*Lex!=59)

                        {

        ErrorLex(21);

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

                        NextLexema();

                        }*/

 

 

    return;

 

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

            }

 

/*** End of If  **/

 

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

            {

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

                        {

                                    OutPut();

                                    return;

                        }

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

                        {

                                    GoTo();

                                    return;

                        }

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

                        {

                                    return;

                        }

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

                        {

                                    IfOp();

                                    return;

                        }

                        Assignment();

            }

 

            БНФ я здесь не привожу. Дело в том, что когда я писал это место, я руководствовался не БНФ, а логикой. Далее я переписал этот кусок программы, немного изменив его (это было уже после введения WHILE). БНФ будет показана уже для окончательного варианта.

            Позже (в папке Gramm95_006) я ввел счет строк для точной диагностики ошибок (глобальная переменная STR, где находится номер текущей строки программы). Но счет отрабатывался не очень точно. Я пришел к выводу, что нужно менять сканер, но этого я пока делать не буду. В конце концов номера строк – это дело далеко не первой важности. Кроме того их точное отслеживание еще не решит проблему диагностики ошибок. Сошлюсь на авторитет – приведу мнение Робина Хантера (из книги «Основные концепции компиляторов»):

 «Возникновение ошибки при считывании одиннадцатого символа может быть связано как с некорректностью настоящего символа, так и с ошибкой в предыдущих символах программы, и это – одна из причин того, что сообщения об ошибках могут причинять неудобства. Это не означает, что компилятор может выдать сообщение об отсутствующей ошибке, он просто может указать неверное место ее нахождения и из-за этого неправильно ее охарактеризовать».

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

Кстати, вот пример программки (на создаваемом языке) и с IF , и с безусловными переходами:

 

M=1;

 

L0: M=M+1;

PRINT("SSSSSSSSSSSSSSSSSSSSS");

J=1;

L2:J=J+1;

 

PRINT("AAAAAAAAAAA");

IF(J>10) GOTO L4;

ENDIF;

GOTO L2;

 

L4:

IF(M>5)

GOTO L1;

ENDIF;

GOTO L0;

 

L1:PRINT("The end!");

;;;;;;;;;;

 

Эта программа должна находиться в файле Pr_Str.txt.

Хостинг от uCoz