Mała baza danych

Program zaliczeniowy ? wersja finalna ? 2008-10-23.
Program zaliczeniowy polega na napisaniu aplikacji w C++. Celem aplikacji jest wykonywanie prostych
programów na danych.
Programem nazywamy listę kolejnych operacji na danych.
Każdy program jest postaci:
operacja 
operacja 
....
operacja 
Każda operacja jest pewnym przekształceniem plików z danymi.
Są dostępne następujące operacje:
? Operacja filtrowania
? Składania: FILTER     .
?  =, !=, >, <, >=, <=.
? Schemat pliku wynikowego jest taki sam jak źródłowego.
? Operacja dołączenia
? Składnia: MERGE   
? Operacja polega na zsumowaniu kolumn plików 1 i 2.
? Operacja powiedzie się jeśli kolumny plików 1 i 2 mają inne nazwy oraz ilość wierszy w pliku 1 i
w pliku 2 jest taka sama.
? Wynikowy plik ma wszystkie kolumny pliku 1 i wszystkie kolumny pliku 2.
? Operacja łączenia
? Składnia: JOIN   
? Operacja polega na wypisaniu do pliku docelowego najpierw zawartości pliku1 a za nim pliku2.
? Operacja jest wykonalna tylko i wyłącznie, gdy ilość kolumn pliku1 i pliku2 jest taka sama i typy
kolejnych kolumn są takie same.
? Wynikowy plik ma schemat taki sam jak plik1.
? Operacja wyliczenia
? Składnia: AGREGATE     
?  oznacza operację z listy: maksimum [MAX], minimum [MIN], suma [SUM], średnia
[AVG] (zaokrąglenie do int'a), ilość [COUNT].
? Operacja powiedzie się jeśli typ danych jest zgodny z operacją.
? Wynikowy plik ma strukturę złożoną z jednej kolumny o podanej nazwie typu int oraz zawiera
jeden wiersz z wynikiem operacji.
? Operacja dodania danych.
? Składnia: INSERT    ... 
? Operacja dodaje wiersz danych na końcu pliku danych.
? Operacja się powiedzie jeśli ilość danych zgadza się z listą kolumn oraz typu danych się
zgadzają.
? Operacja ładowania danych.
? Składnia: LOAD   
? Operacja odczytuje linia po linii dane z pliku wejściowego i dopisuje je na końcu wskazanego
pliku.
? Dane w pliku z danymi są zapisane linia po linii.
? Każda linia zawiera jeden rekord danych.? Każda linia zawiera pewną ilość pól postaci   ... 
? Każda wartość jest zapisana w formacie wartości przyjmowanym we wszystkich
komendach.
? Operacja się powiedzie jeśli ilość danych zgadza się z listą kolumn oraz typu danych się
zgadzają.
? Operacja stworzenia pustego pliku.
? Składnia: CREATE    ... 
? Operacja tworzy pusty plik o podanej strukturze.
? Dodatkowa operacja wypisania pliku.
? Składnia: PRINT 
? Operacja nie posiada żadnego wyjścia.
? Operacja powinna wypisać na standardowe wyjście zawartość danego pliku (oczywiście w
postaci zinterpretowanej).
? Dane powinny być wypisane wierszami. Pierwszy wiersz powinien być w postaci:   ...  
? Kolejne wiersze powinny zawierać kolejne wartości pól (w odpowiedniej kolejności) zapisanie w
formacie , czyli np. 'M &38; M' oznacza wartość ?M & M?.
Legenda:
?  - pole postaci 'łańcuch znaków bez znaku ' , & oraz znaku nowej linii. Znaki ', & oraz
nowej linii są zapisywane jako &;'
? Wszelkie nazwy plików, kolumn, etc. są ciągami znaków [a-z] i [A-Z] oraz [0-9] oraz znaku _ o
długości maksymalnie 50 znaków.
?  oznacza typ danych. Są dwa typy, string ? oznacza łańcuch znaków dowolnej długości oraz
int oznacza liczę 32 bitową ze znakiem.
Schemat działania aplikacji składa się z następujących kroków:
1. Wczytanie programu.
2. W pętli dla każdej komendy.
3. Wykonaj komendę.
Wykonanie każdej komendy polega na:
1. Wczytaniu plików źródłowych do pamięci.
2. Wykonanie komendy w pamięci na danych w pamięci.
3. Zapis danych do plików docelowych.
Aplikacja powinna zapisywać wszelkie dane w lokalnym katalogu. Każdy błąd w programie jest
krytyczny i powinien przerywać działanie aplikacji. Program powinien być wczytywany ze
standardowego wejścia. Wszelkie błędy odczytu/zapisu na dysk są błędami krytycznymi. Struktura
danych w plikach dowolna, wg własnych pomysłów. Optymalizacja implementacji komend nie jest
priorytetem. Można założyć, że w każdej chwili działania programu całość danych w plikach mieści się
w pamięci. W plikach nie może być wartości NULL.
Przykład programu:
CREATE tabela1 dzial string zarobki int
INSERT tabela1 tabela1 'Zarząd' '10000'
INSERT tabela1 tabela1 'Zarząd' '15000'
INSERT tabela1 tabela1 'Zarząd' '12000'
INSERT tabela1 tabela1 'IT' '4000'
INSERT tabela1 tabela1 'Administracja' '2000'
INSERT tabela1 tabela1 'IT' '4000'INSERT tabela1 tabela1 'Zarząd' '19000'
INSERT tabela1 tabela1 'IT' '5000'
FILTER tabela2 tabela1 dzial = 'Zarząd'
AGREGATE tabela3 tabela2 zarobki SUM zarobki
FILTER tabela2 tabela1 dzial = 'IT'
AGREGATE tabela4 tabela2 zarobki SUM zarobki
JOIN tabela3 tabela3 tabela4
PRINT tabela3
Po wykonaniu programu w tabeli 3 powinny być dwa wiersze. Pierwszy powinien zawierać sumę
zarobków zarządu zaś drugi sumę zarobków działu IT.
Po wypisaniu na standardowym wyjściu powinno być:
zarobki int
'56000'
'13000'

A oto rozwiązanie:

#include 
#include 
#include 
#include 
#include 
#define round(x) (x<0?ceil((x)-0.5):floor((x)+0.5))

const int ERR_FILE=1;
const int ERR_LAST_TYPE_MISSING=2;
const int ERR_BAD_TYPE=3;
const int ERR_NUM_ROWS=4;
const int ERR_NAME=5;
const int ERR_TYPE=6;
const int ERR_NUM_COL=7;
const int ERR_AGGR=8;
const int ERR_AMP=9;
const int ERR_ASCII=10;
const int ERR_APO=11;
const int ERR_NAME_LEN=12;
const int ERR_NAME_CHAR=13;
const int ERR_COMM=14;

using namespace std;

	int str2int(string wartosc)
	{
		int liczba=0;
		for(int i=0;i='0')&&(wartosc[i]<='9'))
			{
				liczba=liczba*10+(wartosc[i]-'0');
			}
		}
		return liczba;
	}

	void my_itoa(int value, string& buf, int base){
		
		int i = 30;
		
		buf = "";
		
		for(; value && i ; --i, value /= base) buf = "0123456789abcdef"[value % base] + buf;
		
	}


	string AsciiEncode(string wartosc_string)
	{
		string zwroc="";
		//zamieniamy ' & ; n
		for(int i=0;i")
		{
			if(typ=="int")
			{
				if(wartosc_int>liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string>wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja==">=")
		{
			if(typ=="int")
			{
				if(wartosc_int>=liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string>=wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja=="<=")
		{
			if(typ=="int")
			{
				if(wartosc_int<=liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string<=wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja=="=")
		{
			if(typ=="int")
			{
				if(wartosc_int==liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string==wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja=="!=")
		{
			if(typ=="int")
			{
				if(wartosc_int!=liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string!=wartosc)
				{
					wynik=1;
				}
			}
		}
		else if(operacja=="<")
		{
			if(typ=="int")
			{
				if(wartosc_int<liczba)
				{
					wynik=1;
				}
			}
			else
			{
				if(wartosc_string<wartosc)
				{
					wynik=1;
				}
			}
		}
		else
		{
			wynik=-1; //nieznany operator.
		}

		return wynik;
	}

	string Wypisz_typ()
	{
		return nazwa+" "+typ;
	}

	string Wypisz(int zamien)
	{
		string zwroc="";
		
		if(zamien)
		{
			zwroc=AsciiEncode(wartosc_string);
		}
		else
		{
			zwroc=wartosc_string;
		}

		
		return "'"+zwroc+"'";
	}


}; // Koniec klasy Pole.




//Klasy reprezentujace wiersze tabel

class Wiersz
{
	public:
	vector  pola;
	Wiersz(vector  dane) : pola(dane){}
	Wiersz() {}
	string Wypisz(int zamien)
	{
		string wypisz="";
		int ile=pola.size();
		for(int i=0;i0)
		{
			wypisz+=pola.at(ile-1).Wypisz(zamien);
		}


		return wypisz;
	}
}; // Koniec klasy Wiersz.




//Klasa reprezentujaca tabele z danymi.
class Tabela
{

public:
	vector  wiersze;
	vector  typy;

	void Czysc()
	{
		wiersze.clear();
		typy.clear();
	}

	Pole Agreguj(string funkcja,string kolumna)
	{
		int kol=Kolumna(kolumna);
		Pole wynik;
		int suma=0;
		int min=0;
		int max=0;
		string min_str="";
		string max_str="";

		if(kol==-1)
		{
			
			wynik.typ="blad";
		}
		else
		{
			min=wiersze.at(0).pola.at(kol).wartosc_int;
			max=min;
			min_str=wiersze.at(0).pola.at(kol).wartosc_string;
			max_str=min_str;
			

			for(int i=0;i<wiersze.size();i++)
			{
				suma+=wiersze.at(i).pola.at(kol).wartosc_int;

				//min
				if(wiersze.at(i).pola.at(kol).wartosc_int<min)
				{
					min=wiersze.at(i).pola.at(kol).wartosc_int;
				}

				if(wiersze.at(i).pola.at(kol).wartosc_stringmax)
				{
					max=wiersze.at(i).pola.at(kol).wartosc_int;
				}

				if(wiersze.at(i).pola.at(kol).wartosc_string>max_str)
				{
					max_str=wiersze.at(i).pola.at(kol).wartosc_string;
				}
			}


			if(funkcja=="COUNT")
			{
				wynik.wartosc_int=wiersze.size();
				my_itoa(wiersze.size(),wynik.wartosc_string,10);
				wynik.typ="int";
			}
			else if(funkcja=="MAX")
			{
				wynik.typ=typy.at(kol).typ;
				if(wynik.typ=="int")
				{
					wynik.wartosc_int=max;
					my_itoa(max,wynik.wartosc_string,10);
				}
				else
				{
					wynik.wartosc_string=max;
				}
				
			}
			else if(funkcja=="MIN")
			{
				wynik.typ=typy.at(kol).typ;
				if(wynik.typ=="int")
				{
					wynik.wartosc_int=min;
					my_itoa(max,wynik.wartosc_string,10);
				}
				else
				{
					wynik.wartosc_string=min;
				}
				
			}
			else if((funkcja=="AVG")&&(typy.at(kol).typ=="int"))
			{
				wynik.typ="int";
				wynik.wartosc_int=round(suma/wiersze.size());
				my_itoa(wynik.wartosc_int,wynik.wartosc_string,10);
			}
			else if((funkcja=="SUM")&&(typy.at(kol).typ=="int"))
			{
				wynik.typ="int";
				wynik.wartosc_int=suma;
				my_itoa(wynik.wartosc_int,wynik.wartosc_string,10);
			}
			else
			{
				wynik.typ="blad";//blad.
			}

			
		}

		return wynik;
	}

	int Kolumna(string nazwa)
	//zwraca numer kolumny.
	{
		int znalezione=-1; //blad.
		for(int i=0;i<typy.size();i++)
		{
			if(typy.at(i).nazwa==nazwa)
			{
				znalezione=i;
				break;
			}
		}
		return znalezione;
	}

	int Filtruj(string kolumna, string operacja, string wartosc)
	{
		int blad=0;
		int kol=Kolumna(kolumna);

		if(kol!=-1)
		{
			for(int i=0;i<wiersze.size();i++)
			{
				
				int odp=wiersze.at(i).pola.at(kol).Porownaj(operacja,wartosc);
				if(odp==-1)
				{
					blad=61; //zly operator.
					break;
				}
				else if(odp==0)
				{
					wiersze.erase(wiersze.begin()+i,wiersze.begin()+i+1);
					i=i-1;
				}
			}
		}
		else
		{
			blad=51; //nie ma takiej kolumny.
		}

		return blad;
	}

	int Serializuj(string nazwa)
	{
		int blad=0;
		fstream plik;
		plik.open((nazwa+"_data.txt").c_str(),ios::out);
		if(plik.good())
		{

			plik<<"CREATE "<<nazwa<<" ";
			//zapisujemy.
			//Najpierw typy.
			for(int i=0;i<typy.size();i++)
			{
				plik<<"'"<<typy.at(i).nazwa<<"' "<<typy.at(i).typ<<" ";
			}
			plik<<"n";

			//Teraz dane.
			for(int i=0;i<wiersze.size();i++)
			{
				plik<<"INSERT "<<nazwa<<" "<<nazwa<<" "<<wiersze.at(i).Wypisz(1)<<"n";
			}

			plik.close();
		}
		else
		{
			blad=41;//nie ma dostepu do pliku.
		}

		return blad;
	}

	int Dodaj(vector  pola)
	{
		Wiersz w;
		w.pola=pola;
		wiersze.push_back(w);
		return 0;
	}

	int Utworz(vector  typ,int poczatek)
	{
		int blad=0;

		for(int i=poczatek;i<typ.size();i+=2)
		{
			typy.push_back(Pole(typ.at(i),typ.at(i+1),"1"));
		}
		
		return blad;
	}

	int Wstaw(vector dane,int poczatek)///////////////////////
	{
		int blad=0;

		vector tmp; 
		if(dane.size()-poczatek==typy.size())
		{
			for(int i=poczatek;i<dane.size();i++)
			{
				Pole tymczas=Pole(typy.at(i-poczatek).nazwa,typy.at(i-poczatek).typ,dane.at(i));
				tmp.push_back(tymczas);
				
			}
			
			if(blad==0)
			{
				Dodaj(tmp);
			}
		}
		else
		{
			blad=11; //Niepoprawna ilosc danych
		}
		return blad;
	}

	void Wypisz()
	{
		//Wypisujemy typy
		for(int i=0;i<typy.size();i++)
		{
			cout<<typy.at(i).Wypisz_typ()<<" ";
		}
		cout<<"n";

		//Teraz wiersze
		int ile=wiersze.size();
		for(int i=0;i<ile;i++)
		{
			cout<<wiersze.at(i).Wypisz(0)<<"n";
		}
	}

}; // Koniec klasy tabela.




class Parser
{
private:
	vector  klucze;
	string komenda;
public:
	int blad;		//Kod bledu.
	Tabela tabelka1;
	Tabela tabelka2;

	Parser() : blad(0){}

	void Czysc()
	{
		tabelka1.Czysc();
		tabelka2.Czysc();
		klucze.clear();
		komenda="";
	}

	int Wczytuj(string nazwa)
	{
		fstream plik;
		plik.open((nazwa+"_data.txt").c_str(),ios::in);
		if(plik.good())
		{
			string dane;
			while(getline(plik,dane))
			{
				Wykonaj(dane);
			}
			
			plik.close();
		}
		else
		{
			blad=ERR_FILE;
			cout<<"Problem z plikiem wejsciowym n-----n"<<komenda;
			throw(ERR_FILE);
		}
		
		return blad;
	}

	Tabela Deserializuj(string nazwa)
	{
		Parser pars;
		blad=pars.Wczytuj(nazwa);
		return pars.tabelka1;
	}

	int Insert()
	{
		Nazwa(1);
		Nazwa(2);
		tabelka1=Deserializuj(klucze.at(2));
		blad=tabelka1.Wstaw(klucze,3);

		if(blad==0)
		{
			blad=tabelka1.Serializuj(klucze.at(1));
		}

		return blad;
	}

	int Create()
	{
		for(int i=2;iklucze.size()-1)
			{
				cout<<"Brak typu ostatnigon-------n"<<komenda;
				blad=ERR_LAST_TYPE_MISSING;
				throw(blad);
			}
			else if((klucze.at(i+1)!="string")&&(klucze.at(i+1)!="int"))
			{
				cout<<"Nieprawidlowy typn-------n"<<komenda;
				blad=ERR_BAD_TYPE; //Nieprawidlowy typ.
				throw(blad);
			}
		}

		if(blad==0)
		{
			blad=tabelka1.Utworz(klucze,2);
		}

		if(blad==0)
		{
			blad=tabelka1.Serializuj(klucze.at(1));
		}


		return blad;
	}

	int Filter()
	{
		//Filtruje.
		//Czytamy tabele do przefiltrowania
		tabelka1=Deserializuj(klucze.at(2));
		//Usuwamy niepasujace wiersze
		blad=tabelka1.Filtruj(klucze.at(3),klucze.at(4),klucze.at(5));
		//Zapisujemy:
		blad=tabelka1.Serializuj(klucze.at(1));
		return blad;
	}

	int Load()
	{
		//Laduje dane.
		Parser parserek;
		string wiersz;
		//Otwieramy plik:
		fstream plik;
		tabelka1=Deserializuj(klucze.at(2));
		if (blad==0)
		{
			plik.open(klucze.at(3).c_str(),ios::in);
			if(plik.good())
			{
				
				//Zwalimy robote na juz napisana funkcje:
				while((blad==0)&&(getline(plik,wiersz)))
				{
					blad=parserek.Przetworz(wiersz);

					if(blad==0)
					{
						blad=tabelka1.Wstaw(parserek.klucze,0);
					}
				}

				if(blad==0)
				{
					blad=tabelka1.Serializuj(klucze.at(1));
				}
			}
			else
			{
				cout<<"Problem z plikiem wejsciowym n-----n"<<komenda;
				blad=ERR_FILE;
				throw(blad);
			}
		}
		else
		{
			cout<<"Problem z plikiem wejsciowym n-----n"<<komenda;
			blad=ERR_FILE;
			throw(blad);
		}

		return blad;
	}

	int Merge()
	{
		tabelka1=Deserializuj(klucze.at(2));
		if(blad==0)
		{
			
			tabelka2=Deserializuj(klucze.at(3));
			if(blad!=0)
			{
			}
			else if(tabelka1.wiersze.size()==tabelka2.wiersze.size())
			{
				for(int i=0;i<tabelka1.typy.size();i++)
				{
					if(tabelka1.typy.at(i).nazwa==tabelka2.typy.at(i).nazwa)
					{
						blad=72;//taka sama nazwa.
						break;
					}
				}

				if(blad==0)
				{
					//Dopisujemy typy
					tabelka1.typy.insert(tabelka1.typy.end(),tabelka2.typy.begin(),tabelka2.typy.end());
					//Dopisujemy kolumny.
					for(int i=0;i<tabelka2.wiersze.size();i++)
					{
						tabelka1.wiersze.at(i).pola.insert(tabelka1.wiersze.at(i).pola.end(),tabelka2.wiersze.at(i).pola.begin(),tabelka2.wiersze.at(i).pola.end());
					}
					//zapisujemy:
					tabelka1.Serializuj(klucze.at(1));
				}
			}
			else
			{
				cout<<"Zła liczba wierszy n-----n"<<komenda;
				blad=ERR_NUM_ROWS;
				throw(blad);
			}
		}
		return blad;
	}

	int Join()
	{
		tabelka1=Deserializuj(klucze.at(2));
		if(blad==0)
		{
			
			tabelka2=Deserializuj(klucze.at(3));
			if(blad!=0)
			{
			}
			else if(tabelka1.typy.size()==tabelka2.typy.size())
			{
			
				for(int i=0;i<tabelka1.typy.size();i++)
				{
				
					if(tabelka1.typy.at(i).nazwa!=tabelka2.typy.at(i).nazwa)
					{
						cout<<"Zła nazwa n-----n"<<komenda;
						blad=ERR_NAME;
						throw(blad);
					}
					else if(tabelka1.typy.at(i).typ!=tabelka2.typy.at(i).typ)
					{
						cout<<"Zły typ n-----n"<<komenda;
						blad=ERR_TYPE;
						throw(blad);
					}
				}

				if(blad==0)
				{
					//Dopisujemy wiersze.
					for(int i=0;i<tabelka2.wiersze.size();i++)
					{
						tabelka1.wiersze.push_back(tabelka2.wiersze.at(i));
					}
					//zapisujemy:
					tabelka1.Serializuj(klucze.at(1));
				}
			}
			else
			{
				cout<<"Zła liczba kolumn n-----n"<<komenda;
				blad=ERR_NUM_COL;
				throw(blad);
			}
		}

		return blad;
	}

	int Agregate()
	{
		tabelka1=Deserializuj(klucze.at(2));
		Pole wynik=tabelka1.Agreguj(klucze.at(4),klucze.at(5));
		
		if(wynik.typ=="blad")
		{
			cout<<"Problem agregacji n-----n"<<komenda;
			blad=ERR_AGGR;
			throw(blad);
		}
		else
		{
			wynik.nazwa=klucze.at(3);
			//Tworzymy tabelke z wynikiem.
			vector tmp;
			tmp.push_back(wynik);
			tabelka2.typy=tmp;
			tabelka2.Dodaj(tmp);
			tabelka2.Serializuj(klucze.at(1));
		}

		return blad;
	}

	int Print()
	{
		tabelka1=Deserializuj(klucze.at(1));
		tabelka1.Wypisz();
		return blad;
	}


	int Przetworz(string polecenie)
	//Przetwarza polecenia na wektor z tokenami.
	{
		komenda=polecenie;
		polecenie.insert(polecenie.end(), 1, ' ');//spacja na koniec.
		int ile=polecenie.length();
		string teraz="";
		string tmp;
		int otwarty=0; // otwarty apostrof.
		int kod=0;

		klucze.clear();

		//Przetwarzamy polecenie litera po literze.
		for(int i=0;i<ile;i++)
		{
			if(polecenie[i]=='&')
			{
				kod=0;
				//zamieniamy na ascii.
				i++;
				while((polecenie[i]!=';')&&(i<ile))
				{
					kod=kod*10+(polecenie[i]-'0');
					i++;
				}

				if(i==ile)
				{
					cout<<"Niedokończone & n-----n"<<komenda;
					blad=ERR_AMP;
					throw(blad);
				}
				else if((kod255))
				{
					cout<<"Zły kod ASCII n-----n"<0)
				{
					klucze.push_back(teraz);
					teraz="";
				}
			}
			else
			{
				teraz.insert(teraz.end(), 1, polecenie[i]);
			}

		}

		if(otwarty==1)
		{
			cout<<"Niedokończony apostrof n-----n"<50)
			{
				cout<<"Za długa nazwa n-----n"<<komenda;
				blad=ERR_NAME_LEN;
				throw(blad);
			}
			else
			{
				for(int i=0;i='a')&&(tmp[i]='A')&&(tmp[i]='0')&&(tmp[i]<='9'))))
					{
						cout<<"Zły znak w nazwie n-----n"<<komenda;
						blad=ERR_NAME_CHAR;
						throw(blad);
					}
				}
			}
		}
		return blad;
	}


	int Zrob()
	{

			if(klucze.at(0)=="INSERT")
			{
				blad=Insert();
			}
			else if(klucze.at(0)=="CREATE")
			{
				blad=Create();
			}
			else if(klucze.at(0)=="FILTER")
			{
				blad=Filter();
			}
			else if(klucze.at(0)=="AGREGATE")
			{
				blad=Agregate();
			}
			else if(klucze.at(0)=="JOIN")
			{
				blad=Join();
			}
			else if(klucze.at(0)=="PRINT")
			{
				blad=Print();
			}
			else if(klucze.at(0)=="MERGE")
			{
				blad=Merge();
			}
			else if(klucze.at(0)=="LOAD")
			{
				blad=Load();
			}
			else
			{
				cout<<"Nieznana komenda n-----n"<<komenda;
				blad=ERR_COMM;
				throw(blad);
			}
		return blad;
	}


	int Wykonaj(string polecenie)
	{
		Przetworz(polecenie);
		
		if(blad==0)
		{
			Zrob();
		}

		return blad;
	}


};  // Koniec klasy Parser.





int main()
{
	Parser pars;
	string wiersz;

	int blad=0;
	while((blad==0)&&(getline(cin,wiersz)))
	{	
		pars.Wykonaj(wiersz);
		blad=pars.blad;
		pars.Czysc();
	}

	return 0;
}