Роектирование модуля интерпретации
На начальном этапе реализации константы (CONSTANTS) и переменные (IDENTIFIES) кладутся в формируемую запись в порядке их появления в исходном массиве.
s1.Push(CONSTANTS[CounterConstants++]);
s1.Push(IDENTIFIES[CounterIdentifies++]);
При появлении операции в исходном массиве:
a. если в стеке нет операций или верхним элементом стека является открывающая скобка, операции кладётся в стек
if (operations.Peek() == "16" || operations.Peek() == "00")
{
operations.Push(TokensStack.Pop());
break;
}
if (TokensStack.Peek() == "16") // (
{
operations.Push(TokensStack.Pop());
break;
}
b. если новая операция имеет больший приоритет, чем верхняя операции в стеке, то новая операции кладётся в стек
if (Convert.ToInt32(TokensStack.Peek()) > Convert.ToInt32(operations.Peek()))
{
operations.Push(TokensStack.Pop());
}
c. если новая операция имеет меньший или равный приоритет, чем верхняя операции в стеке, то операции, находящиеся в стеке, до ближайшей открывающей скобки или до операции с приоритетом меньшим, чем у новой операции, перекладываются в формируемую запись, а новая операции кладётся в стек
while (Convert.ToInt32(TokensStack.Peek()) > Convert.ToInt32(operations.Peek()) || operations.Peek() != "16")
{
if (operations.Peek() == "00")
break;
s1.Push(BinOp(operations.Pop()));
}
Открывающая скобка кладётся в стек.
if (operations.Peek() == "16" || operations.Peek() == "00")
{
operations.Push(TokensStack.Pop());
break;
}
Закрывающая скобка выталкивает из стека в формируемую запись все операции до ближайшей открывающей скобки, открывающая скобка удаляется из стека
if (TokensStack.Peek() == "17") // ) => +/- to stack
{
while (operations.Peek() != "16")
{
s1.Push(BinOp(operations.Pop()));
}
TokensStack.Pop();
operations.Pop();
break;
}
После того, как мы добрались до конца исходного выражения, операции, оставшиеся в стеке, перекладываются в формируемое выражение.
while (operations.Peek() != "00")
s1.Push(BinOp(operations.Pop()));
Краткая спецификация модуля интерпретации:
МодульShell
Название процедуры: Equal
Назначение процедуры: Реализует постфиксную запись.
Название процедуры: BinOp
Назначение процедуры: переводит число в знак
Название процедуры: FindOperations
Назначение процедуры: проход по коду в поисках функций
4. РЕАЛИЗАЦИЯ
одирование
Программа была написана на языке программирования C# в среде Microsoft Visual Studio 2012. Исходный текст программы представлен в приложении А.
естирование
Проверка разработанной программы заключалась в её активном использовании с целью выявления ошибок и некорректной работы. В результате этого ошибок обнаружено не было, что позволяет сделать вывод о работоспособности программы.
Этапы тестирования представлены в таблице 3. Скриншоты результатов тестирования представлены в приложении Б.
Таблица2 – план тестирования
№ теста | Цель теста | Ожидаемый результат | Полученный результат |
Проверка вывода ошибок при вводе не корректного кода. | Вывод сообщения об ошибки | Полученный результат совпадает с ожидаемым (рис. 3,4,5). | |
Вычисление необъявленной переменной | Вывод сообщения об ошибки | Полученный результат совпадает с ожидаемым (рис. 6). | |
Ввод корректного кода программы | Программа выводит результат работы программы | Полученный результат совпадает с ожидаемым (рис. 7). |
Заключение
В данной курсовой работе была поставлена задача разработки компилятора к заданной грамматике.
В ходе решения задачи был разработан интерфейс программы, алгоритмического анализатора. Программа производит анализ исходного текста и выдает сообщения об ошибках, если они есть. Было произведено кодирование на языке программирования C# в среде объектно-ориентированного программирования Visual Studio 2012 и тестирование, в ходе которого было выявлено, что программа решает задачу корректно и устойчиво работает на тестовом наборе данных.
Список используемых источников
1. Д. Креншоу «Пишем компилятор»
2. Р. Хантер «Проектирование и конструирование компиляторов»
3. Компаниец Р.И., Маньков Е.В., Филатов Н.Е. «Системное программирование. Основы построения трансляторов»
4. Костельцев А.В. «Построение интерпретаторов и компиляторов»
5. Касьянов В.Н., Поттосин И.В. «Методы построения трансляторов»
6. Д. Грис «Конструирование компиляторов для цифровых вычислительных машин»
7. Ахо А., Ульман Дж. «Теория синтаксического анализа, перевода и компиляции»
8. Льюис Ф., Розенкранц Д., Смирну Д. «Теоретические основы проектирования компиляторов»
ПРИЛОЖЕНИЕ А
Исходный код Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.IO;
namespace KYRS_TLP
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
AsmRichTextBox.ReadOnly = true;
menuStrip1.Renderer = new CustomProfessionalRenderer();
label1.Text = "╔";
for (int i = 0; i < 1; label1.Text += "═", i++) ;
label1.Text += "DEFAULT.FLP";
for (int i = 0; i < 40; label1.Text += "═", i++) ;
label1.Text += "╗\r";
for (int i = 0; i < 26; i++)
{
label1.Text += "║";
for (int j = 0; j < 52; label1.Text += " ", j++) ;
label1.Text += "║\r";
}
label1.Text += "╚";
for (int i = 0; i < 52; label1.Text += "═", i++) ;
label1.Text += "╝";
label2.Text = "╔";
for (int i = 0; i < 1; label2.Text += "═", i++) ;
label2.Text += "OUTPUT";
for (int i = 0; i < 17; label2.Text += "═", i++) ;
label2.Text += "╗\r";
for (int i = 0; i < 26; i++)
{
label2.Text += "║";
for (int j = 0; j < 24; label2.Text += " ", j++) ;
label2.Text += "║\r";
}
label2.Text += "╚";
for (int i = 0; i < 24; label2.Text += "═", i++) ;
label2.Text += "╝";
label3.Visible = false;
}
int len = 0;
static bool IsEnter = false;
static string ReadString = "";
delegate void AddText(string msg);
delegate void IsVisible(bool msg);
struct snd
{
public List<Stack<string>> IN;
public RichTextBox rtb;
public snd(List<Stack<string>> a, RichTextBox b)
{
IN = a;
rtb = b;
}
};
struct ConstIdent
{
public string Ident;
public string Const;
public ConstIdent(string a, string b)
{
Ident = a;
Const = b;
}
};
struct CaseStruct
{
public int one;
public string two;
public string three;
public CaseStruct(int a, string b, string c)
{
one = a;
two = b;
three = c;
}
};
//компилим
private void debugToolStripMenuItem_Click(object sender, EventArgs e)
{
Lexer lex = new Lexer(CodeRichTextBox.Text);
Parser pars = new Parser(lex.TOKENS);
if (pars.DebugMsg == "debug successful")
{
AsmRichTextBox.Focus();
Shell shell = new Shell(pars.TokensShell, lex.IDENTIFIES, lex.CONSTANTS);
snd[] snd1 = { new snd(shell.OUT, AsmRichTextBox) };
Thread RunThread = new Thread(Run);
RunThread.Start(snd1);
}
label3.Visible = true;
label3.Text = pars.DebugMsg;
Thread time = new Thread(timer);
time.Start(label3);
}
static void Run( object INI)
{
snd[] snd1 = (snd[])INI;
List<ConstIdent> CI = new List<ConstIdent>();
for (int i = 0; i < snd1[0].IN.Count(); i++)
{
while (snd1[0].IN[i].Count() != 0)
{
switch (snd1[0].IN[i].Peek())
{
case "05":
{
if (snd1[0].rtb.InvokeRequired)
snd1[0].rtb.Invoke(new IsVisible((s) => snd1[0].rtb.ReadOnly = s), false);
snd1[0].IN[i].Pop();
while(snd1[0].IN[i].Count !=0)
{
int rr=0;
string b = "";
string a = snd1[0].IN[i].Pop();
while (rr == 0)
{
while (IsEnter == false) { Thread.Sleep(100); }
b = ReadString;
try { int k = Convert.ToInt32(b); IsEnter = false; rr++; }
catch
{
if (snd1[0].rtb.InvokeRequired)
snd1[0].rtb.Invoke(new AddText((s) => snd1[0].rtb.AppendText(s)), "Incorrect type\n");
IsEnter = false;
}
}
CI.Add(new ConstIdent(a, b));
}
IsEnter = false;
if (snd1[0].rtb.InvokeRequired)
snd1[0].rtb.Invoke(new IsVisible((s) => snd1[0].rtb.ReadOnly = s), true);
break;
}
case "06":
{
snd1[0].IN[i].Pop();
while (snd1[0].IN[i].Count != 0)
{
for (int j = CI.Count-1; j >= 0 ; j-- )
{
if(snd1[0].IN[i].Peek() == CI[j].Ident)
{
try
{
Convert.ToInt32(CI[j].Const);
if (snd1[0].rtb.InvokeRequired)
snd1[0].rtb.Invoke(new AddText((s) => snd1[0].rtb.AppendText(s)), Convert.ToString(CI[j].Const + "\n"));
}
catch
{
if (snd1[0].rtb.InvokeRequired)
snd1[0].rtb.Invoke(new AddText((s) => snd1[0].rtb.AppendText(s)), "");
}
snd1[0].IN[i].Pop();
break;
}
}
}
break;
}
case "07":
{
Stack<string> s1 = new Stack<string>();
List<CaseStruct> CS = new List<CaseStruct>();
string three;
int case1 = 0;
snd1[0].IN[i].Pop();
snd1[0].IN[i].Pop();
string case2 = snd1[0].IN[i].Pop();
if(snd1[0].IN[i].Peek() == "$")
{
try
{
case1 = Convert.ToInt32(case2);
}
catch
{
try { case1 = Convert.ToInt32(TryFind(case2, CI)); }
catch
{
if (snd1[0].rtb.InvokeRequired)
snd1[0].rtb.Invoke(new AddText((s) => snd1[0].rtb.AppendText(s)), TryFind(case2, CI) + "\n");
}
}
}
else
{
snd1[0].IN[i].Push(case2);
try
{
case1 = Convert.ToInt32(Operation(snd1[0].IN[i], CI));
}
catch
{
if (snd1[0].rtb.InvokeRequired)
snd1[0].rtb.Invoke(new AddText((s) => snd1[0].rtb.AppendText(s)), Operation(snd1[0].IN[i], CI) + "\n");
}
}
snd1[0].IN[i].Pop();
while(snd1[0].IN[i].Count != 0)
{
int one = Convert.ToInt32(snd1[0].IN[i].Pop());
string two = snd1[0].IN[i].Pop();
snd1[0].IN[i].Pop();
three = Operation(snd1[0].IN[i], CI);
CS.Add(new CaseStruct(one, two, three));
snd1[0].IN[i].Pop();
}
for (int j = 0; j < CS.Count; j++ )
{
if (case1 == CS[j].one)
{
CI.Add(new ConstIdent(CS[j].two, CS[j].three));
break;
}
}
break;
}
default:
{
if (snd1[0].IN[i].Count() == 4)
{
string a = snd1[0].IN[i].Pop();
snd1[0].IN[i].Pop();
string err = TryFind(snd1[0].IN[i].Pop(), CI);
CI.Add(new ConstIdent(a, err));
snd1[0].IN[i].Pop();
break;
}
else
{
string a = snd1[0].IN[i].Pop();
snd1[0].IN[i].Pop();
string ww = Operation(snd1[0].IN[i], CI);
if (ww == "variable is not set" || ww == "zero division")
if (snd1[0].rtb.InvokeRequired)
snd1[0].rtb.Invoke(new AddText((s) => snd1[0].rtb.AppendText(s)), ww + "\n");
CI.Add(new ConstIdent(a, ww));
snd1[0].IN[i].Pop();
}
break;
}
}
}
}
}
static string TryFind( string a, List<ConstIdent> ci)
{
int ret;
int kol=0;
while (true)
{
try { ret = Convert.ToInt32(a); return a; }
catch
{
kol = 0;
for (int j = ci.Count-1; j >= 0; j--)
{
if (ci[j].Ident == a)
{
a = ci[j].Const;
kol++;
break;
}
}
if (kol == 0)
return "variable is not set";
}
}
}
static string Operation(Stack<string> a, List<ConstIdent> CI)
{
Stack<string> s1 = new Stack<string>();
while (a.Peek() != "$")
{
switch (a.Peek())
{
case "+":
{
a.Pop();
int b1, c1;
try
{
b1 = Convert.ToInt32(TryFind(s1.Pop(), CI));
c1 = Convert.ToInt32(TryFind(s1.Pop(), CI));
}
catch
{
return "variable is not set";
}
if (a.Peek() != "$")
s1.Push(Convert.ToString(b1 + c1));
else
return Convert.ToString(b1 + c1);
break;
}
case "-":
{
a.Pop();
int b1, c1;
try
{
b1 = Convert.ToInt32(TryFind(s1.Pop(), CI));
c1 = Convert.ToInt32(TryFind(s1.Pop(), CI));
}
catch
{
return "variable is not set";
}
if (a.Peek() != "$")
s1.Push(Convert.ToString(c1 - b1));
else
return Convert.ToString(c1 - b1);
break;
}
case "/":
{
a.Pop();
int b1, c1;
try
{
b1 = Convert.ToInt32(TryFind(s1.Pop(), CI));
c1 = Convert.ToInt32(TryFind(s1.Pop(), CI));
if (b1 == 0)
return "zero division";
}
catch
{
return "variable is not set";
}
if (a.Peek() != "$")
s1.Push(Convert.ToString(c1 / b1));
else
return Convert.ToString(c1 / b1);
break;
}
default:
{
s1.Push(a.Pop());
if(a.Peek()=="$" && s1.Count == 1)
{
return s1.Pop();
}
break;
}
}
}
return "error";
}
static void timer(object l3)
{
Label lbl = (Label)l3;
Thread.Sleep(10000);
if (lbl.InvokeRequired)
lbl.Invoke(new IsVisible((s) => lbl.Visible = s), false);
}
//новый проект
private void newProjectToolStripMenuItem_Click(object sender, EventArgs e)
{
CodeRichTextBox.Text = "";
}
//открыть
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{
using(OpenFileDialog OpnFDlg = new OpenFileDialog())
{
try
{
OpnFDlg.Filter = "TLP files(*.TLP)|*.TLP|All files(*.*)|*.*";
OpnFDlg.FilterIndex = 1;
OpnFDlg.InitialDirectory = "D:";
if(OpnFDlg.ShowDialog() == DialogResult.OK)
{
StreamReader sr = new StreamReader(OpnFDlg.FileName, Encoding.Default);
string str = sr.ReadToEnd();
sr.Close();
CodeRichTextBox.Text = str;
}
}
catch(Exception msg)
{
MessageBox.Show(msg.Message);
}
}
}
//сохранить
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveFileDialog SvFlDlg = new SaveFileDialog();
SvFlDlg.DefaultExt = "*.TLP";
SvFlDlg.Filter = "TLP files(*.TLp)|*.TLP";
if(SvFlDlg.ShowDialog() == DialogResult.OK && SvFlDlg.FileName.Length > 0)
{
CodeRichTextBox.SaveFile(SvFlDlg.FileName, RichTextBoxStreamType.PlainText);
}
}
//выход
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Close();
}
//о программе
private void helpToolStripMenuItem_Click(object sender, EventArgs e)
{
About about = new About();
about.Show();
}
//обработка сочетаний клавиш
private void CodeRichTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == (int)Keys.Control || e.KeyValue == (int)Keys.E || e.KeyValue == (int)Keys.J || e.KeyValue == (int)Keys.R)
{
e.Handled = true;
}
}
//обработка сочетаний клавиш
private void AsmRichTextBox_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == (int)Keys.Control || e.KeyValue == (int)Keys.E || e.KeyValue == (int)Keys.J || e.KeyValue == (int)Keys.R || e.KeyValue == (int)Keys.Z)
{
e.Handled = true;
}
if (e.KeyValue == (int)Keys.Control || e.KeyValue == (int)Keys.A)
{
e.Handled = true;
int k = AsmRichTextBox.Text.Length - AsmRichTextBox.GetFirstCharIndexOfCurrentLine();
AsmRichTextBox.Select(AsmRichTextBox.GetFirstCharIndexOfCurrentLine(), k);
AsmRichTextBox.Refresh();
}
if (e.KeyValue == (int)Keys.Control || e.KeyValue == (int)Keys.Home)
{
e.Handled = true;
}
if(e.KeyValue == (int)Keys.Up || e.KeyValue == (int)Keys.Down)
{
e.Handled = true;
}
if(e.KeyValue == (int)Keys.Left)
{
if (AsmRichTextBox.SelectionStart <= len)
{
e.Handled = true;
}
}
if(e.KeyValue == (int)Keys.PageDown || e.KeyValue == (int)Keys.PageUp)
{
e.Handled = true;
}
if (e.KeyValue == (int)Keys.Back)
{
if(AsmRichTextBox.SelectionStart <= len)
{
e.Handled = true;
}
}
if (e.KeyValue == (int)Keys.Enter)
{
if (AsmRichTextBox.ReadOnly == false)
{
ReadString = AsmRichTextBox.Lines[AsmRichTextBox.GetLineFromCharIndex(AsmRichTextBox.GetFirstCharIndexFromLine(AsmRichTextBox.SelectionStart-1))];
IsEnter = true;
}
len = AsmRichTextBox.SelectionStart = AsmRichTextBox.Text.Length+1;
}
}
}
}
class CustomProfessionalRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
Rectangle r = Rectangle.Inflate(e.Item.ContentRectangle, 1, 1);
if (e.Item.Selected)
{
using (Brush b = new SolidBrush(Color.DarkGray))
{
e.Graphics.FillRectangle(b, r);
}
}
else
{
using (Pen p = new Pen(Color.Black))
{
e.Graphics.DrawRectangle(p, r);
Brush b = new SolidBrush(Color.Black);
e.Graphics.FillRectangle(b, r);
}
}
}
}
Исходный код Lexer.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace KYRS_TLP
{
class Lexer
{
const int IdentLength = 11;
string Code;
int FindInt = 0;
public string Error="";
public int kolError = 0;
struct KeyWords
{
public string Words;
public string WordKey;
public KeyWords(string a, string b)
{
Words = a;
WordKey = b;
}
}
KeyWords[] KEYS = { new KeyWords("VAR", "01"), new KeyWords("INTEGER", "02"),new KeyWords("BEGIN", "03"),
new KeyWords("END", "04"), new KeyWords("READ", "05"),new KeyWords("WRITE", "06"),
new KeyWords("CASE", "07"), new KeyWords("OF", "08"),new KeyWords("END_CASE", "09") };
KeyWords[] CHARS = { new KeyWords(":", "10"), new KeyWords(";", "11"), new KeyWords("=", "12"),
new KeyWords("+", "13"), new KeyWords("-", "14"), new KeyWords("/", "15"),
new KeyWords("(", "16"), new KeyWords(")", "17"), new KeyWords(",", "18") };
/*
Недопустимый символ 91
Слишком длинное имя переменной 92
Повторное объявление переменной 93
Необъявленная переменная 94
Неверное имя переменной 95
*/
//регулярное выражение
string rgz = @"(?<char>[^:;\(\)\=\+\-\/\s\,]*)(?<separator>[:;\(\)\=\+\-\/\s\,]{1})?";
//список полученных токенов, идентификаторов, констант
public Stack<string> TOKENS = new Stack<string>();
public List<string> IDENTIFIES = new List<string>();
public List<string> CONSTANTS = new List<string>();
public Lexer()
{
this.Error = "Lexer error.\n";
}
public Lexer(string Code)
{
this.Code = Code;
string pattern = "( )+";
string replacement = " ";
if (this.Code.Length == 0)
{
this.Error += "Error: No entry.\n";
}
else
{
//удаление лишних пробелов, перевод в вверхний регистр
Regex rgx = new Regex(pattern);
this.Code = rgx.Replace(this.Code, replacement);
this.Code = this.Code.ToUpper();
}
LexerOut();
}
private void LexerOut()
{
Match match = Regex.Match(this.Code, this.rgz);
while (match.Success)
{
if (match.Groups["char"].Length > 0)
if (!IsKeyword(match.Groups["char"].ToString(), KEYS))
if (!IsIdenOrConst(match.Groups["char"].ToString(), "[^0-9]+", "21", CONSTANTS, int.MaxValue.ToString().Length))
{
IDENTIFIES.Add(match.Groups["char"].ToString());
AddError(match.Groups["char"].ToString());
}
if ((match.Groups["separator"].ToString() != " ") && (match.Groups["separator"].ToString() != "\n"))
IsKeyword(match.Groups["separator"].ToString(), CHARS);
match = match.NextMatch();
}
}
private bool IsKeyword(string word, KeyWords[] kwd)
{
bool TOF = false;
for(int i=0; i< kwd.Count(); i++)
{
if (kwd[i].Words == word)
{
TOKENS.Push(kwd[i].WordKey);
TOF = true;
if (word == "BEGIN")
FindInt = IDENTIFIES.Count;
break;
}
}
return TOF;
}
private bool IsIdenOrConst(string word, string regular, string ID, List<string> lst, int len)
{
bool TOF = true;
if (Regex.Match(word, regular).Success)
TOF = false;
else
{
TOKENS.Push(ID);
lst.Add(word);
}
return TOF;
}
private void AddError(string word)
{
int kol = 0;
for (int i = 0; i < 5; i++)
{
switch (i)
{
case 0: { if (Regex.Match(word, @"[^A-Z0-9:;\(\)\=\+\-\/\s\,]").Success) { kol++; TOKENS.Push("91"); } break; }
case 1: { if (word.Length > IdentLength) { kol++; TOKENS.Push("92"); } break; }
case 2: { int k2 = 0; if (FindInt == 0) for (int j = 0; j < IDENTIFIES.Count; j++) if (word == IDENTIFIES[j]) k2++; if (k2 > 1) { kol++; TOKENS.Push("93"); } break; }
case 3: { int k2 = 1; if (FindInt != 0) { k2 = 0; for (int j = 0; j < FindInt; j++) if (word == IDENTIFIES[j]) k2++; } if (k2 == 0) { kol++; TOKENS.Push("94"); } break; }
case 4: { if (Regex.Match(word, "[^A-Z]").Success) { kol++; TOKENS.Push("95"); } break; }
}
}
if (kol == 0)
TOKENS.Push("20");
}
}
}
Исходный код Parser.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace KYRS_TLP
{
class Parser
{
private Stack<string> Tokens = new Stack<string>();
private Stack<string> TokensStack = new Stack<string>();
private Stack<string> StatesStack = new Stack<string>();
public string DebugMsg = "";
public Stack<string> TokensShell = new Stack<string>();
public Parser(Stack<string> Tokens)
{
this.Tokens = Tokens;
Parsing();
}
//создаем список состояний
string[,] States = { { "04", "53", "03", "11", "02", "10", "51", "00" },
{ "54", "11", "17", "51", "16", "00", "00", "00" },
{ "54", "11", "09", "56", "08", "58", "00", "00" },
{ "54", "11", "58", "12", "00", "00", "00", "00" },
{ "11", "58", "12", "00", "00", "00", "00", "00" },
{ "57", "55", "10", "00", "00", "00", "00", "00" },
{ "60", "17", "58", "00", "00", "00", "00", "00" } };
//записываем лексемы в стек
private void ToStack()
{
TokensStack.Push("$");
TokensShell.Push("$");
while (Tokens.Count != 0)
{
TokensStack.Push(Tokens.Peek());
TokensShell.Push(Tokens.Pop());
}
}
//парсер
private int Parsing()
{
ToStack();
StatesStack.Push("$");
StatesStack.Push("50");
while((StatesStack.Count != 0) || (TokensStack.Count != 0))
{
switch(StatesStack.Pop())
{
case "50":
{
switch(TokensStack.Pop())
{
case "01": { int i = 0; while (States[0, i] != "00") StatesStack.Push(States[0, i++]); break; }
default: { DebugMsg = "error: expected \"VAR\""; return 0; }
}
break;
}
case "51":
{
switch(TokensStack.Pop())
{
case "20": { StatesStack.Push("52"); break; }
case "91": { DebugMsg = "error: invalid code"; return 0; }
case "92": { DebugMsg = "error: long variable name"; return 0; }
case "93": { DebugMsg = "error: re variable declaration"; return 0; }
case "94": { DebugMsg = "error: undeclared variable"; return 0; }
case "95": { DebugMsg = "error: incorrect variable name"; return 0; }
default: { DebugMsg = "error: expected variable"; return 0; }
}
break;
}
case "52":
{
switch(TokensStack.Pop())
{
case "18": { StatesStack.Push("51"); break; }
case "10": { StatesStack.Pop(); break; }
case "17": { StatesStack.Pop(); break; }
default: { DebugMsg = "error: Syntax error"; return 0; }
}
break;
}
case "53":
{
switch(TokensStack.Pop())
{
case "05": { int i = 0; while (States[1, i] != "00") StatesStack.Push(States[1, i++]); break; }
case "06": { int i = 0; while (States[1, i] != "00") StatesStack.Push(States[1, i++]); break; }
case "07": { int i = 0; while (States[2, i] != "00") StatesStack.Push(States[2, i++]); break; }
case "20": { int i = 0; while (States[3, i] != "00") StatesStack.Push(States[3, i++]); break; }
case "91": { DebugMsg = "error: invalid code"; return 0; }
case "92": { DebugMsg = "error: long variable name"; return 0; }
case "93": { DebugMsg = "error: re variable declaration"; return 0; }
case "94": { DebugMsg = "error: undeclared variable"; return 0; }
case "95": { DebugMsg = "error: incorrect variable name"; return 0; }
default: { DebugMsg = "error: Syntax error"; return 0; }
}
break;
}
case "54":
{
switch(TokensStack.Peek())
{
case "05": { StatesStack.Push("53"); break; }
case "06": { StatesStack.Push("53"); break; }
case "07": { StatesStack.Push("53"); break; }
case "20": { StatesStack.Push("53"); break; }
case "04": { StatesStack.Pop(); TokensStack.Pop(); break; }
case "91": { DebugMsg = "error: invalid code"; return 0; }
case "92": { DebugMsg = "error: long variable name"; return 0; }
case "93": { DebugMsg = "error: re variable declaration"; return 0; }
case "94": { DebugMsg = "error: undeclared variable"; return 0; }
case "95": { DebugMsg = "error: incorrect variable name"; return 0; }
default: { DebugMsg = "error: Syntax error"; return 0; }
}
break;
}
case "55":
{
switch(TokensStack.Pop())
{
case "20": { int i = 0; while (States[4, i] != "00") StatesStack.Push(States[4, i++]); break; }
case "91": { DebugMsg = "error: invalid code"; return 0; }
case "92": { DebugMsg = "error: long variable name"; return 0; }
case "93": { DebugMsg = "error: re variable declaration"; return 0; }
case "94": { DebugMsg = "error: undeclared variable"; return 0; }
case "95": { DebugMsg = "error: incorrect variable name"; return 0; }
default: { DebugMsg = "error: Syntax error"; return 0; }
}
break;
}
case "56":
{
switch(TokensStack.Pop())
{
case "21": { int i = 0; while (States[5, i] != "00") StatesStack.Push(States[5, i++]); break; }
default: { DebugMsg = "error: Syntax error"; return 0; }
}
break;
}
case "57":
{
switch(TokensStack.Peek())
{
case "21": { StatesStack.Push("56"); break; }
case "09": { TokensStack.Pop(); break; }
default: { DebugMsg = "error: Syntax error"; return 0; }
}
break;
}
case "58":
{
switch(TokensStack.Peek())
{
case "14": { TokensStack.Pop(); StatesStack.Push("59"); break; }
case "16": { StatesStack.Push("59"); break; }
case "20": { StatesStack.Push("59"); break; }
case "21": { StatesStack.Push("59"); break; }
case "91": { DebugMsg = "error: invalid code"; return 0; }
case "92": { DebugMsg = "error: long variable name"; return 0; }
case "93": { DebugMsg = "error: re variable declaration"; return 0; }
case "94": { DebugMsg = "error: undeclared variable"; return 0; }
case "95": { DebugMsg = "error: incorrect variable name"; return 0; }
default: { DebugMsg = "error: incorrect expression"; return 0; }
}
break;
}
case "59":
{
switch(TokensStack.Pop())
{
case "16": { int i = 0; while (States[6, i] != "00") StatesStack.Push(States[6, i++]); break; }
case "20": { StatesStack.Push("60"); break; }
case "21": { StatesStack.Push("60"); break; }
case "91": { DebugMsg = "error: invalid code"; return 0; }
case "92": { DebugMsg = "error: long variable name"; return 0; }
case "93": { DebugMsg = "error: re variable declaration"; return 0; }
case "94": { DebugMsg = "error: undeclared variable"; return 0; }
case "95": { DebugMsg = "error: incorrect variable name"; return 0; }
default: { DebugMsg = "error: Syntax error"; return 0; }
}
break;
}
case "60":
{
switch(TokensStack.Pop())
{
case "13": { StatesStack.Push("59"); break; }
case "14": { StatesStack.Push("59"); break; }
case "15": { StatesStack.Push("59"); break; }
case "08": { StatesStack.Pop(); break; }
case "11": { StatesStack.Pop(); break; }
case "17": { StatesStack.Pop(); break; }
default: { DebugMsg = "error: Syntax error"; return 0; }
}
break;
}
case "02":
{
switch(TokensStack.Pop())
{
case "02": { break; }
default: { DebugMsg = "error: expected \"integer\""; return 0; }
}
break;
}
case "03":
{
switch(TokensStack.Pop())
{
case "03": { break; }
default: { DebugMsg = "error: expected \"begin\""; return 0; }
}
break;
}
case "11":
{
switch(TokensStack.Pop())
{
case "11": { break; }
default: { DebugMsg = "error: expected \";\""; return 0; }
}
break;
}
case "12":
{
switch (TokensStack.Pop())
{
case "12": { break; }
default: { DebugMsg = "error: expected \"=\""; return 0; }
}
break;
}
case "10":
{
switch (TokensStack.Pop())
{
case "10": { break; }
default: { DebugMsg = "error: expected \":\""; return 0; }
}
break;
}
case "16":
{
switch (TokensStack.Pop())
{
case "16": { break; }
default: { DebugMsg = "error: expected \"(\""; return 0; }
}
break;
}
case "17":
{
switch (TokensStack.Pop())
{
case "17": { break; }
default: { DebugMsg = "error: expected \")\""; return 0; }
}
break;
}
case "$":
{
switch (TokensStack.Pop())
{
case "$": { break; }
default: { DebugMsg = "error: incorrect completion"; return 0; }
}
break;
}
default: { break; }
}
}
DebugMsg = "debug successful";
return 0;
}
}
}
Исходный код Shell.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace KYRS_TLP
{
class Shell
{
private List<string> IDENTIFIES = new List<string>();
private List<string> CONSTANTS = new List<string>();
private Stack<string> TokensStack = new Stack<string>();
private int CounterIdentifies = 0;
private int CounterConstants = 0;
public List<Stack<string>> OUT = new List<Stack<string>>();
private string OutAdd = "";
private string[] priority = { "14", "13", "15" };
public Shell(Stack<string> TOKENS, List<string> IDENTIFIES, List<string> CONSTANTS)
{
this.TokensStack = TOKENS;
this.IDENTIFIES = IDENTIFIES;
this.CONSTANTS = CONSTANTS;
FindOperations();
}
private void FindOperations()
{
while(TokensStack.Peek() != "03")
{
if(TokensStack.Pop() == "20")
{
CounterIdentifies++;
}
}
while(TokensStack.Count != 0)
{
switch(TokensStack.Peek())
{
case "05":
{
Stack<string> s1 = new Stack<string>();
Stack<string> s2 = new Stack<string>();
s1.Push(TokensStack.Pop());
while(TokensStack.Peek() != "11")
{
if(TokensStack.Pop() == "20")
{
s1.Push(IDENTIFIES[CounterIdentifies++]);
}
}
while (s1.Count != 0)
s2.Push(s1.Pop());
OUT.Add(s2);
break;
}
case "06":
{
Stack<string> s1 = new Stack<string>();
Stack<string> s2 = new Stack<string>();
s1.Push(TokensStack.Pop());
while (TokensStack.Peek() != "11")
{
if (TokensStack.Pop() == "20")
{
s1.Push(IDENTIFIES[CounterIdentifies++]);
}
}
while (s1.Count != 0)
s2.Push(s1.Pop());
OUT.Add(s2);
break;
}
case "07":
{
Stack<string> s1 = new Stack<string>();
Stack<string> s2 = new Stack<string>();
s1.Push(TokensStack.Pop());
s2 = Equal("08");
while (s2.Count != 0)
s1.Push(s2.Pop());
while(TokensStack.Pop() != "09")
{
if (TokensStack.Peek() == "09")
break;
s1.Push(CONSTANTS[CounterConstants++]);
for (int i = 0; i < 4; TokensStack.Pop(), i++);
s1.Push(IDENTIFIES[CounterIdentifies++]);
s2 = Equal("11");
while (s2.Count != 0)
s1.Push(s2.Pop());
}
while (s1.Count != 0)
s2.Push(s1.Pop());
OUT.Add(s2);
break;
}
case "12":
{
Stack<string> s1 = new Stack<string>();
Stack<string> s2 = new Stack<string>();
s1.Push(IDENTIFIES[CounterIdentifies++]);
TokensStack.Pop();
s2 = Equal("11");
while (s2.Count != 0)
s1.Push(s2.Pop());
while (s1.Count != 0)
s2.Push(s1.Pop());
OUT.Add(s2);
break;
}
default:
{
TokensStack.Pop();
break;
}
}
}
}
private Stack<string> Equal(string end)
{
Stack<string> s1 = new Stack<string>();
Stack<string> s2 = new Stack<string>();
s1.Push("$");
Stack<string> operations = new Stack<string>();
operations.Push("00");
while (TokensStack.Peek() != end)
{
switch (TokensStack.Peek())
{
case "20": { s1.Push(IDENTIFIES[CounterIdentifies++]); TokensStack.Pop(); break; }
case "21": { s1.Push(CONSTANTS[CounterConstants++]); TokensStack.Pop(); break; }
default:
{
//для унарного минуса
//если стек пуст и мы считываем минус
if(s1.Peek() == "$" && TokensStack.Peek() == "14")
s1.Push("0");
if (operations.Peek() == "16" && TokensStack.Peek() == "14")
s1.Push("0");
if (operations.Peek() == "16" || operations.Peek() == "00")
{
operations.Push(TokensStack.Pop());
break;
}
if(TokensStack.Peek() == "16")
{
operations.Push(TokensStack.Pop());
break;
}
if(TokensStack.Peek() == "17")
{
while(operations.Peek() != "16")
{
s1.Push(BinOp(operations.Pop()));
}
TokensStack.Pop();
operations.Pop();
break;
}
if(Convert.ToInt32(TokensStack.Peek()) > Convert.ToInt32(operations.Peek()))
{
operations.Push(TokensStack.Pop());
}
else
{
while(Convert.ToInt32(TokensStack.Peek()) > Convert.ToInt32(operations.Peek()) || operations.Peek() != "16")
{
if(operations.Peek() == "00")
break;
s1.Push(BinOp(operations.Pop()));
}
}
break;
}
}
}
while (operations.Peek() != "00")
s1.Push(BinOp(operations.Pop()));
s1.Push("$");
while (s1.Count != 0)
s2.Push(s1.Pop());
return s2;
}
private string BinOp(string str)
{
if (str == "13")
return "+";
if (str == "14")
return "-";
return "/";
}
}
}
Исходный код About.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace KYRS_TLP
{
public partial class About : Form
{
public About()
{
InitializeComponent();
}
private void LabelClose_Click(object sender, EventArgs e)
{
Close();
}
private Int32 tmpX;
private Int32 tmpY;
private bool flMove = false;
private void About_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left && e.Y <= 21)
{
tmpX = Cursor.Position.X;
tmpY = Cursor.Position.Y;
flMove = true;
}
}
private void About_MouseMove(object sender, MouseEventArgs e)
{
if (flMove)
{
this.Left = this.Left + (Cursor.Position.X - tmpX);
this.Top = this.Top + (Cursor.Position.Y - tmpY);
tmpX = Cursor.Position.X;
tmpY = Cursor.Position.Y;
}
}
private void About_MouseUp(object sender, MouseEventArgs e)
{
flMove = false;
}
private void LabelClose_MouseHover(object sender, EventArgs e)
{
LabelClose.ForeColor = Color.LightGray;
}
private void LabelClose_MouseLeave(object sender, EventArgs e)
{
LabelClose.ForeColor = Color.White; } }}
ПРИЛОЖЕНИЕ Б
Рис3. Вывод сообщения об ошибки
Рис4. Вывод сообщения об ошибки
Рис5. Вывод сообщения об ошибки
Рис6. Вывод сообщения об ошибки
Рис7. Рабочая программа ввод(a = a, b = 2) вывод (a = 4, b = 2)