#include <boost/xpressive/xpressive.hpp>
#include <iostream>
#include <boost/foreach.hpp>

using namespace std;
using namespace boost::xpressive;
using namespace boost;

string recursive_depth_space(int recursive_depth){
	string tabs;	
	for(int i =0; i < recursive_depth; i++)
		tabs += "  ";
	return tabs;
}

void recursive_display_nested_results ( boost::xpressive::smatch::nested_results_type::const_iterator begin,
										boost::xpressive::smatch::nested_results_type::const_iterator end,
										int recurisive_depth){

	boost::xpressive::smatch::nested_results_type::const_iterator beg = begin;

	for(; beg != end; beg++){
		if(beg->nested_results().size()==0){
			cout << recursive_depth_space(recurisive_depth) << beg->str() <<endl;
		}
		else{
			recursive_display_nested_results(beg->nested_results().begin(), beg->nested_results().end(), recurisive_depth + 1);
		}
	}
}


int main(){
	cout << "autor: Michal Przychodzen." << endl;
	cout << "Prezentacja mozliwosci biblioteki boost::xpressive" << endl;
	cout << "==================================================" << endl;
	
	cout << endl;
	cout << "wyrazenia regularne" << endl;
	cout << "==================================================" << endl;
	cout << " - sprawdzanie recursive_display_nested_results do wzorca" << endl;
	cout << " - wyszukiwanie wzorca" << endl;
	cout << " - wyszukiwanie wszystkich wystapien wzorca" << endl;
	cout << "==================================================" << endl;
	cout << endl;

	/* Utworzenie statycznego wyrażenia (dla obiektu string) */
	/* Wyrażenie tworzone jako string i kompilowane */
	string wyrazenie_str("<.*?>");

	/* kompilowane wyrażenie jak w perlu */
	sregex wyrazenie = sregex::compile(wyrazenie_str);
	smatch dopasowanie;

//	string tekst("<html><head></head><body><h1></h1><p></p></body></html>");
	string tekst("<html><body></body></html>");
		
	cout << "Bazowy tekst: " << endl << tekst << endl;

	/* Sprawdzenie czy podany string można dopasować do wyrażenia */
	/* za pomocą pełnego recursive_display_nested_results */
	cout << "1a. regex_match <.*?>: " 
		 << (regex_match(tekst, dopasowanie, wyrazenie) ? string("Dopasowany: ").append(dopasowanie.str()) : "Niedopasowany") 
		 << endl;
	
	/* również sub_stringi */
	cout << "1b. regex_search <.*?>: " 
		 << (regex_search(tekst, dopasowanie, wyrazenie) ? string("Dopasowany: ").append(dopasowanie.str()) : "Niedopasowany") 
		 << endl;
	
	/* wyrażenie perlowe .tm w składni c++ : */
	wyrazenie =  _ >> as_xpr('t') >> as_xpr('m');	

	/* Sprawdzenie czy podany string można dopasować do wyrażenia */
	cout << "2a. regex_match <.>: "
		 << (regex_match(tekst, dopasowanie, wyrazenie) ? string("Dopasowany: ").append(dopasowanie.str())  : "Niedopasowany") 
		 << endl;
	
	cout << "2b. regex_search <.>: "
		 << (regex_search(tekst, dopasowanie, wyrazenie) ? string("Dopasowany: ").append(dopasowanie.str())  : "Niedopasowany") 
		 << endl;

	/* wyrażenie perlowe  <.*> w składni c++ */
	wyrazenie = "<" >> *_ >> ">";	

	/* Sprawdzenie czy podany string można dopasować do wyrażenia */
	cout << "3a. regex_match <.*>: " 
		 << (regex_match(tekst, dopasowanie, wyrazenie) ? string("Dopasowany: ").append(dopasowanie.str())  : "Niedopasowany") 
		 << endl;

	cout << "3b. regex_search <.*>: "
		 << (regex_search(tekst, dopasowanie, wyrazenie) ? string("Dopasowany: ").append(dopasowanie.str())  : "Niedopasowany") 
		 << endl;

	/* wyrażenie perlowe  <.*> w składni c++ */
	wyrazenie = "<" >> *_ >> ">";	


	cout << "4a. regex_iterator <.*>:  Znalezione recursive_display_nested_results: " 
		 << endl;

	/* Wszystkie dopasowane sub_stringi */
	sregex_iterator current(tekst.begin(), tekst.end(), wyrazenie);
	sregex_iterator end;
	
	for(;current != end; current++){
		cout << current->str()<< endl;
	}

	/* wyrażenie perlowe <.*?> w składni c++ */
	wyrazenie = "<" >> (s1 = -*_) >> ">";	

	cout << "4b. regex_iterator <.*?>:  Znalezione recursive_display_nested_results: " 
		 << endl;

	/* Wszystkie dopasowane sub_stringi */
	current = sregex_iterator(tekst.begin(), tekst.end(), wyrazenie);
	
	for(;current != end; current++){
		cout << current->str()<< endl;
	}

	cout << endl;
	cout << "5. Rozszerzone mozliwosci ktorych nie maja wyrazenia regularne" << endl;
	cout << "==================================================" << endl;
	cout << endl;
	
	/* Definiujemy uproszczoną budowę dokumentu HTML */
	sregex open_tag =  "<" >> -*alnum >> ">"; // <tag>
	sregex close_tag = as_xpr("</") >> -*alnum >> ">"; // </tag>
	sregex intext =  *(_w); // insidetag
	//	sregex basic_tag = open_tag  >> !intext >> close_tag; // <tag>insidetag</tag> || <tag></tag> 
	//	sregex tag = (open_tag >> *basic_tag >> close_tag | by_ref(tag) );  
	

	sregex tag = open_tag  >> ( !intext | *by_ref(tag) ) >> close_tag; 
	sregex document = tag;

	smatch what;
	tekst = "<html><head><title>Tytul</title></head><body><h1>Naglowek</h1><p1>"\
 			"Akapit</p1><table><tr><td>naglowek</td><td>naglowek</td><td>naglowek</td></tr><tr><td>A</td><td>B</td>"\
			"<td>C</td></tr><tr><td>1</td><td>2</td><td>3</td></tr></table></body></html>";
	
	while(tekst.length() > 1){
		if(regex_match(tekst, what, document)){
			cout << "Dopasowano dokument HTML:" << endl << tekst << endl << endl;
			recursive_display_nested_results(what.nested_results().begin(), what.nested_results().end(), 0);	
		}
		cin>>tekst;
	}

	return 0;
}