Наверх

Пред. След.  

 

Более совершенный сканер.

 

Перейдем теперь от нашего примитивного сканера к нормальному. Последовательность действий такая – сперва читаем байты из файла с исходным текстом (Pr_str.txt) в строку. Указатель на эту строку делаем глобальной переменной. И начинаем «идти вдоль» строки (сканировать байт за байтом). Если мы при каком-то вызове функции-сканера закончили просмотр строки на каком-то месте, при следующем вызове продолжим с этого же места (из-за глобальности указателя).

Ниже я привожу программу для испытания сканера. Лексемы она выводит в файл Result.txt.

 

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

 

 

    #include <stdio.h>

    #include <stdlib.h>

    #include <ctype.h>

    #include <string.h>

 

    #include "Str_ex.h"

    #include "QnS.h"

 

 

 

    int I=0;

            int n=5;

 

            char Lex[150];  /* Это для лексем */

 

            char End[3];    /* Это конец строки в текстовом файле */

 

    /* Переменные относятся к сканеру */

            char Prog[64000]; /* Это для текста программы */

            char *pProg;      /* Указатель, двигающийся по строке программы */

 

            char LastLex[150];  /* Это для последней лексемы */

            char *pProgLast;    /* Здесь указатель на начало последней

                                полученной лексемы */

            char *pProgLast2;  

 

 

/*         char SS[50];*/

/*         char Sign1[2]={43,0};

            char Sign2[2]={45,0};

            char Sign3[2]={42,0};

            char Sign4[2]={47,0};*/

 

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

