If (!file.Open(qioDevice::ReadOnly | qioDevice::Text))
QMessageBox::critical(0, "Error", "Cannot open file for read: %1", "OK");
QTextStream in(&file);
while (!in.atEnd()) //пока не конец
{
QString line = in.readLine(); //считываем очередную строку
findText(line); //ищем строку в ТИ
}
}
LexFSM.h
#ifndef LEXFSM_H
#define LEXFSM_H
#include <QObject>
#include <QString>
#include <QMap>
class QList;
class LexFSM : public QObject
{
Q_OBJECT
public:
LexFSM();
enum stateName
{
START, //начальное состояние
ID, //переменная
CONSTANT, //константа
SEPARATOR, //разделитель (;)
ERROR,
P, PR, PRO, PROG, PROGR, PROGRA, PROGRAM, //program
E, EN, END, //end
ENDD, //end.
ENDI, ENDIF, //endif
EL, ELS, ELSE, //else
I, IF, //if
T, TH, THE, THEN, //then
B, BE, BEG, BEGI, BEGIN, //begin
A, AN, AND, //and
O, OR, //or
N, NO, NOT, //NOT
LBRACKET, // (
LASTER, RASTER, COMMENT, //комментарий (* *)
RBRACKET, // )
ADD, // +
SUB, // -
EQUAL, // =
LESS, // <
NONEQUAL, // <>
LSHIFT, // << - дополнительная операция
MORE, // >
RSHIFT, // >> - дополнительная операция
TWOSPOT, ASSIGN, // :=
FINITE, //конечное состояние
STOP,
//дополнительные состояния, соответствующие варианту задания
F, FO, FOR, //for
D, DO, //do
DOW, DOWN,DOWNT, DOWNTO //downto
};
private:
QChar cReserved;
QString lexeme;
stateName state;
void setNextState(stateName);
QString stateString(LexFSM::stateName name);
QString finiteStateString(LexFSM::stateName name);
QList<QChar> idFiniteList;
private slots:
void startFSM();
void analyseNextChar(QChar c);
signals:
void getNextChar();
void lexError();
void addNewTableItem(QString);
void setAddLexeme(QString, QString, QString type);
void sendLog(QString text, QString description);
};
#endif
LexFSM.cpp
#include "LexFSM.h"
#include <QFile>
#include <QMessageBox>
#include <QTextStream>
#include <QChar>
#include <QList>
//Конечный автомат
LexFSM::LexFSM()
{
emit sendLog(tr("Модуль LexFSM подключен"), "MESSAGE");
state=START;
}
//Запуск автомата
void LexFSM::startFSM()
{
//Допустимые символы, следующие за переменными
idFiniteList<<' '<<'\n'<<'\0'<<':'<<';'<<'('<<')'<<'>'<<'<'<<'+'<<'-'<<'=';
state=START;
emit sendLog(tr("Начало работы лексического анализатора"), "END");
emit sendLog(tr("Запуск конечного автомата"), "END");
getNextChar();//Запросить входной символ
}
//Переход в новое состояние
void LexFSM::setNextState(LexFSM::stateName nextState)
{
if (state==STOP) //Если автомат остановлен, стоять
{
}
else
{
emit sendLog(tr("Переход из состояния %1 в %2").arg(stateString(state)).arg(stateString(nextState)), "EVENT");
if (nextState==STOP)//Остановка автомата
{
lexeme=lexeme.remove(QChar('\0'));
lexeme=lexeme.remove(QChar(65534));
if (!lexeme.simplified().isEmpty())
emit setAddLexeme(lexeme.simplified(), finiteStateString(state), stateString(state));
state=STOP;
emit sendLog(tr("Остановка конечного автомата"), "END");
emit sendLog(tr("Выполнение лексического анализа успешно завершено"), "END");
}
else if (nextState==FINITE) //Если конечное состояние
{
lexeme=lexeme.remove(QChar('\0'));
if (state==COMMENT) //Если обнаружен комментарий
{
emit sendLog(tr("Проигнорирован комментарий: %1").arg(lexeme.simplified()), "COMMENT");
lexeme="";
}
else if (state==CONSTANT)
{
bool constOk;
int cst=lexeme.simplified().toInt(&constOk, 2);
if ((!constOk) || (cst<0) || (cst>255))
{
QMessageBox::critical(0, "CONSTANT ERROR", tr("Ошибочная константа %1!\nКонстанты типа Byte - это беззнаковое целое от 0 до 255!").arg(cst), "OK");
setNextState(ERROR);
return;
}
else
{
emit setAddLexeme(lexeme.simplified(), finiteStateString(state), stateString(state));
emit sendLog(tr("Добавление новой строки: %1 (%2)").arg(lexeme.simplified()).arg(finiteStateString(state)), "END");
lexeme="";
}
}
else //Обнаружена новая лексема
{
emit setAddLexeme(lexeme.simplified(), finiteStateString(state), stateString(state));
emit sendLog(tr("Добавление новой строки: %1 (%2, %3)").arg(lexeme.simplified()).arg(finiteStateString(state)).arg(stateString(state)), "END");
lexeme="";
}
state=START; //Сброс автомата в начальное состояние
emit sendLog(tr("Новое состояние: %1").arg(stateString(state)), "MESSAGE");
analyseNextChar(cReserved); //Повторный анализ символа, приведшего в переходу в конечное состояние
}
else if ((state!=nextState) && (nextState==ID)) //переход в состояние идентификатора
{
state=ID;
emit sendLog(tr("Новое состояние: %1").arg(stateString(state)), "MESSAGE");
analyseNextChar(cReserved);
}
else if (nextState==ERROR) //Ошибка
{
emit sendLog(tr("Лексическая ошибка!"), "ERROR");
emit lexError();
state=ERROR;
emit sendLog(tr("Новое состояние: %1").arg(stateString(state)), "MESSAGE");
setNextState(STOP);
}
else //Обычный переход
{
lexeme.append(cReserved); //добавление символа в цепочку
state=nextState;
emit sendLog(tr("Новое состояние: %1").arg(stateString(state)), "MESSAGE");
emit getNextChar();//Запросить следующий символ
}
}
}
//Названия состояний, использующиеся для лога
QString LexFSM::stateString(LexFSM::stateName name)
{
QString string="";
switch(name)
{
case START:
string="START";
break;
case ID:
string="ID";
break;
case CONSTANT:
string="CONSTANT";
break;
case SEPARATOR:
string="SEPARATOR";
break;
case ERROR:
string="ERROR";
break;
case P:
string="P";
break;
case PR:
string="PR";
break;
case PRO:
string="PRO";
break;
case PROG:
string="PROG";
break;
case PROGR:
string="PROGR";
break;
case PROGRA:
string="PROGRA";
break;
case PROGRAM:
string="PROGRAM";
break;
case E:
string="E";
break;
case EN:
string="EN";
break;
case END:
string="END";
break;
case ENDD:
string="ENDD";
break;
case ENDI:
string="ENDI";
break;
case ENDIF:
string="ENDIF";
break;
case EL:
string="EL";
break;
case ELS:
string="ELS";
break;
case ELSE:
string="ELSE";
break;
case I:
string="I";
break;
case IF:
string="IF";
break;
case T:
string="T";
break;
case TH:
string="TH";
break;
case THE:
string="THE";
break;
case THEN:
string="THEN";
break;
case B:
string="B";
break;
case BE:
string="BE";
break;
case BEG:
string="BEG";
break;
case BEGI:
string="BEGI";
break;
case BEGIN:
string="BEGIN";
break;
case A:
string="A";
break;
case AN:
string="AN";
break;
case AND:
string="AND";
break;
case O:
string="O";
break;
case OR:
string="OR";
break;
case N:
string="N";
break;
case NO:
string="NO";
break;
case NOT:
string="NOT";
break;
case LBRACKET:
string="LBRACKET";
break;
case COMMENT:
string="COMMENT";
break;
case RBRACKET:
string="RBRACKET";
break;
case ADD:
string="ADD";
break;
case SUB:
string="SUB";
break;
case EQUAL:
string="EQUAL";
break;
case LESS:
string="LESS";
break;
case NONEQUAL:
string="NONEQUAL";
break;
case LSHIFT:
string="LSHIFT";
break;
case MORE:
string="MORE";
break;
case RSHIFT:
string="RSHIFT";
break;
case TWOSPOT:
string="TWOSPOT";
break;
case ASSIGN:
string="ASSIGN";
break;
case FINITE:
string="FINITE";
break;
case LASTER:
string="LASTER";
break;
case RASTER:
string="RASTER";
break;
case STOP:
string="STOP";
break;
case F:
string="F";
break;
case FO:
string="FO";
break;
case FOR:
string="FOR";
break;
case D:
string="D";
break;
case DO:
string="DO";
break;
case DOW:
string="DOW";
break;
case DOWN:
string="DOWN";
break;
case DOWNT:
string="DOWNT";
break;
case DOWNTO:
string="DOWNTO";
break;
}
return string;
}
//Описание конечных состояний
QString LexFSM::finiteStateString(LexFSM::stateName name)
{
QString string="";
switch(name)
{
case ID:
string=tr("Переменная");
break;
case CONSTANT:
string=tr("Константа");
break;
case SEPARATOR:
string=tr("Разделитель");
break;
case PROGRAM:
string=tr("Ключевое слово 'program'");
break;
case END:
string=tr("Ключевое слово 'end'");
break;
case ENDD:
string=tr("Ключевое слово 'end.'");
break;
case ENDIF:
string=tr("Ключевое слово 'endif'");
break;
case ELSE:
string=tr("Ключевое слово 'else'");
break;
case IF:
string=tr("Ключевое слово 'if'");
break;
case THEN:
string=tr("Ключевое слово 'then'");
break;
case BEGIN:
string=tr("Ключевое слово 'begin'");
break;
case AND:
string=tr("Ключевое слово 'and'");
break;
case OR:
string=tr("Ключевое слово 'or'");
break;
case NOT:
string=tr("Ключевое слово 'not'");
break;
case LBRACKET:
string=tr("Открывающая скобка");
break;
case RBRACKET:
string=tr("Закрывающая скобка");
break;
case ADD:
string=tr("Знак операции '+'");
break;
case SUB:
string=tr("Знак операции '-'");
break;
case EQUAL:
string=tr("Знак операции '='");
break;
case LESS:
string=tr("Знак операции '<'");
break;
case NONEQUAL:
string=tr("Знак операции '<>'");
break;
case LSHIFT:
string=tr("Оператор сдвига влево '<<'");
break;
case MORE:
string=tr("Знак операции '>'");
break;
case RSHIFT:
string=tr("Оператор сдвига вправо '>>'");
break;
case ASSIGN:
string=tr("Оператор присваивания ':='");
break;
case FOR:
string=tr("Ключевое слово 'for'");
break;
case DOWNTO:
string=tr("Ключевое слово 'downto'");
break;
case DO:
string=tr("Ключевое слово 'do'");
break;
}
return string;
}
//Обработка очередного входного символа
void LexFSM::analyseNextChar(QChar c)
{
emit sendLog(tr("Обработка символа '%1'").arg(c), "EVENT");
cReserved=c; //запоминание символа
if (c==QChar(65534)) //Если конец файла
{
setNextState(STOP); //остановить автомат
return;
}
switch(state) //если текущее состояние...
{
case START:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(START);
else if (c=='p')
setNextState(P);
else if (c=='e')
setNextState(E);
else if (c=='i')
setNextState(I);
else if (c=='t')
setNextState(T);
else if (c=='b')
setNextState(B);
else if (c=='a')
setNextState(A);
else if (c=='o')
setNextState(O);
else if (c=='n')
setNextState(N);
else if (c=='f')
setNextState(F);
else if (c=='d')
setNextState(D);
else if (c=='(')
setNextState(LBRACKET);
else if (c==')')
setNextState(RBRACKET);
else if (c==';')
setNextState(SEPARATOR);
else if (c=='+')
setNextState(ADD);
else if (c=='-')
setNextState(SUB);
else if (c=='=')
setNextState(EQUAL);
else if (c=='<')
setNextState(LESS);
else if (c=='>')
setNextState(MORE);
else if (c==':')
setNextState(TWOSPOT);
else if (('0'==c) || (c=='1'))
setNextState(CONSTANT);
else if (((c>='a') && (c<='z')) || ((c>='A') && (c<='Z')) || (c=='_'))
setNextState(ID);
else
setNextState(ERROR);
break;
case ID:
if (((c>='0') && (c<='9')) || ((c>='a') && (c<='z')) || ((c>='A') && (c<='Z')) || (c=='_'))
setNextState(ID);
else if (idFiniteList.contains(c))
setNextState(FINITE);
else
setNextState(ERROR);
break;
case SEPARATOR:
setNextState(FINITE);
break;
case CONSTANT:
if ((c=='0') || (c=='1'))
setNextState(CONSTANT);
else if ((c==':') || ((c>='a') && (c<='z')) || ((c>='A') && (c<='Z')))
setNextState(ERROR);
else
setNextState(FINITE);
case COMMENT:
setNextState(FINITE);
break;
case P:
if (c=='r')
setNextState(PR);
else
setNextState(ID);
break;
case PR:
if (c=='o')
setNextState(PRO);
else
setNextState(ID);
break;
case PRO:
if (c=='g')
setNextState(PROG);
else
setNextState(ID);
break;
case PROG:
if (c=='r')
setNextState(PROGR);
else
setNextState(ID);
break;
case PROGR:
if (c=='a')
setNextState(PROGRA);
else
setNextState(ID);
break;
case PROGRA:
if (c=='m')
setNextState(PROGRAM);
else
setNextState(ID);
break;
case PROGRAM:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case E:
if (c=='n')
setNextState(EN);
else if (c=='l')
setNextState(EL);
else
setNextState(ID);
break;
case EN:
if (c=='d')
setNextState(END);
else
setNextState(ID);
break;
case END:
if ((c==' ') || (c=='\n') || (c=='\0') || (c==';'))
setNextState(FINITE);
else if (c=='.')
setNextState(ENDD);
else if (c=='i')
setNextState(ENDI);
else
setNextState(ID);
break;
case ENDD:
if ((c==' ') || (c=='\n') || (c=='\0') || (c==QChar(65534)))
setNextState(FINITE);
else
setNextState(ID);
break;
case ENDI:
if (c=='f')
setNextState(ENDIF);
else
setNextState(ID);
break;
case ENDIF:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case EL:
if (c=='s')
setNextState(ELS);
else
setNextState(ID);
break;
case ELS:
if (c=='e')
setNextState(ELSE);
else
setNextState(ID);
break;
case ELSE:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case I:
if (c=='f')
setNextState(IF);
else
setNextState(ID);
break;
case IF:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case T:
if (c=='h')
setNextState(TH);
else
setNextState(ID);
break;
case TH:
if (c=='e')
setNextState(THE);
else
setNextState(ID);
break;
case THE:
if (c=='n')
setNextState(THEN);
else
setNextState(ID);
break;
case THEN:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case B:
if (c=='e')
setNextState(BE);
else
setNextState(ID);
break;
case BE:
if (c=='g')
setNextState(BEG);
else
setNextState(ID);
break;
case BEG:
if (c=='i')
setNextState(BEGI);
else
setNextState(ID);
break;
case BEGI:
if (c=='n')
setNextState(BEGIN);
else
setNextState(ID);
break;
case BEGIN:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case A:
if (c=='n')
setNextState(AN);
else
setNextState(ID);
break;
case AN:
if (c=='d')
setNextState(AND);
else
setNextState(ID);
break;
case AND:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case O:
if (c=='r')
setNextState(OR);
else
setNextState(ID);
break;
case OR:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case N:
if (c=='o')
setNextState(NO);
else
setNextState(ID);
break;
case NO:
if (c=='t')
setNextState(NOT);
else
setNextState(ID);
break;
case NOT:
case LBRACKET:
if (c=='*')
setNextState(LASTER);
else
setNextState(FINITE);
break;
case LASTER:
if (c=='*')
setNextState(RASTER);
else
setNextState(LASTER);
break;
case RASTER:
if (c==')')
setNextState(COMMENT);
else
setNextState(LASTER);
break;
case RBRACKET:
setNextState(FINITE);
break;
case ADD:
setNextState(FINITE);
break;
case SUB:
setNextState(FINITE);
break;
case EQUAL:
setNextState(FINITE);
break;
case LESS:
if (c=='>')
setNextState(NONEQUAL);
else if(c=='<')
setNextState(LSHIFT);
else
setNextState(FINITE);
break;
case NONEQUAL:
setNextState(FINITE);
break;
case LSHIFT:
setNextState(FINITE);
break;
case MORE:
if (c=='>')
setNextState(RSHIFT);
else
setNextState(FINITE);
break;
case RSHIFT:
setNextState(FINITE);
break;
case TWOSPOT:
if (c=='=')
setNextState(ASSIGN);
else
setNextState(ERROR);
break;
case ASSIGN:
setNextState(FINITE);
break;
case F:
if (c=='o')
setNextState(FO);
else
setNextState(ID);
break;
case FO:
if (c=='r')
setNextState(FOR);
else
setNextState(ID);
break;
case FOR:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case D:
if (c=='o')
setNextState(DO);
else
setNextState(ID);
break;
case DO:
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else if (c=='w')
setNextState(DOW);
else
setNextState(ID);
break;
case DOW:
if ((c=='n'))
setNextState(DOWN);
else
setNextState(ID);
break;
case DOWN:
if (c=='t')
setNextState(DOWNT);
else
setNextState(ID);
break;
case DOWNT:
if (c=='o')
setNextState(DOWNTO);
else
setNextState(ID);
break;
case DOWNTO :
if ((c==' ') || (c=='\n') || (c=='\0'))
setNextState(FINITE);
else
setNextState(ID);
break;
case ERROR:
setNextState(ERROR);
break;
case STOP:
setNextState(STOP);
break;
default:
setNextState(ERROR);
break;
}
}
LexAnalyser.h
#ifndef LEXANALYSER_H
#define LEXANALYSER_H
#include <QFile>
#include <QTextStream>
#include <QObject>
#include <QVector>
#include <QMap>
#include "LexFSM.h"
class LexAnalyser : public QObject
{
Q_OBJECT
public:
LexAnalyser(QObject* parent = 0);
void analyseNextCharacter(QChar c);