Отчет по лабораторной работе 5 Выполнил студент группы 220272 Хавренко В. С. Проверил доцент, к т. н. Волошко А. Г
Скачать 71.94 Kb.
|
МИНОБРНАУКИ РОССИИ Федеральное государственное бюджетное образовательное учреждение высшего образования "Тульский государственный университет" Институт прикладной математики и компьютерных наук Кафедра вычислительной техники Лингвистическое и программное обеспечение автоматизированных систем ОТЧЕТ ПО ЛАБОРАТОРНОЙ РАБОТЕ № 5 Выполнил студент группы 220272 Хавренко В.С. Проверил доцент, к.т.н. Волошко А.Г. Тула 2021 Цель работы Научиться создавать синтаксические анализаторы. Задачи работы Разработать синтаксический анализатор грамматики в соответствии с индивидуальным заданием. Индивидуальное задание: Описать язык арифметических выражений в префиксной форме с операциями сложения, вычитания, умножения, деления без скобок, с операндами в форме идентификаторов. Ход работы Синтаксический анализатор производит анализ арифметических выражений в префиксной форме с операциями сложения, вычитания, умножения, деления без скобок, с операндами в форме идентификаторов. Анализатор проверяет правильность написания текста в соответствии с правилом грамматики. На рисунках 1-5 представлен результат работы программы. Рисунок 1 – Правильный ввод Рисунок 2 – Отсутствует знак Рисунок 3 – Ошибка нехватки идентификаторов Рисунок 4 – Ошибка перебора идентификаторов Рисунок 5 – Ошибка разделения Листинг программы Листинг 1 - program.cs using System; namespace ConsoleApp1 { public struct Result { public string lexeme; public string name; public int position; } public class LexicalAnalyzer { public static string[] lexemeType = { "ID", "SIGN", "FINISH", "|_|" }; private string error; private Result[] lexemes; string s = ""; int i; public LexicalAnalyzer() { error = ""; lexemes = new Result[0]; } public String Error { get { return error; } } public Result[] Lexemes { get { return lexemes; } } public void AddLexeme(byte LexemeType, string name, int position) { Array.Resize(ref lexemes, lexemes.Length + 1); lexemes[lexemes.Length - 1].lexeme = lexemeType[LexemeType - 1]; lexemes[lexemes.Length - 1].name = name; lexemes[lexemes.Length - 1].position = position; } public void ReadNUM(int start_pos) { string num = ""; do { num += s[i]; i++; } while ((i < s.Length) && (char.IsLetterOrDigit(s, i))); AddLexeme(1, num, start_pos); i--; } public void Run(string Data) { s = Data; Array.Resize(ref lexemes, 0); error = ""; for (i = 0; i <= s.Length - 1; i++) { if (s[i] == '+') AddLexeme(2, "+", i); else if (s[i] == '-') AddLexeme(2, "-", i); else if (s[i] == '*') AddLexeme(2, "*", i); else if (s[i] == '/') AddLexeme(2, "/", i); else if (s[i] == ' ') Console.Write(""); //else if (char.IsLetterOrDigit(s, i)) AddLexeme(1, Convert.ToString(s[i]), i); else if (char.IsLetterOrDigit(s, i)) ReadNUM(i); else { error = "Error at pos " + i + ": symbol '" + s[i] + "' is unacceptable."; break; } } AddLexeme(3, "", i); } } class Program { static void Main(string[] args) { string input = Console.ReadLine(); LexicalAnalyzer lexicalAnalyzer = new LexicalAnalyzer(); lexicalAnalyzer.Run(input); Console.WriteLine("Лексический анализ\n"); Console.WriteLine("Input: {0}\n", input); foreach (var lexeme in lexicalAnalyzer.Lexemes) { Console.WriteLine("{0} at {1}: {2}", lexeme.lexeme, lexeme.position, lexeme.name); } if (lexicalAnalyzer.Error != "") Console.WriteLine(lexicalAnalyzer.Error); Console.WriteLine("\n"); Console.WriteLine("Синтаксический анализ\n"); TSyntaxAnalyzer SyntaxAnalyzer3 = new TSyntaxAnalyzer(lexicalAnalyzer.Lexemes); SyntaxAnalyzer3.Parse(); Console.ReadLine(); } } } Листинг 2 - класса TSyntaxAnalyzer.cs using System; namespace ConsoleApp1 { partial class TSyntaxAnalyzer { public string Ferr; //Сообщение об ошибке public string Ferr1; //Сообщение об ошибке public string Ferr2; //Сообщение об ошибке public ushort FerrPos; //Позиция ошибки во входной строке private Result[] Flex; //Входной массив лексем после лексического разбора private Int32 Count; //Номер текущей лексемы public ushort ErrorPos { get { return FerrPos; } } public String Error { get { return Ferr; } } public TSyntaxAnalyzer(Result[] Lexems) //Конструктор { Ferr = ""; Ferr1 = ""; Ferr2 = ""; FerrPos = 0; Flex = Lexems; Count = 0; } public int sign = 0; public int id = 0; public Result GetLex() { if (Count <= Flex.Length - 1) { Count++; return Flex[Count - 1]; } else { Result FinishRes; FinishRes.lexeme = "FINISH"; FinishRes.name = ""; FinishRes.position = 0; return FinishRes; } } public virtual void Parse() { string[] Operation = { "SIGN" }, item = { "ID" }, item2 = { "|_|" }; Result Curlex = GetLex(); do { link1: if (Array.IndexOf(Operation, Curlex.lexeme) != -1) { Curlex = GetLex(); sign = sign + 1; goto link1; } else { if (Array.IndexOf(item, Curlex.lexeme) != -1 || Array.IndexOf(item2, Curlex.lexeme) !=- 1) { if (sign != 0) { goto link2; } } Ferr = "Синтаксическая ошибка. Знаки спереди!"; FerrPos = (ushort)Curlex.position; Console.WriteLine("{0}, {1}", FerrPos, Ferr); Console.ReadLine(); goto link2; } link2: do { if (Array.IndexOf(item2, Curlex.lexeme) != -1) { Curlex = GetLex(); } else if (Array.IndexOf(item, Curlex.lexeme) != -1) { if (sign >= id+1) { Curlex = GetLex(); id = id + 1; } else { Ferr = "Синтаксическая ошибка. Слишком много идентификаторов!"; FerrPos = (ushort)Curlex.position; Console.WriteLine("{0}, {1}", FerrPos, Ferr); Console.ReadLine(); break; } } else if (Array.IndexOf(Operation, Curlex.lexeme) != -1) { Ferr = "Синтаксическая ошибка. Ожидалось разделение"; FerrPos = (ushort)Curlex.position; Console.WriteLine("{0}, {1}", FerrPos, Ferr); Console.ReadLine(); break; } } while (Curlex.lexeme != "FINISH"); } while (Curlex.lexeme != "FINISH"); if (sign > id) { Ferr = "Синтаксическая ошибка. Слишком мало идентификаторов!"; FerrPos = (ushort)Curlex.position; Console.WriteLine("{0}, {1}", FerrPos, Ferr); } if (sign == id) { Console.WriteLine("Ошибки не обнаружены"); } Console.ReadLine(); //Console.WriteLine("OK"); } } } |