/*           sprintf(A,"n=%d",n);*/

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

            /* Это - построение сканера  */

 

 

            int isDelim(int S)  /* Является ли знак разделителем, */

            {

                        if(S==43||  /* - */

           S==45||  /* + */ 

           S==42||  /* * */ 

           S==47||  /* / */  

           S==37||  /* % */

           S==61||  /* = */ 

           S==60||  /* < */ 

           S==62||  /* > */ 

           S==59||  /* ; */  

           S==40||  /* ( */  

           S==41||  /* ) */  

           S==33||  /* ! */  

           S==44||  /* , */  

           S==46)   /* . */  

                        {

                                    return 1;

                        }

                        else

                        {

                                    return 0;

                        };

           

           

           

            }

 

 

 

            int isDelim1(int S,int SNext)  /* Является ли знак разделителем, плюс

                        учет того, что если после точки цифра, то точка уже не разделитель

                        (чтобы действительное число с дробной точкой не разбивалось) */

            {

                        if(S==43||  /* - */

           S==45||  /* + */ 

           S==42||  /* * */ 

           S==47||  /* / */  

           S==37||  /* % */

           S==61||  /* = */ 

           S==60||  /* < */ 

           S==62||  /* > */ 

           S==59||  /* ; */  

           S==40||  /* ( */  

           S==41||  /* ) */  

           S==33||  /* ! */  

           S==44||  /* , */  

           S==46)   /* . */  

                        {

                                    if(S=='.')

                                    {

                                                if(isdigit(SNext)!=0)

                                                {

                                                return 0;

                                                }

                                                else

                                                {

                                                            return 1;

                                                };

                                    }

                                    else

                                    {

                                                return 1;

                                    };

                        }

                        else

                        {

                                    return 0;

                        };

            }

 

 

            void ErrorScaner(int N)

            {

                        ;

        if(N==1) WrStr("Result_0.txt",End,"Unknown Sign - 1-st in Lexema! ",1);

        if(N==2) WrStr("Result_0.txt",End,"No 2-nd quota",1);

 

                        return;

            }

 

            void NextLexema() /* Получает очередную лексему */

            {

              char *pLex=(char *)Lex;

 

                        if(*pProg==0) /* Если на входе пустая строка */

                        {

                                    *pLex=0;

                                    return;

                        }

        

                        /* Сохраняем положение указателя на позицию

                        в тексте программы (если вдруг придется

                        возвращаться назад):  */

        pProgLast2=pProgLast;

                        pProgLast=pProg;

 

                        while(isspace(*pProg)) ++pProg; /* Убираем лидирующие пробелы */

 

 

                        if(*pProg==47&&*(pProg+1)==42) /* Обработка комментария */

                        {

                                    pProg++;

                                    pProg++;

                                    while(!(*pProg==42&&*(pProg+1)==47))

                                    {

                                                if(*pProg==0) return;

                                                pProg++;

                                    }

                                    pProg++;

                                    pProg++;

 

                                    /*return;*/

                        }

 

                        while(isspace(*pProg)) ++pProg; /* Убираем  пробелы после комментария */

 

 

                        if(*pProg==45||  /* - */

           *pProg==43||  /* + */ 

           *pProg==42||  /* * */ 

           *pProg==47||  /* / */  

           *pProg==37||  /* % */

           *pProg==61||  /* = */ 

           *pProg==60||  /* < */ 

           *pProg==62||  /* > */ 

           *pProg==59||  /* ; */  

           *pProg==40||  /* ( */  

           *pProg==41||  /* ) */  

           *pProg==33||  /* ! */  

           *pProg==44||  /* , */  

           *pProg==46)   /* . */

                        {  /* Это мы рассматриваем знаки */

/***/   /* Обработка двухсимвольных знаков */

                                    if(*pProg==60&&*(pProg+1)==61)

                                    {

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=0;

                                    return;

                                    }

 

                                    if(*pProg==62&&*(pProg+1)==61)

                                    {

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=0;

                                    return;

                                    }

 

                                    if(*pProg==60&&*(pProg+1)==62)

                                    {

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=0;

                                    return;

                                    }

 

                                    if(*pProg==33&&*(pProg+1)==61)

                                    {

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=0;

                                    return;

                                    }

 

/***/   /* Теперь - односимвольные */

 

                                    *pLex=*pProg;

                                    pProg++;

                                    pLex++;

                                    *pLex=0;

                                    return;

                        }

 

                        if(*pProg==34) /* Обработка выражения в кавычках */

                        {

                                    *pLex=34;

                                    pProg++;

                                    pLex++;

                                    while(*pProg!=34)

                                    {

                                                if(*pProg==0)

                                                {

                                                            ErrorScaner(2);

                                                            return;

                                                }

                                                *pLex++=*pProg++;

                                    }

                                    pProg++;

                                    *pLex=34;

                                    pLex++;

                                    *pLex=0;

                                    return;

                        }

 

 

                        if(isdigit(*pProg)) /* Начинаем рассматривать число */

                        {

                        int k=0;

                        while(k>-1)                            

                        {

                                    if(*pProg==0)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    if(*pProg==13)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    if(*pProg==10)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    if(isspace(*pProg)==1)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    if(isDelim1(*pProg,*(pProg+1))==1)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    *pLex=*pProg;

                                    pLex++;

                                    pProg++;

                        }

                        }

 

 

                        if(isalpha(*pProg)) /* Начинаем рассматривать имя переменной или

                                                                                    ключевое слово языка */

                        {

                        int k=0;

                        while(k>-1)                            

                        {

                                    if(*pProg==0)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    if(*pProg==13)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    if(*pProg==10)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    if(isspace(*pProg)==1)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    if(isDelim(*pProg)==1)

                                    {

                                                *pLex=0;

                                                return;

                                    }

                                    *pLex=*pProg;

                                    pLex++;

                                    pProg++;

                        }

                        }

 

                        if(!(isspace(*pProg)!=0||*pProg==0)) ErrorScaner(1);

                        pProg++;

 

                        return;

            }

 

 

 

 

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

 

 

 

    void main(void)

 

    {

                        Lex[0]=0;

 

                        End[0]=13;

                        End[1]=10;

                        End[2]=0;

                        char dest[200];

 

/*****/

FILE *f1;

int Ch;

char ch;

int jc,J;

 

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++;

}

 

/*****/

 

                        jc=0;

                        /* Сканируем лексему за лексемой */

                        while(jc>-1)

                        {

 

                WrStr("Result.txt",End,"one more lexema",1);

                        Lex[0]=0;

 

                        NextLexema();

                WrStr("Result.txt",End,Lex,1);

                        if(*Lex==0) break;

                        }

 

                WrStr("Result.txt",End,"End!!!",1);

 

                        /* Проверяем, удастся ли получить предшествующую

                        лексему */

 

                        /*pProg=pProgLast;

                        NextLexema();

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

 

                        /*pProg=pProgLast2;

                        NextLexema();

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

 

                        return;

            }

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

Это проект Gramm1_001.

 

Хостинг от uCoz