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 08:55] 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 230: | Linia 231: | ||
//w momencie poprawnego sparsowania, funkca wypisze w postaci stringa wszystkie sparsowane elementy | //w momencie poprawnego sparsowania, funkca wypisze w postaci stringa wszystkie sparsowane elementy | ||
</code> | </code> | ||
+ | |||
+ | |||
Linia 236: | Linia 239: | ||
==== Zbierzmy wszystko razem ==== | ==== 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. | ||
- | Po tych podstawach, przydałoby się napisać krótki program ilustrujący faktyczne działanie biblioteki Spirit. Wykorzytsmy w nim dyrektywy, prymitywy , reguły , operatory oraz akcje semantyczne. | ||
<code cpp> | <code cpp> | ||
+ | |||
+ | |||
#include <boost/spirit/core.hpp> | #include <boost/spirit/core.hpp> | ||
- | #include <boost/spirit/actor/push_back_actor.hpp> | ||
#include <iostream> | #include <iostream> | ||
#include <string> | #include <string> | ||
+ | |||
using namespace std; | using namespace std; | ||
using namespace boost::spirit; | using namespace boost::spirit; | ||
- | //nasza prosta akcja | + | //////////////////////////////////////////////////////////////////////////// |
- | void action(char const* first, char const* last) | + | //TUTAJ PODAJEMY AKCJE JAKIE BEDA WYKONYWANE W ZALEZNOSCI OD WEJSCIA |
+ | //////////////////////////////////////////////////////////////////////////// | ||
+ | |||
+ | void | ||
+ | h1Action(char const* first,char const* last) | ||
{ | { | ||
- | std::string str(first, last); | + | std::string str(first, last); |
- | std::cout << str << std::endl; | + | 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 action1(char const* first, char const* last) | + | 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::string str(first, last); |
- | std::cout << str << std::endl; | + | 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 | ||
+ | /////////////////////////////////////////////////////////////////////////////// | ||
- | void action1(char const* first, char const* last) | + | struct html : public grammar<html> |
+ | { | ||
+ | template <typename ScannerT> | ||
+ | struct definition | ||
{ | { | ||
- | std::string str(first, last); | + | definition(html const& ) |
- | std::cout << str << std::endl; | + | { |
+ | 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> | </code> | ||