Różnice między wybraną wersją a wersją aktualną.
Both sides previous revision Previous revision Next revision | Previous revision Last revision Both sides next revision | ||
spirit [2008/04/16 07:44] bwojcies |
spirit [2008/04/17 00:11] bwojcies |
||
---|---|---|---|
Linia 1: | Linia 1: | ||
+ | |||
====== Biblioteka Boost Spirit ====== | ====== Biblioteka Boost Spirit ====== | ||
Bartłomiej Wojcieszek G1SST | Bartłomiej Wojcieszek G1SST | ||
Linia 5: | Linia 6: | ||
Parser, zwany także analizatorem składniowym, pozwala na analize danych wejściowych i określenie czy są zgodne z daną gramatyką. Zazwyczaj parsery są wykorzystywane przy przetwarzaniu danych zrozumialych dla czlowieka w dane najbardziej wygodne dla komputera. | Parser, zwany także analizatorem składniowym, pozwala na analize danych wejściowych i określenie czy są zgodne z daną gramatyką. Zazwyczaj parsery są wykorzystywane przy przetwarzaniu danych zrozumialych dla czlowieka w dane najbardziej wygodne dla komputera. | ||
- | Biblioteka Spirit pozwala tworzyć własne złożone parsery lub wykorzytywać te najprostsze wbudowane w bibliotekę. Szablony wyrażeń zastosowanych w bibliotece pozwalają na zapis w notcacji bardzo podobnej do EBNF (Extended Backus-Normal Form): | + | Biblioteka Spirit pozwala tworzyć własne złożone parsery lub wykorzytywać te najprostsze wbudowane w bibliotekę. Szablony wyrażeń zastosowanych w bibliotece pozwalają na zapis w notacji bardzo podobnej do EBNF (Extended Backus-Normal Form): |
\\ Gramatyka EBNF: | \\ Gramatyka EBNF: | ||
<code cpp> | <code cpp> | ||
Linia 179: | Linia 180: | ||
my_rule=str_p("blaBla"); | my_rule=str_p("blaBla"); | ||
</code> | </code> | ||
+ | |||
====Dyrektywy==== | ====Dyrektywy==== | ||
Linia 195: | Linia 197: | ||
integer = lexeme_d[ !(ch_p('+') | '-') >> +digit ]; | integer = lexeme_d[ !(ch_p('+') | '-') >> +digit ]; | ||
+ | |||
+ | //Dyrektywa limit_d ogranicza min i max w jakim może się znajdować parsowane wyrażenie | ||
+ | //Stwórzmy np. parser przyjmujący date w formacie: dd.mm.yyyy i zakładamy że interesują nas tylko daty z lat 2000 do 2010: | ||
+ | |||
+ | uint_parser<int, 10, 2, 2> uint2_p; | ||
+ | uint_parser<int, 10, 4, 4> year; | ||
+ | |||
+ | lexeme_d | ||
+ | [ | ||
+ | limit_d(1, 31)[uint2_p] >> '.' // dni od 1 do 31 | ||
+ | >> limit_d(1, 12)[uint2_p] >> '.' // miesiace od 1 do 12 | ||
+ | >> limit_d(2000,2010)[year] // rok ograniczony latami 2000 do 2010 | ||
+ | ] | ||
+ | |||
</code> | </code> | ||
- | ==== Bardziej użyteczny przykład ==== | ||
+ | ==== Akcje semantyczne ==== | ||
+ | Jak już wcześniej wspomniałem możemy użyć funkcji które będą wyzwalane w momencie pozytywnego sparsowania. Dzięki temu można łatwo tworzyć program w którym po sparsowaniu analizujemy to co było no wejściu. Za pomocą funkcji możemy także generować osrtrzeżenia o niepoprawnych argumentach itp. | ||
+ | Prosty przykład: | ||
- | ==== Wykorzytanie funkcji ==== | + | <code cpp> |
+ | void | ||
+ | action(char const* first, char const* last) | ||
+ | { | ||
+ | std::string str(first, last); | ||
+ | std::cout << str << std::endl; | ||
+ | } | ||
+ | |||
+ | rule<> myrule = (ch_p(a) | int_p >> *(int_p >> ch_p('x')))[&action]; | ||
+ | //w momencie poprawnego sparsowania, funkca wypisze w postaci stringa wszystkie sparsowane elementy | ||
+ | </code> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ==== Zbierzmy wszystko razem ==== | ||
+ | Po tych podstawach, przydałoby się napisać krótki program ilustrujący faktyczne działanie biblioteki Spirit. Podany program zamienia formatowanie w stylu wiki na dokument html. Aby rozpocząc wprowadzanie należy otworzyć klamrę { a po zakończonym wprowadzaniu zamknąć klamrą }. Podobnie jak w wiki nagłówki oznacza się za pomocą symboli "=" linki tak jak w wiki, kod za pomocą tagów <coding> </coding>. Program jest bardzo uproszczony, ale latwo mozna dodac więcej rozpoznawanych przez niego tagów. | ||
+ | |||
+ | |||
+ | |||
+ | <code cpp> | ||
+ | |||
+ | |||
+ | #include <boost/spirit/core.hpp> | ||
+ | #include <iostream> | ||
+ | #include <string> | ||
+ | |||
+ | |||
+ | using namespace std; | ||
+ | using namespace boost::spirit; | ||
+ | |||
+ | //////////////////////////////////////////////////////////////////////////// | ||
+ | //TUTAJ PODAJEMY AKCJE JAKIE BEDA WYKONYWANE W ZALEZNOSCI OD WEJSCIA | ||
+ | //////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void | ||
+ | h1Action(char const* first,char const* last) | ||
+ | { | ||
+ | std::string str(first, last); | ||
+ | std::cout << "<h1>"<<str.substr(4,str.length()-8)<<"</h1>" << std::endl; | ||
+ | } | ||
+ | void h2Action(char const* first,char const* last) | ||
+ | { | ||
+ | std::string str(first, last); | ||
+ | std::cout << "<h2>"<<str.substr(3,str.length()-6)<<"</h2>" << std::endl; | ||
+ | } | ||
+ | void h3Action(char const* first,char const* last) | ||
+ | { | ||
+ | std::string str(first, last); | ||
+ | std::cout << "<h3>"<<str.substr(2,str.length()-4)<<"</h3>" << std::endl; | ||
+ | } | ||
+ | void h4Action(char const* first,char const* last) | ||
+ | { | ||
+ | std::string str(first, last); | ||
+ | std::cout << "<h4>"<<str.substr(1,str.length()-2)<<"</h4>" << std::endl; | ||
+ | } | ||
+ | void href(char const* first,char const* last) | ||
+ | { | ||
+ | std::string str(first, last); | ||
+ | std::cout << "<a href="+str.substr(2,str.find("|",2)-2)+">"+str.substr(str.find("|",2)+1,str.length()-5-(str.substr(2,str.find("|",2)-2)).length())+"</a>" << std::endl; | ||
+ | } | ||
+ | |||
+ | void code(char const* first,char const* last) | ||
+ | { | ||
+ | |||
+ | std::string str(first, last); | ||
+ | std::cout << "<div style=\"border-width: 1px; border-style: dashed; border-color: blue; \">"+str.substr(6,str.length()-13)+"</div>" << std::endl; | ||
+ | } | ||
+ | |||
+ | void tail(char const* first,char const* last) | ||
+ | { | ||
+ | std::string str(first, last); | ||
+ | std::cout << "</body>" << std::endl << "</html>" << std::endl; | ||
+ | } | ||
+ | void head(char const first) | ||
+ | { | ||
+ | std::cout <<"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""<<std::endl; | ||
+ | std::cout <<"\"http://www.w3.org/TR/xhtml1/DTD/xhtml1i-strict.dtd\">"<<std::endl; | ||
+ | std::cout<<"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"pl\">"<<std::endl; | ||
+ | std::cout<<"<head>"<<std::endl<< "<link rel=\"stylesheet\" type=\"text/css\" href=\"main.css\" />"<<std::endl; | ||
+ | std::cout<<"</head>"<<std::endl<<"<body>"<<std::endl; | ||
+ | } | ||
+ | |||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | //TUTAJ DEFINIUJEMY REGULY PARSOWANIA | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | struct html : public grammar<html> | ||
+ | { | ||
+ | template <typename ScannerT> | ||
+ | struct definition | ||
+ | { | ||
+ | definition(html const& ) | ||
+ | { | ||
+ | header | ||
+ | = ch_p('{')[&head]; | ||
+ | tag | ||
+ | = (str_p("====")>>(*(~ch_p('=')))>>str_p("===="))[&h1Action] | ||
+ | | (str_p("===")>>(*(~ch_p('=')))>>str_p("==="))[&h2Action] | ||
+ | | (str_p("==")>>(*(~ch_p('=')))>>str_p("=="))[&h3Action] | ||
+ | | (str_p("=")>>(*(~ch_p('=')))>>str_p("="))[&h4Action] | ||
+ | | (str_p("<coding>")>>*(anychar_p-str_p("</coding>"))>>str_p("</coding>"))[&code] | ||
+ | | (str_p("[[")>>(*((~ch_p(']'))-ch_p('|')))>>ch_p('|')>>(*(~ch_p(']')))>>str_p("]]"))[&href]; | ||
+ | document | ||
+ | = header>>(*tag>>ch_p('}'))[&tail]; | ||
+ | |||
+ | |||
+ | |||
+ | } | ||
+ | |||
+ | rule<ScannerT> tag, document, header; | ||
+ | |||
+ | rule<ScannerT> const& | ||
+ | start() const { return document; } | ||
+ | }; | ||
+ | }; | ||
+ | |||
+ | |||
+ | int | ||
+ | main() | ||
+ | { | ||
+ | cout << "Simple parsing example\n"; | ||
+ | cout << "Type \"quit\" to exit program\n"; | ||
+ | |||
+ | html htmlParser; // Our parser | ||
+ | |||
+ | string str,tmp; | ||
+ | while (getline(cin, str)) | ||
+ | { | ||
+ | if (str=="quit") | ||
+ | break; | ||
+ | if(str[str.length()-1]=='}') | ||
+ | { | ||
+ | tmp+=str; | ||
+ | parse_info<> info = parse(tmp.c_str(), htmlParser, space_p); | ||
+ | if (info.full) | ||
+ | { | ||
+ | cout << "Parsing succeeded\n"; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | cout << "Parsing failed at:\n"<<info.stop; | ||
+ | } | ||
+ | |||
+ | tmp=""; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | tmp+=str; | ||
+ | } | ||
+ | } | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </code> | ||
==== O bibliotece Spirit w sieci ==== | ==== O bibliotece Spirit w sieci ==== |