if(((curState=newState) < 0)||(curState >= (int)states.size())||(curChar < 0))
break;
w.push_back((char)curChar);
//если по этой литере был выполнен переход в рабочее состояние - добавим ее к тексту слова
}
if((curState < -1) && (curState > -2147483647)) //если не EndOfFile и не ошибка (в частности ошибкой является случай, когда curState>=0)
inp.back(curChar); //вернем литеру во входной поток
lexem retLexem; //образуем новую лексему
retLexem.wordIndex = 0; //индекс слова установим в 0
retLexem.groupIndex = (curState >= 0 ? -2147483647 : curState); //сформируем индекс группы слов
if((curState = (int)w.length()) > 0) //если слово содержит хотя бы одну литеру
{
retLexem.textOfWord.append(w);
//поместим текст слова в лексему
w.erase(0,curState);
//и подготовимся к накоплению текста следующего слова
}
return retLexem; //вернем лексему
}
public: int getIndex() //возвращает индекс акцептора, нужен в мультиавтоматном варианте
{
return index;
}
};
Сравнение реализации конечных автоматов, управляемых различными способами, между собой:
1. В плане написания алгоритма на каком-то языке (в частности на C++) для каждого из этих способов. Код по объему окажется приблизительно одинаковой, как в одном, так и другом способе нужны дополнительные классы (для таблиц это класс (преобразователь кода символа в индекс), а для графа это класс (дуга графа состояний и переходов конечного автомата)). Сложность алгоритмов тоже приблизительно одинаковая.
2. Для восприятия и понимая, лучше подходит графовой способ, чем табличный. Это возможно обусловлено, тем, что графой способ отображается в виде рисунка и содержит меньше чисел, чем табличный.
3. Но табличный способ отображает все переходы в полном объеме, часто графовом способом не все видно наглядно. Когда из графогово способа, переходят к табличному способу, становиться видно автомат полностью определенный или нет.
В итоге можно сказать, что какому-то способу отдать предпочтение сложно, т.к. эти два способа дополняют друг друга и лучший вариант использовать их вместе.
4.Изучил реализацию вызова действий, определенных в лексических правилах и алгоритм работы формирователя лексем (см. ст. 8-9 для табличного способа, ст. 10-11 для графового способа).
Вызов действий, определенных в лексических правил:
public:
lexem getLexem()
{
if(lexStk.size()<=0) //если стек пуст - вернем лексему-ошибку
{
Lexem.groupIndex = -2147483647;
return Lexem;
}
ignoreLastWord = true;
//для входа в основной цикл установим флажок игнорирования слова
while(ignoreLastWord)
{
ignoreLastWord = false;
//и сбросим его (возможно, он будет установлен действием)
//вызов лексического акцептора:
Lexem = lexAcceptor->getLexem();
//получим лексему от текущего лексического акцептора
//для каждого автомата и каждой группы слов обеспечим возможность выполнения действий (имена автоматов и групп слов в примечаниях)
//индексы групп слов, имена которых используются в грамматике, преобразуются в те значения, который присвоил им построитель синтаксического акцептора
//в действиях, в частности, может быть взведен флажок ignoreLastWord и изменены поля лексемы, установленные акцептором
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.