Главная страница

МУ_ЛР_ЛиПОАС. Методические указания по выполнению лабораторных работ по дисциплине (модулю) Лингвистическое и программное обеспечение автоматизированных систем


Скачать 2.76 Mb.
НазваниеМетодические указания по выполнению лабораторных работ по дисциплине (модулю) Лингвистическое и программное обеспечение автоматизированных систем
Дата12.04.2023
Размер2.76 Mb.
Формат файлаdoc
Имя файлаМУ_ЛР_ЛиПОАС.doc
ТипМетодические указания
#1057976
страница7 из 32
1   2   3   4   5   6   7   8   9   10   ...   32

2.4. Анализаторы для сложных рекурсивных грамматик


Следует заметить, что для более сложных случаев, когда в грамматике встречается рекурсия, т.е. какой-то нетерминальный символ определяется через самого себя, необходимо при нисходящем разборе создавать отдельные процедуры для обработки каждого такого символа. Скажем, язык целочисленных математических выражений со скобками и учетом приоритета операций определяется грамматикой:

{}

{}

|'('')'

 + | -

 * | /

(символ описывает грамматику целого числа и/или идентификатора и эквивалентен рассмотренному выше символу <Слагаемое>).

Здесь символ неявно описан рекурсивно: в его определение входит символ , в определение входит символ , а в определение - снова . Для реализации такого распознавателя нужно каждый нетерминальный символ выразить в виде отдельной процедуры.

Добавим в наш лексический анализатор возможность распознавания новых лексем:

public static string[] TLexemeType = { "NUMBER", "ID", "PLUS", "MINUS", "FINISH", "MUL", "DIVIDE", "LP", "RP"};

Здесь MUL соответствует символу "*", DIVIDE – символу "/", LP – "(", RP – ")". Изменения в самом лексическом анализаторе очень просты – надо лишь добавить четыре строчки в процедуру Run:

if (s[i] == '+') AddLex(3, 0, "+");

else if (s[i] == '-') AddLex(4, 0, "-");

else if ((char.IsLetter(s, i)) || (s[i] == '_')) ReadID();

else if (char.IsDigit(s, i)) ReadNumber();

else if (s[i] == '*') AddLex(6, 0, "*");

else if (s[i] == '/') AddLex(7, 0, "/");

else if (s[i] == '(') AddLex(8, 0, "(");

else if (s[i] == ')') AddLex(9, 0, ")");

else

{

Ferr = "Недопустимый символ в коде!";

break;

}

А вот синтаксический анализатор придется писать заново. Как и в примере с КА, создадим его как потомка класса TSyntaxAnalyzer. Метод Parse будет иметь в своём составе вложенные рекурсивно вызываемые процедуры, соответствующие нетерминальным символам:

string[] Operation2 = { "MUL", "DIVIDE" };

Tresult CurLex;

bool Flag = false;

public TSyntaxAnalyser3(Tresult[] Lexems) : base(Lexems) { } //Конструктор

public override void Parse()

{

while ((Error != "") | !Flag) TermF();

}

private void TermF()

{

CurLex = GetLex();

Expr();

if (Ferr != "") FerrPos = CurLex.position;

}

void Expr()

{

Term();

while (Array.IndexOf(Operation, CurLex.lexeme) != -1)

{

CurLex = GetLex();

Term();

}

}
void Term()

{

Factor();

while (Array.IndexOf(Operation2, CurLex.lexeme) != -1)

{

CurLex = GetLex();

Factor();

}

}

void Factor()

{

if (Array.IndexOf(item, CurLex.lexeme) != -1)

{

CurLex = GetLex();

Flag = true;

}

else

if (CurLex.lexeme == "LP")

{

CurLex = GetLex();

Expr();

if (CurLex.lexeme != "RP")

{

Ferr = "Непарные скобки";

FerrPos = CurLex.position;

Flag = true;

}

else CurLex = GetLex();

}

else

{

Ferr = "Синтаксическая ошибка!";

FerrPos = CurLex.position;

Flag = true;

}

}

}

Все процедуры (Expr, Term, Factor) описаны в полном соответствии с заданной грамматикой. Подобный анализатор корректно разбирает сложные выражения со вложенными скобками.

3. Задание на лабораторную работу


Разработать синтаксический анализатор для грамматики в соответствии с индивидуальным заданием лабораторной работы 1.

4. Ход работы (порядок выполнения работы)



1) Ознакомится теоретической справкой.

2) Разработать ПО для реализации задания.

3) Оформить отчет.

4) Защитить работу преподавателю.

1   2   3   4   5   6   7   8   9   10   ...   32


написать администратору сайта