using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; public class LexicalAnalyzer { string except; // ошибка public int subroutineNumber = 0; public int label = 1; public int isLabeled = 0; // вспомогательные элементы для 3 лабы public int p = 0; // количество всп. переменных public int label1 = 0; // счетчик меток для условий public struct Element // описание элемента стека { public string operation; // операция public int count; // счетчик public int wParam; // старший параметр public int lParam; // младший параметр public Element(string oper, int cnt = -1, int oneParam = -1, int twoParam = -1) { this.operation = oper; this.count = cnt; this.wParam = oneParam; this.lParam = twoParam; } } public struct Operand // описание элемента стека { public string operand; // операция public int count; // счетчик public Operand(string oper, int cnt = -1) { this.operand = oper; this.count = cnt; } } public Dictionary priorities = new Dictionary(); // таблица приоритетов public void AddPriority() { priorities["R3"] = 0; priorities["R5"] = 0 ; priorities["O13"] = 0 ; priorities["W4"] = 0 ; priorities["AAE"] = 0 ; priorities["F"] = 0 ; priorities["DA"] = 0 ; priorities["DS"] = 0 ; priorities["R4"] = 1 ; priorities["R6"] = 1 ; priorities["O14"] = 1 ; priorities["W5"] = 1 ; priorities["R2"] = 1 ; priorities["R1"] = 1 ; priorities["O12"] = 2 ; priorities["W3"] = 2 ; priorities["UJ"] = 2 ; priorities["O8"] = 3 ; priorities["O9"] = 3 ; priorities["O6"] = 3 ; priorities["O7"] = 3 ; priorities["O10"] = 3 ; priorities["O11"] = 3 ; priorities["O1"] = 4 ; priorities["O2"] = 4 ; priorities["O3"] = 5 ; priorities["O4"] = 5 ; priorities["O5"] = 5 ; priorities["W1"] = 6 ; priorities["W2"] = 6; priorities["W3"] = 6; priorities["O15"] = 6; } public Stack myStack = new Stack(); // стек для перевода в ОПЗ по алгоритму Дейкстры public Stack ASMStack = new Stack(); // множество ключевых слов List KeyWords = new List(); public void AddKeyWords() { KeyWords.Add("sub"); KeyWords.Add("return"); KeyWords.Add("goto"); KeyWords.Add("if"); KeyWords.Add("else"); } // множество операций List Operations = new List(); public void AddOperations() { Operations.Add("+"); Operations.Add("-"); Operations.Add("*"); Operations.Add("/"); Operations.Add("**"); Operations.Add("<"); Operations.Add(">"); Operations.Add("=="); Operations.Add("!="); Operations.Add("<="); Operations.Add(">="); Operations.Add("="); Operations.Add("{"); Operations.Add("}"); Operations.Add(":"); } // множество разделителей List Delimeters = new List(); public void AddDelimeters() { Delimeters.Add(","); Delimeters.Add(";"); Delimeters.Add("("); Delimeters.Add(")"); Delimeters.Add("["); Delimeters.Add("]"); } public List Identifiers = new List(); public int NumberOfIdentifiers; // таблица идентификаторов public List NumberConstants = new List(); public int NumberOfNumberConstants; // таблица числовых констант public List SymbolConstants = new List(); public int NumberOfSymbolConstants; // таблица символьных констант public string Lexems; // входной текст public string Source; // выходной текст public string OPZ_Lexems; // выходной ОПЗ текст public string metka; public StreamReader sourceFile; // исходный файл public StreamWriter lexemsFile; // файл результата public StreamWriter OPZ_lexemsFile; // файл с ОПЗ результатом public StreamWriter ASM_File; public StreamReader OPZ_sourceFile; public LexicalAnalyzer(string pathToSource, string pathToLexemsFile) // открытие файлов { sourceFile = File.OpenText(pathToSource); lexemsFile = new StreamWriter(pathToLexemsFile); this.AddKeyWords(); this.AddOperations(); this.AddDelimeters(); } public bool Identifier(string IdentifierLexem) { NumberOfIdentifiers = Identifiers.Count; if (Identifiers.Contains(IdentifierLexem)) { Lexems = Lexems + "I" + (Identifiers.FindIndex((x) => x == IdentifierLexem)+1) + " "; lexemsFile.Write("I" + (Identifiers.FindIndex((x) => x == IdentifierLexem)+1) + " "); return true; } else { Identifiers.Add(IdentifierLexem); Lexems = Lexems + "I" + Identifiers.Count + " "; lexemsFile.Write("I" + Identifiers.Count + " "); return true; } } // поиск и добавление идентификаторов public bool KeyWord(string KeyWordLexem) { if (KeyWords.Contains(KeyWordLexem)) { Lexems = Lexems + "W" + (KeyWords.FindIndex((x) => x == KeyWordLexem) + 1) + " "; lexemsFile.Write("W" + (KeyWords.FindIndex((x) => x == KeyWordLexem) + 1) + " "); } else { this.Identifier(KeyWordLexem); return true; } return false; } // поиск ключевых слов public bool NumberConstant(string NumberConstantLexem) { NumberOfNumberConstants = NumberConstants.Count; if (NumberConstants.Contains(NumberConstantLexem)) { Lexems = Lexems + "N" + (NumberConstants.FindIndex((x) => x == NumberConstantLexem) + 1) + " "; lexemsFile.Write("N" + (NumberConstants.FindIndex((x) => x == NumberConstantLexem) + 1) + " "); return true; } else { NumberConstants.Add(NumberConstantLexem); Lexems = Lexems + "N" + NumberConstants.Count + " "; lexemsFile.Write("N" + NumberConstants.Count + " "); return true; } } // поиск и добавление числовых констант public bool SymbolConstant(string SymbolConstantLexem) { NumberOfSymbolConstants = SymbolConstants.Count; if (SymbolConstants.Contains(SymbolConstantLexem)) { Lexems = Lexems + "C" + (SymbolConstants.FindIndex((x) => x == SymbolConstantLexem)+1) + " "; lexemsFile.Write("C" + (SymbolConstants.FindIndex((x) => x == SymbolConstantLexem)+1) + " "); return true; } else { SymbolConstants.Add(SymbolConstantLexem); Lexems = Lexems + "C" + SymbolConstants.Count + " "; lexemsFile.Write("C" + SymbolConstants.Count + " "); return true; } } // поиск и добавление символьных констант public bool Operation(string OperationLexem) { if (Operations.Contains(OperationLexem)) { Lexems = Lexems + "O" + (Operations.FindIndex((x) => x == OperationLexem) + 1) + " "; lexemsFile.Write("O" + (Operations.FindIndex((x) => x == OperationLexem) + 1) + " "); return true; } else { return false; } } // поиск операций public bool Delimeter(string DelimeterLexem) { if (Delimeters.Contains(DelimeterLexem)) { if ((DelimeterLexem != "\n" & DelimeterLexem != "\r") & (DelimeterLexem != " ")) { Lexems = Lexems + "R" + (Delimeters.FindIndex((x) => x == DelimeterLexem) + 1) + " "; lexemsFile.Write("R" + (Delimeters.FindIndex((x) => x == DelimeterLexem) + 1) + " "); } else if (DelimeterLexem == "\n" || DelimeterLexem == "\r") { Lexems = Lexems + "\r\n"; lexemsFile.Write("\r\n"); } return true; } else { return false; } } // поиск разделителей public bool LexicalScanner() { string buffer; char ch; int terminate; ch = (char)sourceFile.Read(); terminate = 0; while (!sourceFile.EndOfStream) { buffer = ""; if (terminate == 1) { break; } if (ch == ' ') ch = (char)sourceFile.Read(); // Поиск идентификаторов if (ch == '$' || ch == '@' || ch == '&') { ch = (char)sourceFile.Read(); while ('A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z' || '0' <= ch && ch <= '9' || ch == '_') { buffer = buffer + ch; ch = (char)sourceFile.Read(); } this.Identifier(buffer); continue; } // Поиск ключевых слов и идентификаторов if ('A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z') { while ('A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z' || '0' <= ch && ch <= '9' || ch == '_') { buffer = buffer + ch; ch = (char)sourceFile.Read(); } if ('0' <= ch && ch <= '9' || ch == '_') { while ('A' <= ch && ch <= 'Z' || 'a' <= ch && ch <= 'z' || '0' <= ch && ch <= '9' || ch == '_') { buffer = buffer + ch; ch = (char)sourceFile.Read(); } this.Identifier(buffer); continue; } this.KeyWord(buffer); continue; } // Поиск числовых констант if (('0' <= ch && ch <= '9') || ch == '.') { while ('0' <= ch && ch <= '9') { buffer = buffer + ch; ch = (char)sourceFile.Read(); } if (ch == '.') { buffer = buffer + ch; ch = (char)sourceFile.Read(); if ('0' <= ch && ch <= '9') { while ('0' <= ch && ch <= '9') { buffer = buffer + ch; ch = (char)sourceFile.Read(); } if (ch == 'e' || ch == 'E') { buffer = buffer + ch; ch = (char)sourceFile.Read(); if (ch == '+' || ch == '-') { buffer = buffer + ch; ch = (char)sourceFile.Read(); while ('0' <= ch && ch <= '9') { buffer = buffer + ch; ch = (char)sourceFile.Read(); } } else if ('0' <= ch && ch <= '9') { while ('0' <= ch && ch <= '9') { buffer = buffer + ch; ch = (char)sourceFile.Read(); } } else { Lexems = Lexems + "ERRROOOOORR!!"; lexemsFile.Write("ERRROOOOORR!!"); break; } NumberConstant(buffer); continue; } else if (!Operations.Contains(Convert.ToString(ch)) && !Delimeters.Contains(Convert.ToString(ch))) { Lexems = Lexems + "ERRROOOOORR!!"; lexemsFile.Write("ERRROOOOORR!!"); break; } NumberConstant(buffer); continue; } else if (!Operations.Contains(Convert.ToString(ch)) && !Delimeters.Contains(Convert.ToString(ch))) { Lexems = Lexems + "ERRROOOOORR!!"; lexemsFile.Write("ERRROOOOORR!!"); break; } } else if (!Operations.Contains(Convert.ToString(ch)) && !Delimeters.Contains(Convert.ToString(ch))) { Lexems = Lexems + "ERRROOOOORR!!"; lexemsFile.Write("ERRROOOOORR!!"); break; } NumberConstant(buffer); continue; } // Поиск символьных и строковых констант if (ch == '\'' || ch == '"') { while (true) { ch = (char)sourceFile.Read(); if (ch == '\n' || ch == '\r') { Lexems = Lexems + "ERRROOOOORR!!"; lexemsFile.Write("ERRROOOOORR!!"); terminate = 1; break; } if (ch == '\'' || ch == '"') { ch = (char)sourceFile.Read(); if (ch != '\'' && ch != '"') { SymbolConstant(buffer); break; } else { buffer = buffer + ch; } } buffer = buffer + ch; } continue; } // обработка операций и разделителей if (ch == '+' || ch == '-' || ch == '/' || ch == ':' || ch == '{' || ch == '}' || ch == ',' || ch == ';' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == '\n' || ch == '\r') { buffer = buffer + ch; if (Operations.Contains(buffer)) { Operation(buffer); ch = (char)sourceFile.Read(); continue; } else if (ch == '\n') { Lexems = Lexems + "\r\n"; lexemsFile.Write("\r\n"); ch = (char)sourceFile.Read(); continue; } else if (Delimeters.Contains(buffer)) { Delimeter(buffer); ch = (char)sourceFile.Read(); continue; } } // двулитерные операции if (ch == '=' || ch == '!' || ch == '<' || ch == '>') { buffer = buffer + ch; ch = (char)sourceFile.Read(); if (ch == '=') { buffer = buffer + ch; Operation(buffer); ch = (char)sourceFile.Read(); continue; } Operation(buffer); continue; } if (ch == '*') { buffer = buffer + ch; ch = (char)sourceFile.Read(); if (ch == '*') // что делать если ввели *= ? ошибка? { buffer = buffer + ch; Operation(buffer); ch = (char)sourceFile.Read(); continue; } Operation(buffer); //ch = (char)sourceFile.Read(); continue; } // комментарии if (ch == '#') { ch = (char)sourceFile.Read(); while (ch != '\n') { ch = (char)sourceFile.Read(); } continue; } if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t') { ch = (char)sourceFile.Read(); continue; } } lexemsFile.Close(); sourceFile.Close(); return true; } /// /// Метод выполняющий алгоритм перевода исходной программы в ОПЗ /// /// /// /// public bool ConvertToOPZ(string pathToSourceLexems, string pathToOPZ_LexemsFile) { OPZ_lexemsFile = new StreamWriter(pathToOPZ_LexemsFile); OPZ_sourceFile = File.OpenText(pathToSourceLexems); AddPriority(); string currentElem = ""; // текущий элемент string lastElem; // элемент, находящийся в вершине стека bool mayUnaty = false; // char ch = (char)OPZ_sourceFile.Read(); while (!OPZ_sourceFile.EndOfStream) { string buffer = ""; lastElem = currentElem; if (ch == ' ' || ch == '\\' || ch == 'r' || ch == 'n') ch = (char)OPZ_sourceFile.Read(); while (ch != ' ' && ch != '\\' && ch != 'r' && ch != 'n') { if (ch != '\n' && ch != '\r') { buffer = buffer + ch; } ch = (char)OPZ_sourceFile.Read(); } currentElem = buffer; currentElem.Trim('\n','\r'); if (currentElem[0] == 'O' || currentElem[0] == 'R' || currentElem[0] == 'W') { // обработка операции разделения операций if (currentElem == "R2") { T_Semicolon(); } // обработка запятой else if (currentElem == "R1") { T_Comma(); } // обработка двоеточия else if (currentElem == "O15") { T_Colon(lastElem); } // обработка открывающей круглой скобки else if (currentElem == "R3") { T_OpeningParenthesis(currentElem, lastElem); //TODO: mayUnary mayUnaty = true; } // обработка закрывающей круглой скобки else if (currentElem == "R4") { T_ClosingParenthesis(); //TODO: mayUnary mayUnaty = false; } // обработка [ скобоки else if (currentElem == "R5") { T_OpeningSquareBracket(); } // обработка ] скобоки else if (currentElem == "R6") { T_ClosingSquareBracket(); } // обработка объявления подпрограмм else if (currentElem == "W1") { T_DeclarationSubprogram(currentElem); } // обработка открывающей операторной скобоки else if (currentElem == "O13") { T_OpeningOperatorBracket(currentElem); } // обработка закрывающей операторной скобоки else if (currentElem == "O14") { T_ClosingOperatorBracket(); } // обработка условного оператора else if (currentElem == "W4" || currentElem == "W5") { T_ConditionalOperator(currentElem); } // обработка безусловного перехода (goto) else if (currentElem == "W3") { Element elem = new Element("UJ"); myStack.Push(elem); } // обработка операций else { if (mayUnaty) { if (currentElem == "O1") { currentElem = "O1"; } else { currentElem = "O2"; } } T_Operation(currentElem); mayUnaty = true; } } else { OPZ_Lexems = Lexems + currentElem + " "; OPZ_lexemsFile.Write(currentElem + " "); mayUnaty = false; } buffer = ""; } T_FlushStack(); OPZ_lexemsFile.Close(); OPZ_sourceFile.Close(); return true; } /// /// Проверка лексемы на принадлежность к классу операций /// /// /// public bool IsOperation(string OperationLexem) { if (Operations.Contains(OperationLexem)) { return true; } return false; } /// /// Обработка операций /// /// /// public bool T_Operation(string currentElem) { string lastOper; // элемент, находящийся в вершине стека if (myStack.Count != 0) { lastOper = myStack.Peek().operation; while (priorities[lastOper] >= priorities[currentElem]) { OPZ_Lexems = Lexems + lastOper + " "; OPZ_lexemsFile.Write(lastOper + " "); myStack.Pop(); if (myStack.Count == 0) { except = "Стек пуст!"; return false; } lastOper = myStack.Peek().operation; } } Element el = new Element(currentElem); myStack.Push(el); return true; } /// /// Обработка открывающей скобки /// /// /// /// public bool T_OpeningParenthesis(string currentElem, string lastElem) { if (myStack.Count != 0) { Element sub = myStack.Peek(); if (lastElem[0] == 'O') { Element el = new Element(currentElem); myStack.Push(el); } else if (sub.operation != "W1" && lastElem != "W4") { Element el = new Element("F", 1); myStack.Push(el); } else if (lastElem == "W4") { Element el = new Element(currentElem); myStack.Push(el); } } else if (lastElem[0] == 'I') { Element el = new Element("F", 1); myStack.Push(el); } else if (lastElem == "W4") { Element el = new Element(currentElem); myStack.Push(el); } return true; } /// /// Обработка закрывающей скобки /// /// public bool T_ClosingParenthesis() { string lastOper = ""; // элемент, находящийся в вершине стека if (myStack.Count != 0) lastOper = myStack.Peek().operation; if (lastOper == "W1") { OPZ_Lexems = Lexems + subroutineNumber + " " + myStack.Peek().lParam + " НП " + Environment.NewLine; OPZ_lexemsFile.Write(subroutineNumber + " " + myStack.Peek().lParam + " НП " + Environment.NewLine); //myStack.Pop(); } while(lastOper != "R3" && lastOper != "F" && lastOper != "W1") { OPZ_Lexems = Lexems + lastOper + " "; OPZ_lexemsFile.Write(lastOper + " "); if (myStack.Count != 0) myStack.Pop(); else break; if (myStack.Count != 0) lastOper = myStack.Peek().operation; else break; } if(lastOper == "F") { OPZ_Lexems = Lexems + Convert.ToString(myStack.Peek().count + 1) + " " + myStack.Peek().operation + " "; OPZ_lexemsFile.Write(Convert.ToString(myStack.Peek().count + 1) + " " + myStack.Peek().operation + " "); } if (myStack.Count != 0) if (myStack.Peek().operation != "W1") myStack.Pop(); return true; } /// /// Обработка открывающей квадратной скобки /// /// public bool T_OpeningSquareBracket() { if (myStack.Count != 0 ) { if (myStack.Peek().operation == "DA") { } else { Element el = new Element("AAE", 2); myStack.Push(el); } } else { Element el = new Element("AAE", 2); myStack.Push(el); } return true; } /// /// Обработка закрывающей квадратной скобки /// /// public bool T_ClosingSquareBracket() { string lastOper; // элемент, находящийся в вершине стека lastOper = myStack.Peek().operation; while(lastOper != "AAE" && lastOper != "DA") { OPZ_Lexems = Lexems + lastOper + " "; OPZ_lexemsFile.Write(lastOper + " "); myStack.Pop(); lastOper = myStack.Peek().operation; } OPZ_Lexems = Lexems + Convert.ToString(myStack.Peek().count) + " " + myStack.Peek().operation + " "; OPZ_lexemsFile.Write(Convert.ToString(myStack.Peek().count) + " " + myStack.Peek().operation + " "); myStack.Pop(); return true; } /// /// Обработка запятой /// /// public bool T_Comma() { string lastOper; // элемент, находящийся в вершине стека if (myStack.Count == 0) return false; lastOper = myStack.Peek().operation; while(lastOper != "AAE" && lastOper != "F" && lastOper != "DA") { OPZ_Lexems = Lexems + lastOper + " "; OPZ_lexemsFile.Write(lastOper + " "); myStack.Pop(); if (myStack.Count != 0) lastOper = myStack.Peek().operation; else break; } if (myStack.Count != 0) { Element el = new Element(); el = myStack.Pop(); ++el.count; myStack.Push(el); } return true; } /// /// Обработка точки с запятой /// /// public bool T_Semicolon() { string lastOper; // элемент, находящийся в вершине стека try { if(myStack.Count == 0) { except = "Стек пуст!"; return false; } lastOper = myStack.Peek().operation; while(lastOper != "O13" && lastOper != "W4" && lastOper != "W1" && lastOper != "DS") { OPZ_Lexems = Lexems + lastOper + " "; OPZ_lexemsFile.Write(lastOper + " ");; myStack.Pop(); if(myStack.Count == 0) { except = "Стек пуст!"; return false; } lastOper = myStack.Peek().operation; } } catch { throw; } if(lastOper == "W4") { Element label = new Element(); label = myStack.Peek(); while (label.operation == "W4") { OPZ_Lexems = Lexems + "L" + label.count + " : "; OPZ_lexemsFile.Write("L" + label.count + " : "); isLabeled = 1; myStack.Pop(); if (myStack.Count == 0) break; label = myStack.Peek(); } } else if(lastOper == "W1") { // данные беруться из оператора procedure или program Element title = myStack.Peek(); // вывод количество операндов, номер подпрограммы, уровень подпрограммы OPZ_Lexems = Lexems + title.count + " " + title.wParam + " " + title.lParam + " SS " + Environment.NewLine; OPZ_lexemsFile.Write(title.count + " " + title.wParam + " " + title.lParam + " SS " + Environment.NewLine); myStack.Pop(); if (lastOper == "W1") { Element elem = new Element("DS", -1, title.wParam, title.lParam); myStack.Push(elem); } } else if(lastOper == "DS") { OPZ_Lexems = Lexems + "ES "; OPZ_lexemsFile.Write("ES "); myStack.Pop(); } return true; } /// /// Обработка открывающей операторной скобки /// /// /// public bool T_OpeningOperatorBracket(string currentElem) { Element elem = new Element(currentElem); Element elif = new Element("W4"); if (myStack.Contains(elif)) { this.T_ConditionalOperator("O13"); } if (myStack.Count != 0 && myStack.Peek().operation != "W4") { Element el = new Element(); el = myStack.Peek(); //OPZ_Lexems = Lexems + el.wParam + " " + el.lParam + " ED " + Environment.NewLine; //OPZ_lexemsFile.Write(el.wParam + " " + el.lParam + " ED " + Environment.NewLine); } myStack.Push(elem); return true; } /// /// Обработка закрывающей операторной скобки /// /// public bool T_ClosingOperatorBracket() { Element lastOper = new Element(); // элемент, находящийся в вершине стека if (myStack.Count != 0) { lastOper = myStack.Peek(); while (lastOper.operation != "O13") // выталкивает все операции в вых. послед, пока не встретим "(" или "F" { if (lastOper.operation == "W4") { OPZ_Lexems = Lexems + "L" + lastOper.count + " : "; OPZ_lexemsFile.Write("L" + lastOper.count + " : "); isLabeled = 1; } else { if (lastOper.operation != "W1") { OPZ_Lexems = Lexems + lastOper.operation + " "; OPZ_lexemsFile.Write(lastOper.operation + " "); } else if (lastOper.operation == "W1") { OPZ_Lexems = Lexems + "КП "; OPZ_lexemsFile.Write("КП "); } } if (myStack.Count != 0) myStack.Pop(); if (myStack.Count != 0) lastOper = myStack.Peek(); } Element back = myStack.Pop(); if (myStack.Count != 0 && myStack.Peek().operation == "W1") { OPZ_Lexems = Lexems + "КП "; OPZ_lexemsFile.Write("КП "); if (myStack.Count != 0) myStack.Pop(); } myStack.Push(back); myStack.Pop(); } else { } return true; } /// /// Обработка условного оператора /// /// /// public bool T_ConditionalOperator(string currentElem) { Element lastOper = new Element(); // элемент, находящийся в вершине стека // отвечает за раздачу меток if(currentElem == "W4") { Element elem = new Element(currentElem); myStack.Push(elem); isLabeled = 0; } else if(currentElem == "W5" || currentElem == "O13") { lastOper = myStack.Peek(); while (lastOper.operation != "W4") { OPZ_Lexems = Lexems + lastOper.operation + " "; OPZ_lexemsFile.Write(lastOper.operation + " "); myStack.Pop(); lastOper = myStack.Peek(); } if (currentElem == "O13") { Element elem = new Element(); elem = myStack.Pop(); elem.count = label; myStack.Push(elem); OPZ_Lexems = Lexems + "L" + label + " УПЛ "; OPZ_lexemsFile.Write("L" + label + " УПЛ "); label += 2; } else { if (lastOper.operation == "W4" && lastOper.count % 2 == 0) { // завершился вложенный полный условный оператор OPZ_Lexems = Lexems + "L" + lastOper.count + " : "; OPZ_lexemsFile.Write("L" + lastOper.count + " : "); isLabeled = 1; myStack.Pop(); } Element elem = new Element(); elem = myStack.Pop(); ++elem.count; myStack.Push(elem); OPZ_Lexems = Lexems + "L" + myStack.Peek().count + " БП L" + Convert.ToString(myStack.Peek().count - 1) + " : "; OPZ_lexemsFile.Write("L" + myStack.Peek().count + " БП L" + Convert.ToString(myStack.Peek().count - 1) + " : "); isLabeled = 1; } } return true; } /// /// Обработка объявления подпрограмм /// /// /// public bool T_DeclarationSubprogram(string currentElem) { Element elem; int subroutineLevel = 1; // уровень подпрограммы if (myStack.Count != 0) { Element back = myStack.Pop(); if (myStack.Count() != 0) { Element lastOper = myStack.Peek();// элемент находящийся в вершине стека ++subroutineNumber; //OPZ_Lexems = Lexems + subroutineNumber + " " + lastOper.lParam + " ED " + Environment.NewLine; //OPZ_lexemsFile.Write(subroutineNumber + " " + lastOper.lParam + " ED " + Environment.NewLine); subroutineLevel = lastOper.lParam + 1; myStack.Push(back); elem = new Element(currentElem, 1, subroutineNumber, subroutineLevel); } else { ++subroutineNumber; //OPZ_Lexems = Lexems + subroutineNumber + " " + "1" + " ED " + Environment.NewLine; //OPZ_lexemsFile.Write(subroutineNumber + " " + "1" + " ED " + Environment.NewLine); elem = new Element(currentElem, 1, subroutineNumber, 1); } } else { ++subroutineNumber; //OPZ_Lexems = Lexems + subroutineNumber + " " + "1" + " ED " + Environment.NewLine; //OPZ_lexemsFile.Write(subroutineNumber + " " + "1" + " ED " + Environment.NewLine); elem = new Element(currentElem, 1, subroutineNumber, 1); } myStack.Push(elem); return true; } /// /// Обработка двоеточия /// /// /// public bool T_Colon(string lastElem) { //Element lastOper = myStack.Peek(); OPZ_Lexems = Lexems + ": "; OPZ_lexemsFile.Write(": "); return true; } public bool T_FlushStack() { while(myStack.Count != 0) { if (myStack.Peek().operation == "W4") { OPZ_Lexems = Lexems + "L" + myStack.Peek().count + " : "; OPZ_lexemsFile.Write("L" + myStack.Peek().count + " : "); myStack.Pop(); } else { OPZ_Lexems = Lexems + myStack.Peek().operation + " "; OPZ_lexemsFile.Write(myStack.Peek().operation + " "); myStack.Pop(); } } return true; } public bool ConvertToASM(string pathToSourceLexemsOPZ, string pathToASMFile) { ASM_File = new StreamWriter(pathToASMFile); OPZ_sourceFile = File.OpenText(pathToSourceLexemsOPZ); string currentElem = ""; // текущий элемент string lastElem; // элемент, находящийся в вершине стека string tmp; int num; // для проверки на тип char ch = (char)OPZ_sourceFile.Read(); StartProgram(); InitializeVariables(); while (!OPZ_sourceFile.EndOfStream) { string buffer = ""; lastElem = currentElem; if (ch == ' ' || ch == '\\' || ch == 'r' || ch == 'n') ch = (char)OPZ_sourceFile.Read(); while (ch != ' ' && ch != '\\' && ch != 'r' && ch != 'n') { if (ch != '\n' && ch != '\r') { buffer = buffer + ch; } ch = (char)OPZ_sourceFile.Read(); } currentElem = buffer; currentElem.Trim('\n', '\r'); if (currentElem[0] != 'N' && currentElem[0] != 'I' && currentElem[0] != 'C' && currentElem[0] != 'L' && !int.TryParse(currentElem, out num)) { // обработка арифметических операций if (currentElem == "O1" || currentElem == "O2" || currentElem == "O3" || currentElem == "O4" || currentElem == "O5") { ArithmeticOperations(currentElem); } // обработка оператора присваивания else if (currentElem == "O12") { Assignment(); } // обработка безусловного перехода else if (currentElem == "БП" || currentElem == "UJ") { UnconditionalJump(); } // обработка операции метки else if (currentElem == ":") { OperationLabel(); } // обработка операций отношения else if (currentElem == "O6" || currentElem == "O7" || currentElem == "O10" || currentElem == "O11" || currentElem == "O8" || currentElem == "O9") { RelationalOperators(currentElem); } // обработка перехода по значени ложь else if (currentElem == "УПЛ") { JumpByValueLie(); } // обработка вызова подпрограммы else if (currentElem == "F") { SubroutineCall(); } // обработка заголовка подпрограммы else if (currentElem == "НП") { StartSubroutine(); } // обработка операции "КП" else if (currentElem == "КП") { EndSubroutine(); } else if (currentElem == "AAE") { Arrays(); } } else { if (currentElem[0] == 'N') { tmp = currentElem.Remove(0,1); Operand elem = new Operand(NumberConstants[Convert.ToInt32(tmp) - 1]); ASMStack.Push(elem); } if (currentElem[0] == 'I') { tmp = currentElem.Remove(0, 1); Operand elem = new Operand(Identifiers[Convert.ToInt32(tmp) - 1]); ASMStack.Push(elem); } if (currentElem[0] == 'C') { tmp = currentElem.Remove(0, 1); Operand elem = new Operand("\"" + SymbolConstants[Convert.ToInt32(tmp) - 1] + "\""); ASMStack.Push(elem); } if (currentElem[0] == 'L') { Operand elem = new Operand(currentElem); ASMStack.Push(elem); } if (int.TryParse(currentElem, out num)) { Operand elem = new Operand(currentElem); ASMStack.Push(elem); } } buffer = ""; } ASM_File.Close(); OPZ_sourceFile.Close(); return true; } public void StartProgram() { ASM_File.Write(".model small" + Environment.NewLine); ASM_File.Write(".386" + Environment.NewLine); ASM_File.Write("locals __" + Environment.NewLine); ASM_File.Write("stack 100h" + Environment.NewLine + Environment.NewLine); } public void InitializeVariables() { int i; for (i = 0; i < Identifiers.Count; i++) { ASM_File.Write(Identifiers[i] + " dd ?" + Environment.NewLine); } ASM_File.Write(Environment.NewLine); } public void ArithmeticOperations(string currentElem) { string operand1; // string operand2; // //TODO: переписать сократив число обращений к стеку с использованием tmp operand2 = ASMStack.Peek().operand; if(operand2 == "R") operand2 += Convert.ToString(ASMStack.Peek().count); ASMStack.Pop(); operand1 = ASMStack.Peek().operand; if(operand1 == "R") operand1 += Convert.ToString(ASMStack.Peek().count); ASMStack.Pop(); if(operand1[0] != 'R' && operand2[0] != 'R') ++p; if(operand1[0] == 'R' && operand2[0] == 'R') --p; ASM_File.Write("mov AX, " + operand1 + Environment.NewLine); if(currentElem == "O1") { ASM_File.Write("add AX, " + operand2 + Environment.NewLine); } else if(currentElem == "O2") { ASM_File.Write("sub AX, " + operand2 + Environment.NewLine); } else if(currentElem == "O3") { ASM_File.Write("mul " + operand2 + Environment.NewLine); } else if(currentElem == "O4") { ASM_File.Write("div " + operand2 + Environment.NewLine); } // TODO: РЕАЛИЗОВАТЬ ВОЗВЕДЕНИЕ В СТЕПЕНЬ ASM_File.Write("mov R" + Convert.ToString(p) + ", AX" + Environment.NewLine); ASMStack.Push(new Operand("R", p)); } public void Assignment() { string operand1; // string operand2; // operand2 = ASMStack.Peek().operand; if(operand2 == "R") { operand2 += Convert.ToString(ASMStack.Peek().count); --p; } ASMStack.Pop(); operand1 = ASMStack.Peek().operand; ASMStack.Pop(); ASM_File.Write("mov AX, " + operand2 + Environment.NewLine); ASM_File.Write("mov " + operand1 + ", AX" + Environment.NewLine); } public void UnconditionalJump() { ASM_File.Write("jmp " + ASMStack.Peek().operand + Environment.NewLine); ASMStack.Pop(); } public void OperationLabel() { ASM_File.Write(ASMStack.Peek().operand + ": " + Environment.NewLine); ASMStack.Pop(); } public void RelationalOperators(string currentElem) { // счетчик меток string operand1; // string operand2; // operand2 = ASMStack.Peek().operand; ASMStack.Pop(); operand1 = ASMStack.Peek().operand; ASMStack.Pop(); ++p; ++label1; ASM_File.Write("mov R" + p + ", 1" + Environment.NewLine); ASM_File.Write("mov AX, " + operand1 + Environment.NewLine); ASM_File.Write("cmp AX, " + operand2 + Environment.NewLine); if(currentElem == "O6") { ASM_File.Write("jl LABEL" + label1 + " " + Environment.NewLine); } else if(currentElem == "O10") { ASM_File.Write("jle LABEL" + label1 + " " + Environment.NewLine); } else if(currentElem == "O7") { ASM_File.Write("jg LABEL" + label1 + " " + Environment.NewLine); } else if(currentElem == "O11") { ASM_File.Write("jge LABEL" + label1 + " " + Environment.NewLine); } else if(currentElem == "O8") { ASM_File.Write("je LABEL" + label1 + " " + Environment.NewLine); } else if(currentElem == "O9") { ASM_File.Write("jne LABEL" + label1 + " " + Environment.NewLine); } ASM_File.Write("mov R" + p + ", 0" + Environment.NewLine); ASM_File.Write("LABEL" + label1 + ": "); ASMStack.Push(new Operand("R", p)); } public void JumpByValueLie() { string operand1; // string operand2; // operand2 = ASMStack.Peek().operand; ASMStack.Pop(); operand1 = ASMStack.Peek().operand + Convert.ToString(ASMStack.Peek().count); ASMStack.Pop(); --p; ASM_File.Write("test " + operand1 + ", 1" + Environment.NewLine); ASM_File.Write("je " + operand2 + Environment.NewLine); } public void SubroutineCall() { int qtyArg; // количество аргументов string tmp; qtyArg = Convert.ToInt32(ASMStack.Peek().operand); ASMStack.Pop(); for(int i = 0; i < qtyArg - 1; i++) { tmp = ASMStack.Peek().operand; if(tmp == "R") tmp += Convert.ToString(ASMStack.Peek().count); ASMStack.Pop(); ASM_File.Write("push " + tmp + Environment.NewLine); } ASM_File.Write("call " + ASMStack.Peek().operand + Environment.NewLine); if (ASMStack.Count != 0) { Operand back = ASMStack.Pop(); /*if (ASMStack.Count != 0) { ASM_File.Write("mov " + ASMStack.Peek().operand + ", EAX" + Environment.NewLine); } */ back.operand = "EAX"; ASMStack.Push(back); } //TODO: доработать случай функции } public void StartSubroutine() { ASMStack.Pop(); ASMStack.Pop(); ASM_File.Write(ASMStack.Peek().operand + " proc" + Environment.NewLine); } public void EndSubroutine() { ASM_File.Write("ret;" + Environment.NewLine); ASM_File.Write(ASMStack.Peek().operand + " endp;" + Environment.NewLine); ASMStack.Pop(); } public void Arrays() { int array_level = Convert.ToInt32(ASMStack.Pop().operand); int metka_level = p; int index,i; if (ASMStack.Peek().count != -1) ASM_File.Write("mov BX, " + ASMStack.Peek().operand + ASMStack.Pop().count + Environment.NewLine); else ASM_File.Write("mov BX, " + ASMStack.Peek().operand + Environment.NewLine); i = array_level - 1; metka_level--; for (; i > 1; i-- , metka_level--) { if (ASMStack.Peek().count != -1) ASM_File.Write("add BX, " + ASMStack.Peek().operand + ASMStack.Pop().count + Environment.NewLine); else ASM_File.Write("add BX, " + ASMStack.Peek().operand + Environment.NewLine); } if (ASMStack.Count > 1) ASMStack.Pop(); Operand back = new Operand(ASMStack.Pop().operand + "[BX]"); ASMStack.Push(back); } }