Результаты работы программы




Межрегиональный центр переподготовки специалистов

Лабораторная работа №3

По дисциплине:

«Теория языков программирования и методы трансляции»

 

 

Выполнил:

Группа: ПБВ-89

Вариант: 8

 

 

Проверил: Бах О.А.

 

 

Новосибирск, 2018 г

Постановка задачи

Перевод с помощью МП-преобразователя

Пусть дан преобразователь с магазинной памятью; написать программу, которая будет выполнять перевод цепочек с одного языка на другой с помощью заданного преобразователя (теоретический материал раздела 4.2). При невозможности выполнить перевод (цепочка не принадлежит исходному языку) необходимо выводить на экран соответствующее сообщение.

Исходный преобразователь вводить с клавиатуры в соответствии с определённым форматом. Ввод цепочек также производить с клавиатуры, выполняя его до тех пор, пока не возникнет желание закончить работу. Процесс перевода цепочки в виде последовательной смены конфигураций отображать на экране.

Рекомендуется за основу взять программу лабораторной работы №3, дополнив исходные данные выходным алфавитом, функцию переходов – в соответствии с определением преобразователя, а конфигурации – выходными цепочками.

Проверить работу программы на примерах из лекций и задачах из контрольных вопросов.

Дополнительно:

Предоставить пользователю возможность не только вводить данные с клавиатуры, но и загружать преобразователь из файла (аналогично лабораторной работе №2).

 

 

Описание входных данных программы и её результатов

На вход программы подаётся ДМП-преобразователь (множество состояний, алфавиты входного и выходного языков, алфавит магазина, начальное состояние, начальное содержимое стека, множество заключительных состояний, функция переходов в виде списка правил) и проверяемая цепочка символов (аналогично лаб. раб. №3).

На выход: отображение на экране процесса перевода цепочки в виде последовательной смены конфигураций преобразователя, результат перевода – полученная цепочка.

Описание основных переменных, а также основных блоков и подпрограмм

Q - множество состояний.

Vin - множество символов входного алфавита.

Vout - множество символов выходного алфавита.

Z - множество символов магазина.

int F - множество конечных состояний.

nF - число заключительных состояний.

q0 - начальное состояние.

z0 - начальный символ магазина.

nQ - количество состояний.

nVin - количество символов входного алфавита.

nVout - количество символов выходного алфавита.

nZ - количество символов магазина.

Stack - магазин.

struct ConfMod - структура изменения конфигурации.

function ConfMod - функция переходов.

function SymbolSearch - ищет символ, указатель которого ей передается в качестве параметра Symb, в массиве M[][MAX_SYMB_LENGHT].

function SymbolIdentify - читает строку по указателю Str и ищет совпадения с символами, находящимися в массиве M[][MAX_SYMB_LENGHT].

function StackMod - заменяет верхний символ в цепочке магазина на цепочку символов по указателю g, определенную в правиле перехода.

function TranslateString без параметров. Запрашивает ввод цепочки и осуществляет перевод введенной цепочки с входного языка на выходной по алгоритму решения задачи.

 

Алгоритм решения задачи

Устанавливается начальное состояние преобразователя, в магазин добавляется начальный символ и указатель устанавливается на первый символ цепочки. Алгоритм проверки и перевода цепочки заключается в чтении символа из входной цепочки и, в зависимости от полученной тройки состояние/символ цепочки/символ магазина, по правилу перехода определяется новое состояние автомата, символ магазина заменяется на цепочку, в правиле и к выходной цепочке присоединяется цепочка, определенная в правиле перехода. Если правило для какой-либо конфигурации состояние/символ цепочки/символ магазина не определено, может совершаться пустой такт, т.е. правило перехода для комбинации состояние/пустой символ/символ магазина.

Процесс осуществляется в цикле до тех пор, пока:

1. не закончатся символы в цепочке;

2. прочитан неизвестный символ;

3. для полученной комбинации состояние/символ цепочки/символ магазина значение функции не определено и для пустого такта значение не определено;

4. магазин опустеет до прочтения всей цепочки.

Цепочка будет считаться успешно переведенной, если будут прочитаны все символы цепочки, и автомат окажется в одном из заключительных состояний.

 

 

Текст программы:

(main.cpp)

#include <stdio.h>

#include <conio.h>

#include <string.h>

#include <stdlib.h>

#include "main.h"

