МУ_ЛР_ЛиПОАС. Методические указания по выполнению лабораторных работ по дисциплине (модулю) Лингвистическое и программное обеспечение автоматизированных систем
Скачать 2.76 Mb.
|
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) Защитить работу преподавателю. |