Лексика языков программирования. Конечные автоматы без памяти для обнаружения слов в тексте программы, страница 3

      retLexem.groupIndex = (curState >= 0 ? -2147483647 : curState | 0x40000000); //сформируем индекс группы слов

      if( (curState = (int)w.length())  >  0 )

//если слово содержит хотя бы одну литеру

      {

            retLexem.textOfWord.append(w);      //перепишем его в лексему

            w.erase(0,curState);   

//и подготовим строку для накопления текста следующего слова

      }

      return retLexem;  //вернем лексему

}

public: int getIndex()

{

      return index;

}

};

Лексический акцептор для графового способа реализации КА.

class fAutomat

{

      int index;  //собственный индекс акцептора (имеет смысл в мультиавтоматном варианте)

      vector<faState*> states;      //множество состояний графа

      textReader& inp;        //входной поток литер

      string w;   //накопитель текста слова

      bool inputExists; //флажок состояния входного потока

//конструктор одноавтоматного варианта

public: fAutomat(int nodesCount, textReader& Inp)

: states(nodesCount), inp(Inp)

{

      fAutomat(0, nodesCount, Inp);

}

//конструктор мультиавтоматного варианта

public: fAutomat(int ind, int nodesCount,textReader& Inp)

: states(nodesCount), inp(Inp)

{

      for (int i = 0; i < nodesCount; i++)

            states[i] = NULL;

//заполним нулями массив состояний (вершин графа)

      index = ind;      //запомним собственный индекс

      inputExists = true;    

//установим флажок, что входной поток не исчерпан

}

//сохранение заданного состояния (вершины)

public: void setState(size_t no, faState* st)

{

      if((no >= 0) && ( no < states.size()))  

//если номер состояния в заданных пределах

            states[no] = st;  //сохраним состояние в массиве

}     //иначе ничего не делаем

//основной метод лексического акцептора - чтение одного слова из входного потока и формирование лексемы

public: lexem fAutomat::getLexem()

{

      int curState = -1;     

//текущее состояние (-1 на случай, если входной поток ранее был исчерпан)

      int curChar = -1;

//текущая литера (-1 на случай, если входной поток ранее был исчерпан)

      int newState;

      if(inputExists)   //если входной поток существует

            for(curState = 0; curState>=0; )   

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

            {

                  try

                  {

                        curChar = inp.read();  

//пытаемся получить очередную литеру

                  }

                  catch(...)  //(exception &e)

                  {

                        curChar = -1;    

//если это не удалось, формируем значение кода литеры -1

                  }

                  if(curChar == -1) //если код литеры равен -1

                  {

                        inputExists = false;   

//сбрасываем флажок существования входного потока

//и формируем текущее состояние

//-1, если конец входного потока обнаружен в момент запуска автомата

//и номер финального состояния, в которое из текущего есть переход по эпсилон в противном случае

//(возможен случай, когда такого перехода нет, тогда получим значение -2147483647)

                        newState = (curState == 0 ? -1 : states[curState]->getFinalState());

                  }

                  else  //если код литеры получен

                  {

                        newState = states[curState]->getState((char)curChar);     //получаем новый номер состояния

                        if((newState==-1)&&(curState==0))

                              newState=-2147483647;

                  }

//если номер нового состояния вне пределов массива состояний или код литеры меньше нуля - выйдем из цикла