Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
daniel.docx
Скачиваний:
2
Добавлен:
21.09.2019
Размер:
236.18 Кб
Скачать

Лабораторная работа №6. Определить форму кс-грамматики и сделать ее приведение.

Приведенные грамматики — это КС-грамматики, которые не содержат недостижимых и бесполезных символов, циклов и ε-правил.

6.1. Задана следующая грамматика:

G = {V = {S, F, L},T={i, * , :,(,)}, P = {S→(F:L), F→ L*, F→ i, L→F},S0}

6.2. Эта же грамматика в приведённом виде:

G’={V={S,F,L},T={i,*,:,(,)},P={S→(F:L),F→i,L→i,L→iL’,L’→*L’,L’→*},S0}

6.3. Определить форму грамматики (Грейбаха и т.д.)

КС – грамматика G = (V, T, P, S) называется грамматикой в нормальной форме Хомского, если каждое правило из Р имеет один из следующих видов:

1. A → BC, где A,B и C ϵ V;

2. A → a, где a ϵ T;

3. S → ε, если ε ϵ L(G), причем S не встречается в правых частях правил.

КС – грамматика G = (V, T, P, S) называется грамматикой в нормальной форме Грейбах, если в ней нет ε-правил и каждое правило из Р, отличное от

S → ε, имеет вид A → аα, где а ϵ T и α ϵ V*.

Данная грамматика имеет нормальную форму Грейбах.

Лабораторная работа №7.

Спроектировать МП автомат для приведенной КС-грамматики

G’={V={S, F, L},T={i,*,:,(,)}, P={S→(F:L), F→ L*, F→ i, L→i, L→iL’, L’→*L’ , L’→ *},S0}

MP = {Q, T, Г, δ, q0, Z0, F}

Q = {S, F, L, L’},

T = {i, *, :, (, )},

q0 = S0.

Правила перехода δ:

δ(q, ɛ, S) = {(q, (F : L))}

δ(q, ɛ, F) = {(q, L*), (q, i)}

δ(q, ɛ, L) = {(q, i), (q, iL’)}

δ(q, ɛ, L’) = {(q, *L’), (q, *)}

δ(q, α) = {(q, ɛ)}, для любого терминала α ϵ T.

Пример разбора входной цепочки символов:

(q, (i**:i*), S) ˫ (q, (i**:i*), (F:L))

˫ (q, i**:i*), F:L))

˫ (q, i**:i*), L*:L))

˫ (q, i**:i*), iL’*:L))

˫ (q, **:i*), L’*:L))

˫ (q, **:i*), **:L))

˫ (q, *:i*), *:L))

˫ (q, :i*), :L))

˫ (q, i*), L))

˫ (q, i*), iL’))

˫ (q, *), L’))

˫ (q, *), *))

˫ (q, ), ))

˫ (q, ɛ, ɛ)

Лабораторная работа №8. Реализовать мп автомат для приведенной кс-грамматики

Класс Grammar.

class Grammar

