Прямой лексический анализатор DPL
При разработке прямого лексического анализатора поступают очень просто: все правила, используемые в этой фазе, сваливают в одну кучу, после чего начинается их систематизация по группам, начинающихся с одинаковых начальных символов. Эти символы образуют набор альтернатив, анализируемых на первом шаге или, что одно и тоже, из начального состояния единого и плоского конечного автомата. Далее, аналогичный анализ осуществляется в каждой из подгрупп. При этом достаточно длинные правила можно оформлять как отдельные автоматы, что, в конце концов, приведет к созданию соответствующих процедур. Сформированный общий автомат, обеспечивающий прямой лексический анализ (представленный диаграммой Вирта), приведен на Рисунке 7.4.
Рисунок 7.4 Диаграммы Вирта, используемые для построения
Прямого лексического анализатора
Рисунок 7.4 Диаграммы Вирта, используемые для построения
Прямого лексического анализатора (продолжение)
Рисунок 7.4 Диаграммы Вирта, используемые для построения
Прямого лексического анализатора (окончание)
Программная реализация выглядит следующим образом:
//----------------------------------------------------------------
// Функция, формирующая следующую лексему
// Вызывается синтаксическим анализатором
//----------------------------------------------------------------
void nxl(void) {
do {
i_lv = -1;
lv[0] = '\0';
if(si == EOF) {lc = lexEof;}
else if(isSkip(si)) {nxsi(); lc = lexSkip;}
else if(isLetter(si) || si == '_'){
lv[++i_lv]=si; nxsi(); id_etc();
}
else if(isDigit(si)) {number();}
else if(isIgnore(si)) {nxsi(); lc = lexIgnore;}
else if(si == '/') {nxsi(); divcom();}
else if(si == '\"') {nxsi(); string_const();}
else if(si == ';') {nxsi(); lc = lexSemicolon;}
else if(si == ',') {nxsi(); lc = lexComma;}
else if(si == ':') {
nxsi();
if(si == '=') {nxsi(); lc = lexAssign;}
else lc = lexColon;
}
else if(si == '(') {nxsi(); lc = lexLftRndBr;}
else if(si == ')') {nxsi(); lc = lexRghRndBr;}
else if(si == '[') {nxsi(); lc = lexLftSqBr;}
else if(si == ']') {nxsi(); lc = lexRghSqBr;}
else if(si == '*') {nxsi(); lc = lexStar;}
else if(si == '%') {nxsi(); lc = lexPercent;}
else if(si == '+') {nxsi(); lc = lexPlus;}
else if(si == '-') {
nxsi();
if(si == '>') {nxsi(); lc = lexArrow;}
else lc = lexMinus;
}
else if(si == '=') {nxsi(); lc = lexEQ;}
else if(si == '!') {
nxsi();
if(si == '=') {nxsi(); lc = lexNE;}
else {lc = lexError; er(1);}
}
else if(si == '>') {
nxsi();
if(si == '=') {nxsi(); lc = lexGE;}
lc = lexGT;
}
else if(si == '<') {
nxsi();
if(si == '=') {nxsi(); lc = lexLE;}
lc = lexLT;
}
else if(si == '{') {nxsi(); prenumber();}
else if(si == '.') {lv[++i_lv]=si; nxsi(); fltnumber2();}
else {lc = lexError; er(0); nxsi();}
} while (lc == lexComment || lc == lexSkip || lc == lexIgnore);
}
При взятии для анализа и транслитерации следующего символа, не надо учитывать позицию в файле.
Диаграммы Вирта, описывающие отдельные подавтоматы прямого лексического анализатора, представлены на Рисунке 7.5. Их программную реализацию проще всего изучить на прилагаемых исходных текстах.
Рисунок 7.5 Диаграммы Вирта, описывающие отдельные крупные фрагменты правил прямого лексического анализатора
Примечание 1. Под остальными понимаются символы, не рассматриваемые непосредственно в текущей точке. В точке 1 – это не «*» и не конец файла; в точке 2 – это не «*», не конец файла и не «/».
Рисунок 7.5 Диаграммы Вирта, описывающие отдельные крупные фрагменты правил прямого лексического анализатора (продолжение)
Рисунок 7.5 Диаграммы Вирта, описывающие отдельные крупные фрагменты правил прямого лексического анализатора (окончание)