struct ConfMod // структура изменения конфигурации

{

int q; // новое состояние

char *g; // цепочка для магазина

char *y; // выходная цепочка

};

char Q [MAX_SYMB_COUNT][MAX_SYMB_LENGTH],// множество состояний

Vin[MAX_SYMB_COUNT][MAX_SYMB_LENGTH], // множество входного алфавита

Vout[MAX_SYMB_COUNT][MAX_SYMB_LENGTH], // множество выходного алфавита

Z[MAX_SYMB_COUNT][MAX_SYMB_LENGTH]; // множество символов магазина

int F[MAX_SYMB_COUNT], // множество конечных состояний

nF, // число заключительных состояний

q0, // начальное состояние

z0, // начальный символ магазина

nQ, // количество состояний

nVin, // количество символов входного алфавита

nVout, // количество символов выходного алфавита

nZ; // количество символов магазина

char Stack[MAX_STR_LENGTH]; // магазин

ConfMod func[MAX_SYMB_COUNT][MAX_SYMB_COUNT][MAX_SYMB_COUNT];

int main ()

{

while(true)

{

system("cls");

puts("1 - Ввод ДМП-преобразователя");

puts("2 - Выход");

switch(_getch())

{

case '1':

{

EnterAutomate();

bool end = false;

while(!end)

{

system("cls");

puts("1 - Перевести цепочку");

puts("2 - Назад");

switch(_getch())

{

case '1':

{

RulesView();

int Result = TranslateString();

ResultMessage(Result);

}

break;

case '2':

end = true;

}

}

}

break;

case '2':return 1;

}

}

}

int SymbolSearch(char M[][MAX_SYMB_LENGTH], int Size, char *Symb)

{

int i = 0;

while (i< Size)

{

if (strcmp(M[i], Symb) == 0) break;

i++;

}

return i;

}

int EnterScores(char M[][MAX_SYMB_LENGTH], int max)

{

char Str[MAX_STR_LENGTH];

char *pNextToken = NULL;

int i = 0;

printf("Введите через запятую множество:\n>> ");

gets_s(Str, MAX_STR_LENGTH-1);

char * pToken = strtok_s(Str, ", ", &pNextToken);

while (pToken)

{

strcpy_s(M[i], pToken);

i++;

if(i == max) break;

pToken = strtok_s('\0', ", ", &pNextToken);

}

return i;

}

// Ввод множества конечных состояний

int EnterFinalStates()

{

bool end = false;

char Symb[MAX_SYMB_COUNT][MAX_SYMB_LENGTH];

int i;

while (!end)

{

end = true;

i = 0;

EnterScores(Symb, MAX_SYMB_LENGTH);

if ((F[i] = SymbolSearch(Q, nQ, Symb[i])) == nQ)

{

printf("Символ %s не принадлежит множеству состояний!\n", Symb[i]);

end = false;

}

i++;

}

return i;

}

// Ввод символа

int ControlEnterSymbol(char M[][MAX_SYMB_LENGTH], int Size)

{

char Str[MAX_SYMB_LENGTH];

int index;

while (true)

{

printf(">> ");

gets_s(Str, MAX_SYMB_LENGTH-1);

if ((index = SymbolSearch(M, Size, Str)) == Size)

printf("%s - недопустимый символ!\n", Str);

else break;

}

return index;

}

// Функция возвращает указатель на созданную строку

char *ControlEnterString(char M[][MAX_SYMB_LENGTH], int Size)

{

char Str[MAX_STR_LENGTH];

char *pStr;

bool end = false;

while(!end)

{

printf(">> ");

end = true;

pStr = gets_s(Str, MAX_STR_LENGTH-1);

if(strcmp(Str, "lam") == 0) *pStr = '\0';

while(*pStr)

if(SymbolIdentify(M, Size, &pStr) == Size)

{

puts("В строке присутствуют недопустимые символы!");

end = false;

break;

}

}

pStr = (char *)malloc(strlen(Str)+1);

if(!pStr) return NULL;

strcpy_s(pStr, strlen(Str)+1, Str);

return pStr;

}

// Идентификация первого символа в строке

int SymbolIdentify(char M[][MAX_SYMB_LENGTH], int Size, char **Str)