{ // KC-Grammar (T,V,P,S)

ArrayList T = null; // множество вcех терминалов

ArrayList V = null; // множество всех нетерминалов

ArrayList P = new ArrayList(); // множество вcех правил порождения

string S = null; // начальный символ

// атрибутное программирование на C#

public ArrayList t { get { return T; } set { T = value; } }

public ArrayList v { get { return V; } set { V = value; } }

public ArrayList p

{

get { return P; }

set { P = value; }

}

public string s { get { return S; } set { S = value; } }

public Grammar()

{

Init();

}

public void Init()

{ // задание правил

T = new ArrayList() { "i", "*", ":", "(", ")" };

V = new ArrayList() { "S", "F", "L", "A" };

S = "S";

Rule rule = null;

// 1. transition

rule = new Rule("S", new ArrayList() { "(", "F", ":", "L", ")" });

P.Add(rule);

// 2. transition

rule = new Rule("F", new ArrayList() { "L", "*", });

P.Add(rule);

// 3. transition

rule = new Rule("F", new ArrayList() { "i" });

P.Add(rule);

// 4. transition

rule = new Rule("L", new ArrayList() { "i" });

P.Add(rule);

rule = new Rule("L", new ArrayList() { "i", "A" });

P.Add(rule);

rule = new Rule("A", new ArrayList() { "*", "A" });

P.Add(rule);

rule = new Rule("A", new ArrayList() { "*" });

P.Add(rule);

} // end

public void lrecdel() // устранение левой рекурсии

{

ArrayList P1; // новые правила

ArrayList V1 = new ArrayList(); // новые символы A`

foreach (string A in V) // i=1,..,n

{

P1 = new ArrayList();

foreach (Rule r in P) P1.Add(r);

foreach (string B in V) // j=1,..,i-1

{

if (B == A) break; // j=i

foreach (Rule r in P)

if (r.right.Count != 0 && r.left.ToString() == A && r.right[0].ToString() == B)

{ // замена правил для j<i-1

P1.Remove(r);

foreach (Rule r1 in P)

if (r1.left.ToString() == B)

{

ArrayList rulright = new ArrayList();

foreach (string q in r1.right) rulright.Add(q);

Rule rul = new Rule(A, rulright);

for (int i = 1; i < r.right.Count; i++) rul.right.Add(r.right[i]);

P1.Add(rul);

}

}

P = new ArrayList();

foreach (Rule r in P1) P.Add(r);

}

bool inc = false; // есть ли непосредственная левая рекурсия

foreach (Rule r in P) // определение inc

if (r.right.Count != 0 && r.left.ToString() == A && r.right[0].ToString() == A) { inc = true; V1.Add(A + "`"); }

if (inc) // если есть - замена правил, добавление символа A`

{

foreach (Rule r in P)

{

if (r.right.Count != 0 && r.left.ToString() == A && r.right[0].ToString() == A)

{

P1.Remove(r);

Rule rul = new Rule(A + "`", new ArrayList() { "" });

for (int i = 1; i < r.right.Count; i++) rul.right.Add(r.right[i]);

rul.right.Add(A + "`");

P1.Add(rul);

}

else if (r.left.ToString() == A)

{

P1.Remove(r);

Rule rul = new Rule(A, r.right);

rul.right.Add(A + "`");

P1.Add(rul);

}

}

Rule rul1 = new Rule(A + "`", new ArrayList() { "e" });

P1.Add(rul1);

}

P = new ArrayList();

foreach (Rule r in P1) P.Add(r);

} // замена и добавление новых правил и символов, упорядочивание

foreach (string A in V1) if (!V.Contains(A)) V.Add(A);

P1 = new ArrayList();

foreach (string A in V)

foreach (Rule r in P)

if (r.left.ToString() == A) P1.Add(r);

P = new ArrayList();

foreach (Rule r in P1) P.Add(r);

}

public void prout() // вывод на экран

{

Console.WriteLine("\n Сформирована грамматика G");

Console.WriteLine("Начальное состояние: " + S);

Console.Write("Множество терминальных символов: ");

foreach (string t in T) Console.Write(t);

Console.Write("\n");

Console.Write("Множество нетерминальных символов: ");

foreach (string v in V) Console.Write(v);

Console.Write("\n");

Console.WriteLine("Множество правил порождения:");

foreach (Rule r in P)

{

Console.Write(r.left.ToString() + " -> ");

foreach (string rr in r.right)

{

Console.Write(rr);

}

Console.WriteLine("\n");

}

}

}

Класс Rule.

class Rule

{ // структура Rule правил порождения

private string Left = null;

private ArrayList Right = null;

public string left { get { return Left; } set { Left = value; } }

public ArrayList right { get { return Right; } set { Right = value; } }

// Rule A => {a}

// Left Right

public Rule(string Left, ArrayList Right)

{

this.Left = Left;

this.Right = Right;

}

public void DebugRuleRight()

{

int i = 0;

for (; i < this.right.Count; i++)

{

if (i == 0)

System.Console.Write(" (" + this.right[i]);

else

System.Console.Write("," + this.right[i]);

}

if (i == 0)

System.Console.WriteLine();

else

System.Console.WriteLine(") ");

}

} // end class Rule

Класс MPAutomate.

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");

}

}

}

Main.

Grammar G = new Grammar();

G.lrecdel();

G.prout();

MPAutomate MP = new MPAutomate(G);

MP.Debug();

Console.WriteLine("Сформирован МП-автомат, введите строчку для проверки на допустимость.");

string s = Console.ReadLine();

if (MP.check(s, 0, 0, MP.z) == true) Console.WriteLine("Цепочка допускается");

else Console.WriteLine("Цепочка не допускается");

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]