- •Лабораторные работы по курсу «Системное программное обеспечение»
- •Спроектировать грамматику по заданному языку l:
- •Спроектировать конечный автомат, составить диаграмму переходов ка и реализовать
- •2.1 Таблица переходов и диаграмма переходов.
- •Определить свойства ка. Изучить алгоритм преобразования ндка в дка.
- •2.1 Таблица переходов и диаграмма переходов.
- •4. Устранить из кс-грамматики бесполезные символы и ε–правила.
- •5. Устранить из kс-грамматики цепные правила и устранить левую рекурсию
- •6. Определить форму кс-грамматики и сделать ее приведение.
- •8. Реализовать мп автомат для приведенной кс-грамматики
8. Реализовать мп автомат для приведенной кс-грамматики
Класс МП-автомата.
class MPAutomate
{ // MP-Automate (Q,T,G,D,Q0,Z,F)
ArrayList Q = null; // множество состояний
ArrayList T = null; // входной алфавит
ArrayList G = new ArrayList(); // алфавит магазинных символов
ArrayList D = new ArrayList(); // отображения delta
string Q0 = null; // начальное состояние
Stack Z = new Stack(); // магазин
ArrayList F = null; // множество заключительных состояний
// атрибутное программирование на C#
public ArrayList t { get { return T; } set { T = value; } }
public ArrayList q { get { return Q; } set { Q = value; } }
public ArrayList g { get { return G; } set { G = value; } }
public ArrayList d
{
get { return D; }
set { D = value; }
}
public string q0 { get { return Q0; } set { Q0 = value; } }
public Stack z { get { return Z; } set { Z = value; } }
public ArrayList f { get { return F; } set { F = value; } }
public MPAutomate() { }
public MPAutomate(Grammar gramm)
{
Init(gramm); // иницинализация по данной КС-грамматике
}
class Delta
{ // структура Delta отображения
private string LeftQ = null; // исходное состояние
private string LeftT = null; // символ входной цепочки
private string LeftZ = null; // верхний символ магазин
private ArrayList RightQ = null; // множество следующих состояний
private ArrayList RightZ = null; // множество символов магазина
public string leftQ { get { return LeftQ; } set { LeftQ = value; } }
public string leftT { get { return LeftT; } set { LeftT = value; } }
public string leftZ { get { return LeftZ; } set { LeftZ = value; } }
public ArrayList rightQ { get { return RightQ; } set { RightQ = value; } }
public ArrayList rightZ { get { return RightZ; } set { RightZ = value; } }
// Delta ( q1 , a , z ) = { {q} , {z1z2...} }
// LeftQ LeftT LeftZ RightQ RightZ
public Delta(string LeftQ, string LeftT, string LeftZ, ArrayList RightQ, ArrayList RightZ)
{
this.LeftQ = LeftQ;
this.LeftT = LeftT;
this.LeftZ = LeftZ;
this.RightQ = RightQ;
this.RightZ = RightZ;
}
} // end class Delta
public void Init(Grammar gramm)
{ // задание отображения D
Q = new ArrayList() { "q" }; // состояние
T = gramm.t; // входной алфавит
foreach (string v1 in gramm.v) // магазинные символы
G.Add(v1);
foreach (string t1 in gramm.t)
G.Add(t1);
Q0 = Q[0].ToString(); // начальное состояние
Z.Push(gramm.s); // начальный символ в магазине
F = new ArrayList(); // пустое множество заключительных состояний
Delta delta = null;
foreach (string v1 in gramm.v)
{ // сопоставление правил с отображениями
ArrayList q1 = new ArrayList();
ArrayList z1 = new ArrayList();
foreach (Rule rule in gramm.p)
{
if (rule.left == v1)
{
Stack zb = new Stack();
ArrayList rr = new ArrayList(rule.right);
rr.Reverse();
foreach (string s in rr)
zb.Push(s);
z1.Add(zb);
q1.Add(Q0);
}
}
delta = new Delta(Q0, "e", v1, q1, z1);
D.Add(delta);
}
foreach (string t1 in gramm.t)
{
Stack e = new Stack();
e.Push("e");
delta = new Delta(Q0, t1, t1, new ArrayList() { Q0 }, new ArrayList() { e });
D.Add(delta);
}
} // end
string printstack(Stack s) // печать текущего состояния магазина
{
string p = "|";
Stack s1 = new Stack();
while (s.Count != 0)
{
s1.Push(s.Pop());
p = p + s1.Peek().ToString();
}
while (s1.Count != 0) s.Push(s1.Pop());
return p;
}
int c = 1; // нумерация шагов в log
public bool check(string s, int i, int j, Stack z0) // проверка на допустимость
{ // рекурсивный метод (i-текущий символ в строке, j-текущее состояние, z0-текущие символы в магазине)
if (z0.Count != 0 && z0.Peek().ToString() == "S") c = 1;
if (i == s.Length) // если конец строки
{
if (z0.Count == 0) // если магазин пуст
{
if (F.Count == 0) return true; // множество заключительных состояний пусто
else if (F.Contains(Q[j])) return true; // или автомат дошел до заключительного состояния
else return false;
}
else return false;
}
bool k = false; // успех/неуспех работы
string a = s[i].ToString();
string cq = Q[j].ToString();
foreach (Delta delta in D)
{
if (delta.leftQ == cq && (delta.leftT == a || delta.leftT == "e") && delta.leftZ == z0.Peek().ToString()) // подходящее правило для текущей конфигурации
{
Stack zz1 = new Stack(); // здесь и далее - создание дополнительных стеков для магазина (предотвращение потери данных)
Stack zz2 = new Stack();
Console.Write(c.ToString() + ")"); // оформление отчета
c++;
Console.Write("Входная цепочка: ");
for (int l = i; l < s.Length; l++) Console.Write(s[l].ToString());
Console.Write("\n");
Console.Write("Магазин: ");
while (z0.Count != 0) { Console.Write(z0.Peek().ToString()); zz2.Push(z0.Pop()); }
Console.Write("\n");
string zz;
while (zz2.Count != 0)
{
zz = zz2.Pop().ToString();
if (zz != "e")
{
zz1.Push(zz);
z0.Push(zz);
}
}
if (zz1.Count != 0) zz1.Pop();
foreach (string q1 in delta.rightQ)
{
j = Q.IndexOf(q1); // переход в новое состояние
foreach (Stack z2 in delta.rightZ)
{
if (delta.rightQ[delta.rightZ.IndexOf(z2)].ToString() == q1) // замена верхнего символа на цепочку
{
// стек со снятой вершиной zz1 запоминаем в zz10
Stack zz10 = new Stack();
Stack zz20 = new Stack();
while (zz1.Count != 0) zz20.Push(zz1.Pop());
string zzz;
while (zz20.Count != 0)
{
zzz = zz20.Pop().ToString();
if (zzz != "e")
{
zz10.Push(zzz);
zz1.Push(zzz);
}
}
// замена в стеке zz10
Stack z1 = new Stack();
while (z2.Count != 0)
{
z1.Push(z2.Pop());
}
string z3;
while (z1.Count != 0)
{
z3 = z1.Pop().ToString();
if (z3 != "e")
{
zz10.Push(z3);
z2.Push(z3);
}
}
// формирование стека z02 для нового такта
Stack z01 = new Stack();
Stack z02 = new Stack();
while (zz10.Count != 0) z01.Push(zz10.Pop());
string z00;
while (z01.Count != 0)
{
z00 = z01.Pop().ToString();
if (z00 != "e")
{
z02.Push(z00);
zz10.Push(z00);
}
}
if (delta.leftT == "e") i--;
if (check(s, i + 1, j, z02)) { k = true; return true; } // рекурсивный вызов
if (delta.leftT == "e") i++;
}
}
}
}
if (k) break;
}
if (k) return true;
else return false;
}
public void Debug()
{
Console.WriteLine("\n Сформирован МП-автомат");
Console.Write("Множество состояний: ");
foreach (string q in Q) Console.Write(q);
Console.Write("\n");
Console.Write("Алфавит входных символов: ");
foreach (string t in T) Console.Write(t);
Console.Write("\n");
Console.Write("Алфавит магазинных символов: ");
foreach (string g in G) Console.Write(g);
Console.Write("\n");
Console.Write("Начальное состояние: ");
Console.Write(Q0 + "\n");
Console.Write("Начальный символ в магазине: ");
Console.Write(Z.Peek().ToString() + "\n");
Console.Write("Множество заключительных состояний: ");
foreach (string f in F) Console.Write(f);
if (F.Count == 0) Console.Write("(пустое множество)");
Console.Write("\n");
Console.Write("Отображение:\n");
foreach (Delta delta in D)
{
Console.Write("( " + delta.leftQ + " , " + delta.leftT + " , " + delta.leftZ + " )= (" + delta.rightQ[0].ToString() + " , ");
foreach (Stack s in delta.rightZ)
Console.Write(printstack(s));
Console.Write(" ) \n");
}
}
}