{

char Symb[MAX_SYMB_LENGTH];

int ind = Size;

if(!**Str) return ind-1;

char *pNextSymb = *Str;

for(unsigned char i=1; (i<=strlen(*Str))&&(i < MAX_SYMB_LENGTH); i++)

{

strncpy_s(Symb, MAX_SYMB_LENGTH, *Str, i);

if(SymbolSearch(M, Size, Symb) < Size)

{

ind = SymbolSearch(M, Size, Symb);

pNextSymb = *Str + i;

}

}

*Str = pNextSymb;

return ind;

}

// Ввод правил переходов

void EnterRules()

{

char Triple [3][MAX_SYMB_LENGTH];

int q, a, z;

memset(func, -1, sizeof(ConfMod)*MAX_SYMB_COUNT*MAX_SYMB_COUNT*MAX_SYMB_COUNT);

system("cls");

do

{

puts("Введите тройку q, a, z для которой создать правило.\nlam - пустая цепочка символов.");

while (true)

{

EnterScores(Triple, 3);

q = SymbolSearch(Q, nQ, Triple[0]);

a = SymbolSearch(Vin, nVin, Triple[1]);

z = SymbolSearch(Z, nZ, Triple[2]);

if ((q==nQ) || (a==nVin) || (z==nZ))

puts("Допущена ошибка! Проверьте, чтобы символы принадлежали своим множествам и повторите ввод.");

else break;

}

puts("Введите новое состояние q' для данного правила.");

func[q][a][z].q = ControlEnterSymbol(Q, nQ);

puts("Введите цепочку магазина");

func[q][a][z].g = ControlEnterString(Z, nZ);

puts("Введите выходную цепочку");

func[q][a][z].y = ControlEnterString(Vout, nVout);

RulesView();

puts("Правило успешно создано");

puts("1 - Ввести новое правило");

puts("2 - Завершить ввод правил");

}

while (_getch()!= '2');

}

// Вывод списка правил на экран

void RulesView()

{

system("cls");

for(int q=0; q<nQ; q++)

for(int a=0; a<nVin; a++)

for(int z=0; z<nZ; z++)

if(func[q][a][z].q!= -1)

{

printf("f(%s, %s, %s) = ", Q[q], Vin[a], Z[z]);

printf("{(%s, ",Q[func[q][a][z].q]);

if(*func[q][a][z].g)

printf("%s, ", func[q][a][z].g);

else printf("lam, ");

if(*func[q][a][z].y)

printf("%s)}\n", func[q][a][z].y);

else printf("lam)}\n");

}

puts("");

}

// Ввод ДМПП с клавиатуры

void EnterAutomate()

{

system("cls");

puts("Ввод состояний");

nQ = EnterScores(Q,MAX_SYMB_COUNT);

puts("Начальное состояние");

q0 = ControlEnterSymbol(Q, nQ);

puts("Ввод конечных состояний");

nF = EnterFinalStates();

puts("Ввод алфавита входного языка");

nVin = EnterScores(Vin, MAX_SYMB_COUNT);

strcpy_s(Vin[nVin], MAX_SYMB_LENGTH, "lam");

nVin++;

puts("Ввод алфавита выходного языка");

nVout = EnterScores(Vout, MAX_SYMB_COUNT);

puts("Ввод алфавита магазина");

nZ = EnterScores(Z, MAX_SYMB_COUNT);

puts("Начальный символ магазина");

z0 = ControlEnterSymbol(Z, nZ);

puts("Ввод правил перехода");

EnterRules();

}

// Вывод мгновенного описания автомата

void PrintConfig(char *w, int q, char *y)

{

printf("(%s, ", Q[q]);

if(!*w) printf("lam, ");

else printf("%s, ", w);

if (!*Stack) printf("lam, ");

else printf("%s, ", Stack);

if(!*y) printf("lam)\n");

else printf("%s)\n", y);

}

// Замена верхнего символа магазина цепочкой из правила перехода

void StackMod(char *g, char *Next)

{

char Buf[MAX_STR_LENGTH];

strcpy_s(Buf, MAX_STR_LENGTH, Next);

strcpy_s(Stack, MAX_STR_LENGTH, g);

strcat_s(Stack, MAX_STR_LENGTH, Buf);

}

// Функция проверки цепочки

int TranslateString()

{

char StrIn[MAX_STR_LENGTH], StrOut[MAX_STR_LENGTH];

StrOut[0] = '\0';

puts("Введите цепочку символов для перевода:");

gets_s(StrIn, MAX_STR_LENGTH-1);

int a, z;

int q = q0; // устанавливаем начальное состояние

strcpy_s(Stack, MAX_STR_LENGTH, Z[z0]); // в магазин помещаем начальный символ

char *w = StrIn; // головку на первый символ цепочки

while(true)

{

PrintConfig(w, q, StrOut); // печатаем МО

if(!*Stack) break; // если магазин опустел - заканчиваем анализ

char *pr = w; // запоминаем текущее расположение головки

// читаем символ, и смещаем головку вправо

if((a = SymbolIdentify(Vin, nVin, &w)) == nVin) return UNDEFINED_SYMBOL; // если не удалось распознать символ цепочки, она не допускается

char *StNext = Stack;

z = SymbolIdentify(Z, nZ, &StNext); // читаем символ магазина

ConfMod NewConf = func[q][a][z];

if(NewConf.q == -1)

{

NewConf = func[q][nVin-1][z];

w = pr; // возвращаем головку на прочтенный символ

if(NewConf.q == -1) return UNDEFINED_STATE;

printf("lam-step: ");

}

q = NewConf.q;

StackMod(NewConf.g, StNext);

strcat_s(StrOut, MAX_STR_LENGTH, NewConf.y);

}

if(*w)return STACK_EMPTY;

for(int i=0; i<nF; i++)

if(q == F[i]) return SUCCESS;

return NO_FINAL_STATE;

}

// Вывод результатов анализа

void ResultMessage(int Result)

{

if(Result!= SUCCESS)

{

puts("Цепочка не принадлежит языку, определяемому данным автоматом! Причина:");

switch(Result)

{

case UNDEFINED_SYMBOL:

puts("Недопустимый символ.");

break;

case UNDEFINED_STATE:

puts("Неопределенное значение для функции перехода.");

break;

case NO_FINAL_STATE:

puts("Автомат не пришел в конечное состояние.");

break;

case STACK_EMPTY:

puts("Опустошение магазина.");

}

}

else puts("Цепочка переведена успешно!");

system("pause");

}

Результаты работы программы

Выполнение перевода τ = {(x,y)| x = 0k1k, y= a2kb2k | k>0}

Ввод преобразователя P =({q0,q1,q2},{0,1},{0,z0},{a,b},δ,q0,z0,{q2})

Ввод списка правил:

Ввод цепочки и результат:

Ввод другой цепочки:

Контрольные вопросы

1. Как поведёт себя преобразователь, если поданная на его вход цепочка не может быть распознана (не принадлежит к заданному языку)?

Ответ: если поданная на вход преобразователя цепочка не может быть распознана, то выйдет предупреждающее сообщение и перевод прекратиться.

 

2. Как соотносятся алфавиты исходного языка и того, на который выполняется перевод (должны совпадать, различаться…)? Поясните ответ.

Ответ: входной и выходной алфавиты могут полностью совпадать, могут полностью различаться, могут пересекаться. Потому-что при переводе символы входного и выходного алфавита никак не смешиваются (как, например, терминальные и нетерминальные символы грамматики при выводе цепочек), так как перевод осуществляется в отдельную цепочку символов.

 

3. Как поведёт себя Ваша программа при некорректном вводе? Например, функция переходов задана не в том формате, определена не для того количества параметров, использует алфавит, отличный от заданных…

Ответ: при некорректном вводе программа предложит повторный ввод. Поскольку программа полностью контролирует ввод правил перехода, принадлежность введенных символов своим множествам.

 

1. Замечание то же, что в работе №2.

2. Плюс к этому следовало проверить программу на контрольных вопросах – этого не сделано. Добавьте скриншоты с решением контрольного вопроса №6 из соответствующего раздела теории.

 

1. Дан МП-преобразователь: P = ({q},{a,+,*},{+,*,E},{a,+,*},δ, q,E,{q}), где δ определяется равенствами:

δ(q, *, E) = {(q, EE*, l)} δ(q, l, +) = {(q, l, +)} δ(q, a, E) = {(q, l, a)} δ(q, +, E) = {(q, EE+, l)} δ(q, l, *) = {(q, l, *)}

Выполнить перевод цепочек: а) ’++aaa’; б) ’*+aaa’; в) ’*+aaa’; г) ’+a*aa’.

 

Федеральное агентство связи

 

Сибирский Государственный Университет Телекоммуникаций и Информатики



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2022-11-28 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: