際際滷

際際滷Share a Scribd company logo
掲g喘議  Boost Spirit Qi  秘T 2011/5/14 Boost  茶氏 兆硬塁 @yak_ex /  仟 慎丐
徭失B初 箆兆 仟 慎丐  ( あたらし やすたか ) Twitter ID: yak_ex Web: http://yak3.myhome.cx:8080/junks C++ / Perl  が麼 F壓、碧並でコ`ドに乾れていないので 室プログラミング TopCoder 、 Codeforces で いa割 の發麻燭譴襪燭世  C++  挫き 兜めて  Spirit  聞ったUYを圷にk燕
Spirit  とのZれ兜め PDF  喘  Susie  プラグインがライセンスの vSでずっと巷_唯峭になってる ライセンスの}がない  PDF Susie  プラグインを恬ろう 恷詰沺∋颪世iいて栖られればいいや PDF  フォ`マットは護とテキストベ`ス 猟盾裂が駅勣 ☆ プラグインは  axpdf--.spi β 井として巷_嶄 せっかくだから鯵はこの  Spirit   をxぶぜ ->  Spirit  を兜めて聞喘したUYを圷にk燕
Boost Spirit  とは Boost  巷塀サイトの峰 LL parser framework represents parsers directly as EBNF grammars in inlined C++ 猟盾裂匂を、 C++  坪で岷俊  EBNF  猟隈をく並で恬れるフレ`ムワ`ク はぁ
Boost Spirit  とは 弊gでのu登 B なことで嗤兆な Boost::Spirit を´ http://zo3kirin3.net/?p=82 B 議と兆互い (?) Boost.Spirit  で盾裂。 http://ja.doukaku.org/comment/6518/ ´ 揖じく B ┛め冱~と兆互い boost::spirit  を聞ってg廾することにした。 http://d.hatena.ne.jp/Hossy/20080407 Y  Boost Spirit   B
これが  Spirit  の薦だ // #include  と  using namespace  福待 int main(void){   typedef std::map<std::string, std::string> Config;   Config config;   std::string input(&quot;Boost.Spirit = extraordinary  C++er = ...&quot;);   phrase_parse(input.begin(), input.end(),    *(lexeme[*(graph - char_('='))] >> lit('=') >> lexeme[*graph]),   space, config);   BOOST_FOREACH(Config::value_type &kv, config) {   std::cout << kv.first << '=' << kv.second << std::endl;   } } 竃薦 Boost.Spirit=extraordinary C++er=... <key>=<value> が  std::map  に融っzまれる 侏と竃薦篳協x 秘薦協x 竃薦 へ  ん  た  い
互業にk_した C++ は徴隈と曝eがつかない ア`サ`? C++ ?クラ`ク
Boost Spirit  とは Boost  ライブラリの嶄でも恷互桁の匯つ┳暴 Optional, Variant, Fusion, Proto, Phoenix, MPL  吉、 麿の  Boost  ライブラリをふんだんに聞喘 C++  でできることのベンチマ`ク議了崔づけ どんなものか岑っとくだけでも吭龍はあるかと Qi, Karma, Lex  で撹 Qi:  猟盾裂猟忖双->デ`タ夛 Karma  竃薦┘禰`タ夛->猟忖双 Lex  忖鞘盾裂猟忖双->ト`クン双 ○ 書指のテ`マ
Spirit Qi  秘T Tutorial 灼
アジェンダ 古勣B初 浙┐気譴進垢し修里 來 Directive を徭恬してみる Customization point 敷怎
Boost Spirit  とは Boost  巷塀サイト LL parser framework represents parsers directly as EBNF grammars in inlined C++ 猟盾裂匂を、 C++  坪で岷俊  EBNF  猟隈をく 並で恬れるフレ`ムワ`ク
猟盾裂と  EBNF 猟盾裂猟忖双->デ`タ夛 あるル`ルにtった猟忖双を盾裂 箭 塀 10 20 30 40 - * + 0 ( - 4 3 0  0 * ) 2 + 0 1
猟盾裂と  EBNF EBNF = Extended Backus Normal Form 仝あるル`ル々塾跳┐留輦圭隈 xk | 0指參貧のRり卦し *、1指參貧のRり卦し + 箭 塀 <Expression> ::= <Term> ((`+¨ | `-¨ ) <Term>)* <Term> ::= <Factor> ((`*¨ | `/¨ ) <Factor>)* <Factor> ::= <Integer> | `(` <Expression> `)¨
Boost Spirit  の  rule EBNF による塀の燕F <Expression> ::= <Term> ((`+¨ | `-¨ ) <Term>)* <Term> ::= <Factor> ((`*¨ | `/¨ ) <Factor>)* <Factor> ::= <Integer> | `(` <Expression> `)¨  C++  の塀として嗤 Spirit  での塀の燕F expr = term >> *(char_(^+- ̄) >> term); term = factor >> *(char_(^*/ ̄) >> factor); factor = int_ | lit(`(`) >> expr >> lit(`)¨);
Boost Spirit  の  rule 撹勣殆 Parser┿云勣殆 Directive俐 Operator┰Y栽
Boost Spirit  の  rule Parser┿云勣殆 etc. 猟忖双  abc  をiむ lit(^abc ̄) abc  いずれか 1 猟忖をiむ char_(^abc ̄) a ゛ b の譴 1 猟忖をiむ char_(`a¨, `b¨) isgraph()  が  true  な 1 猟忖をiむ graph a 1 猟忖をiむ lit(`a¨) 屁方、鰌iむ int_ 販吭の 1 猟忖をiむ char_
Boost Spirit  の  rule Directive (俐Parser の咾笋┐) etc. p  の  N  指のRり卦し repeat(N)[p] p  坪何で寄猟忖、弌猟忖を曝eしない no_case[p] p  の  N  指參貧のRり卦し repeat(N,inf)[p] p  の  N ゛ M  指のRり卦し repeat(N,M)[p] p  枠^で腎易をスキップ、 p  坪何では腎易をスキップしない lexeme[p]
Boost Spirit  の  rule Operator (Y栽) etc. p  が  0 or 1  指 -a b  でない  a a - b p  の  0  指參貧のRり卦し *a xk a  あるいは  b  a | b b  で曝俳られた  a  のRり卦し a % b p  の  1  指參貧のRり卦し +a B俊噸宥に、欧襭 a >> b
これが  Spirit  の薦だ // #include  と  using namespace  福待 int main(void){   typedef std::map<std::string, std::string> Config;   Config config;   std::string input(&quot;Boost.Spirit = extraordinary  C++er = ...&quot;);   phrase_parse(input.begin(), input.end(),    *(lexeme[*(graph - char_('='))] >> lit('=') >> lexeme[*graph]),   space, config);   BOOST_FOREACH(Config::value_type &kv, config) {   std::cout << kv.first << '=' << kv.second << std::endl;   } } 竃薦 Boost.Spirit=extraordinary C++er=... <key>=<value> が  std::map  に融っzまれる へ  ん  た  い
Boost Spirit  の  rule *(   lexeme[   *(   graph - char_('=')   )]   >> lit('=')   >> lexeme[   *graph ]) 0 指參貧のRり卦し 坪何スキップなし 0 指參貧のRり卦し =  參翌の燕幣猟忖 = 坪何スキップなし 燕幣猟忖の  0  指參貧のRり卦し <key>=<value> のRり卦し
で、竃薦は
で、竃薦は Parser  には仝奉來々があってその奉來侏の、魴気 int_ -> int / char_ -> char 俐、Y栽されたものは -> Fusion  シ`ケンス  or STL  コンテナが奉來になる char_ >> int_ >> double_  -> tuple<char, int, double> *int_ -> vector<int> int_ >> int_  は -> どっちでも OK ☆ tuple, vector  は旗燕で  Fusion  シ`ケンス  /  コンテナなら採でも措い ☆ は仝 Quick Reference 々 の仝 Compound Attribute Rules 々を歌孚
で、竃薦は pair  はアダプタによって  Fusion  シ`ケンスとなせる ( ヘッダの  #include  が駅勣 ) 夛悶も  Fusion  シ`ケンスとなせる BOOST_FUSION_ADAPT_STRUCT BOOST_FUSION_DEFINE_STRUCT  で 夛悶協xと ADAPT  を匯櫃砲任る ☆ Fusion  は念指茶氏の  cpp_akira  さんのk燕も歌孚 BOOST_FUSION_DEFINE_STRUCT( (yak)(pdf), indirect_ref, (int, number) (int, generation) ) 夛悶  yak::pdf::indirect_ref  が  tuple<int, int>  犁韻砲覆
これが  Spirit  の薦だ //  #include   と  using namespace  福待 int main(void){   typedef std::map<std::string, std::string> Config;   Config config;   std::string input(&quot;Boost.Spirit = extraordinary  C++er = ...&quot;);   phrase_parse(input.begin(), input.end(),    *(lexeme[*(graph - char_('='))] >> lit('=') >> lexeme[*graph]),   space,  config );   BOOST_FOREACH(Config::value_type &kv, config) {   std::cout << kv.first << '=' << kv.second << std::endl;   } } 竃薦 Boost.Spirit=extraordinary C++er=... <key>=<value> が  std::map  に融っzまれる へ  ん  た  い
竃薦枠 lexeme  は  skip  の碧圭が笋錣襪世韻琶來は篁しないのです lit  はo奉來 (unused_type) 、 graph, char_  は char 、 pa C pb  は  pa  の奉來 vector<tuple<vector<char>, vector<char> > > or  vector<vector<char> > ☆ vector<char>  と  string  は札Q ->これらも札Q *(*(graph - char_('=')) >> lit('=') >> *graph) *(*char >> *char) std::map<std::string, std::string>  std::pair<std::string, std::string>  のコンテナ std::string, std::string  の  Fusion  シ`ケンスのコンテナ Rule の奉來 旗秘枠 *(lexeme[*(graph - char_('='))] >> lit('=') >> lexeme[*graph])
Spirit.Qi  秘T 頼 まだ  Spirit  の Bフェイズは K阻してないぜ。
アジェンダ 古勣B初 浙┐気譴進垢し修里 來 Directive  を徭恬してみる Customization point 敷怎
來 Spirit ┐B來を屶える嶷勣な勣殆 瘁からできるような碧譴韻してある Proto を聞っているので徭念のコンポ`ネントParser吉を恬撹できる ->Directive の徭恬 I尖にフックが喘吭してある ->Customization point
Boost Spirit  の  rule  壅 Directive (俐Parser の咾笋┐) etc. p  の  N  指のRり卦し repeat(N)[p] p  坪何で寄猟忖、弌猟忖を曝eしない no_case[p] p  の  N  指參貧のRり卦し repeat(N,inf)[p] p  の  N ゛ M  指のRり卦し repeat(N,M)[p] p  枠^で腎易をスキップ、 p  坪何では腎易をスキップしない lexeme[p]
Directive  の徭恬 Parser  の徭恬は  boost-spirit.com  に並嗤り http://bit.ly/ikdvQt 恬る麗  delimited (delimiter)[parser] 箭  delimited(std::string(^endstream ̄))[char_] endstream  という猟忖双にぶつかるまで  char  をiみ竃す せっかくなので  char  掲浙┐牌撹 std::vector<int> delim(2, -1); delimited(delim)[int_] で  -1 -1  にぶつかるまで  int  をiみ竃す
Directive  の徭恬 徭恬コンポ`ネントの勣殆 K極催の傚冱 Parser 云悶の協x 奉來の侏 gHの盾裂I尖 Parser generator の協x(rule -> Parser のQ) 嗤浸 コンポ`ネント徭附 Semantic action ☆ 書指  semantic action  には畠く乾れませんので  Tutorial  歌孚
Directive  の徭恬 K極催の傚冱 namespace mine {   BOOST_SPIRIT_TERMINAL_EX( delimited ) }
Directive  の徭恬 Parser  云悶 namespace mine {   //  坪何  parser  が  1  つの  parser  侏を協x  (CRTP  を旋喘 )   template<typename  Subject , typename Delimiter>   struct delimited_parser   : boost::spirit::qi::unary_parser<delimited_parser< Subject , Delimiter> > {   //  メンバテンプレ`トクラス  attribute   を協x type   が 奉來の侏    template <typename Context, typename Iterator>   struct   attribute  {   typedef  typename boost::spirit::traits::build_std_vector<   typename boost::spirit::traits::attribute_of<Subject, Context, Iterator>::type   >::type  type ;   };   //  コンストラクタ parser generator  から柵ばれる   delimited_parser( Subject  const &subject,  Delimiter  const &delimiter)   : subject(subject), delimiter(delimiter) {} ☆ Directive  坪何の  Parser  の侏 delimited(delimiter)[parser]
Directive  の徭恬 Parser  云悶 namespace mine {   //  gHの盾裂ル`チン   template<typename Iterator, typename Context, typename Skipper, typename Attribute>   bool  parse (Iterator &first, Iterator const &last,   Context &context, Skipper const &skipper, Attribute &attribute) const {   //  待  subject.parse()  を聞って KMP 隈議にI尖。   //  喘議にやるならコンテナ荷恬には  traits  を聞う。   // traits::container_value<Attribute>::type   // traits::container_iterator<const Delimiter>::type   // traits::begin(delimiter);   }   template <typename Context>   boost::spirit::info what(Context& context) const {   return boost::spirit::info(^delimited ̄, subject.what(context));   }   Subject subject;  // Directive  坪何のパ`サ`隠隔喘   Delimiter delimiter;  //  デリミタ隠隔喘   }; ☆ 奉來
Directive  の徭恬 Parser generator  の協x (rule -> Parser  のQ )  namespace boost { namespace spirit { namespace qi {   template <typename Delimiter, typename Subject, typename Modifiers>   struct  make_directive <   terminal_ex<mine::tag:: delimited ,    fusion::vector1<Delimiter>  >, Subject, Modifiers>  {   // Parser  の侏   typedef mine:: delimited_parser <Subject, Delimiter>  result_type ;   // Parser  を卦す  operator()   template <typename Terminal> result_type  operator()   (Terminal const& term, Subject const& subject, unused_type) const {   return result_type(subject,  fusion::at_c<0>(term.args) );   } }; }}} 哈方の  0  桑朕勣殆 Directive  の哈方の侏  Delimiter 1 つ delimited (delimiter) [parser] Parser  の コンストラクタ柵び竃し
Directive  の徭恬 嗤浸 (Proto  にJRさせる namespace boost { namespace spirit {   //  宥械喘   template<typename Delimiter>   struct  use_directive <qi::domain,   terminal_ex<mine::tag:: delimited ,   fusion::vector1<Delimiter> > > : mpl::true_ {};   // Phoenix (Lambda  みたいなもの ) 喘   template<>   struct  use_lazy_directive <qi::domain,   mine::tag::delimited, 1 // arity   > : mpl::true_ {};
Directive  の徭恬 // #include  と  using namespace  福待 int main(void){   typedef std::map<std::string, std::string> Config;   Config config;   std::string input(&quot;Boost.Spirit= extraordinary  C++er= ...&quot;);   phrase_parse(input.begin(), input.end(),    *(lexeme[ delimited(std::string(^=^))[graph] ] >> lexeme[*graph]),   space, config);   BOOST_FOREACH(Config::value_type &kv, config) {   std::cout << kv.first << '=' << kv.second << std::endl;   } } 竃薦 Boost.Spirit=extraordinary C++er=... ☆ 秘薦を裏虫に筝
ね、酒gでしょう
旗紋返粁 哈方 (Inherit attribute) 原きル`ルを協x rule<Iterator, std::string(std::string)> delimited; delimited = *(graph_ - _r1) >> omit[_r1]; 聞い圭   phrase_parse(input.begin(), input.end(),    *(lexeme[ delimited(^=^) ] >> lexeme[*graph]),   space, config); 哈方 哈方 、里討 哈方の侏 奉來
掲g喘議秘壇
Customization point いちいち  Parser  とか  Directive  とか 恬ってらんないけど咾鬟スタマイズしたい ->それ、 Spirit  ならできるよ traits  を蒙歩晒することで咾筝
Customization point boost::spirit::traits  參和に喘吭されている。 SFINAE  喘の  Enabler  は福待 is_container<Container> >>  狼喘 vB  container_value<Container> etc. handles_container<Component, Attr> >>  狼喘 transform_attribute<Exposed, Transformed, Domain> rule  狼喘 assign_to_attribute_from_iterators<Attr, Iterator> 喘 assign_to_attribute_from_value<Attr, T> 喘 assign_to_container_from_value<Attr, T> 喘 push_back_container<Container, Attr> R卦狼喘 clear_value<Attr> R卦狼喘 etc. create_parser<T> auto_ 喘 cf.  http://slashdot.jp/~Yak!/journal/525693
Customization point  のvS 箭  Foo >> *Bar  のY惚のし枠として侏  Qux  の篳  qux  が局された栽    ☆  Foo >> *Bar  の奉來が  Qux  侏であるとは泙蕕覆ぃ    ☆ 寄だけ輅勝 ::type  や  ::call  も福待 is_container<Qux> handles_container<Foo> handles_container<*Bar> push_back_container<Qux,Foo_temp>(qux, foo_temp); foo_temp ○ Foo  iみ竃し container_value<Qux>::type foo_temp; true true qux ○ Foo  iみ竃し false true qux ○ *Bar  iみ竃し ☆ * ならデフォルト true   false なら●と揖のI尖 clear_value<Bar> push_back_container<Qux,Bar_attr> を坪何で旋喘
Customization point  のvS 箭  Foo >> *Bar  のY惚のし枠として侏  Qux  の篳  qux  が局された栽    ☆  Foo >> *Bar  の奉來が  Qux  侏であるとは泙蕕覆ぃ    ☆ 寄だけ輅勝 ::type  や  ::call  も福待 is_container<Qux> is_container<QA> transform_attribute<QA, Foo_attr>::type foo_temp = transform_attribute<QA, Foo_attr>::pre(qa); false true 念ペ`ジと揖のI尖 false Qux  は  2  勣殆の Fusion  シ`ケンス tuple<QA, QB> とする foo_temp ○ Foo  iみ竃し transform_attribute<QA, Foo_attr>::post(qa, foo_temp); QB と *Bar の奉來について貧と揖のI尖 Foo  は採 rule  や  attr_cast Foo_attr foo_temp; 麿 ☆ デフォルトは坪何で  assign_to  を聞喘 ☆ 坪何で  assign_to_*  怛を聞喘 assign_to(foo_temp, qa); foo_temp ○ Foo  iみ竃し
アジェンダ 古勣B初 浙┐気譴進垢し修里 來 Directive を徭恬してみる Customization point 敷怎
Spirit Qi  とうまく原き栽うために コンパイルrgが Boost!!!   ->コ`ヒ`でもんで囘に棋つといいよ ☆ axpdf--.spi  だとフルビルドにs  10  蛍 Spirit  vB何蛍を蛍xして猟隈が笋錣蕕覆は泙袵戰灰鵐僖ぅ覯子にする Parser  はあくまで  parser  に莂靴 猟盾裂Y惚にするI尖はeに蛍けるとか
Spirit Qi  とうまく原き栽うために エラ`メッセ`ジ楚が Boost!!! ->箭 3.3MB
えてる 20% s弌燕幣 鮫駱a屎しないと院くて猟忖が 蛍からないレベル
Spirit Qi  とうまく原き栽うために エラ`メッセ`ジ楚が Boost!!! ->箭 3.3MB テンプレ`トのインスタンス晒秤鵑ほとんど まずは error で碧
error  で碧 ココ 20% s弌燕幣
Spirit Qi  とうまく原き栽うために エラ`メッセ`ジ楚が Boost!!! ->箭 3.3MB テンプレ`トのインスタンス晒秤鵑ほとんど まずは error で碧 瘁はどこが寔咀かインスタンス晒秤鵑鰡iる´念に 匯業エラ`w侭をてみるといいことがあるかも
ケ`ス 1. static_assert エラ`メッセ`ジ spirit7.cpp:30:  instantiated from here /usr/local/include/boost/spirit/home/qi/nonterminal/grammar.hpp:75: error: no matching function for call to `assertion_failed( mpl_::failed**  (boost::spirit::qi::grammar<Iterator, T1, T2, T3, T4>::grammar(const boost::spirit::qi::rule<Iterator_, T1_, T2_, T3_, T4_>&, const std::string&) [ 採か匯鵜 ]:: incompatible_start_rule::** )( 採か匯鵜 ))¨ Spirit Qi  とうまく原き栽うために
ケ`ス 2.  コメント エラ`メッセ`ジ spirit7.cpp:39:  instantiated from here /usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:277: error: no match for call to ` 採か匯鵜¨ /usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp // If you are seeing a compilation error here stating that the // forth parameter can't be converted to a required target type // then you are probably trying to use a rule or a grammar with // an incompatible skipper type. if (f(first, last, context, skipper)) Spirit Qi  とうまく原き栽うために 277 佩朕
枠伏.灰鵐僖ぅ詬┐辰燭韻彬爾辰人┐蠅 咾ません Spirit Qi  とうまく原き栽うために   ->プログラムは房った宥りに咾ない。    いたとおりに咾。 debug(rule);  を聞うと猟盾裂の徨がトレ`ス できる http://boost- spirit.com /home/articles/doc-addendum/debugging/ 奉來に  operator<<  が駅勣
まとめ Spirit  はB 寔中朕に  Spirit  やりたい繁は Tutorial  をiみながら匯宥りg佩する boost-spirit.com  の並をiむ 昧r  Quick Reference  を歌孚する
ご床ありがとうございました

More Related Content

Impractical Introduction of Boost Spirit Qi [PPT]

  • 1. 掲g喘議 Boost Spirit Qi 秘T 2011/5/14 Boost 茶氏 兆硬塁 @yak_ex / 仟 慎丐
  • 2. 徭失B初 箆兆 仟 慎丐 ( あたらし やすたか ) Twitter ID: yak_ex Web: http://yak3.myhome.cx:8080/junks C++ / Perl が麼 F壓、碧並でコ`ドに乾れていないので 室プログラミング TopCoder 、 Codeforces で いa割 の發麻燭譴襪燭世 C++ 挫き 兜めて Spirit 聞ったUYを圷にk燕
  • 3. Spirit とのZれ兜め PDF 喘 Susie プラグインがライセンスの vSでずっと巷_唯峭になってる ライセンスの}がない PDF Susie プラグインを恬ろう 恷詰沺∋颪世iいて栖られればいいや PDF フォ`マットは護とテキストベ`ス 猟盾裂が駅勣 ☆ プラグインは axpdf--.spi β 井として巷_嶄 せっかくだから鯵はこの Spirit をxぶぜ -> Spirit を兜めて聞喘したUYを圷にk燕
  • 4. Boost Spirit とは Boost 巷塀サイトの峰 LL parser framework represents parsers directly as EBNF grammars in inlined C++ 猟盾裂匂を、 C++ 坪で岷俊 EBNF 猟隈をく並で恬れるフレ`ムワ`ク はぁ
  • 5. Boost Spirit とは 弊gでのu登 B なことで嗤兆な Boost::Spirit を´ http://zo3kirin3.net/?p=82 B 議と兆互い (?) Boost.Spirit で盾裂。 http://ja.doukaku.org/comment/6518/ ´ 揖じく B ┛め冱~と兆互い boost::spirit を聞ってg廾することにした。 http://d.hatena.ne.jp/Hossy/20080407 Y Boost Spirit B
  • 6. これが Spirit の薦だ // #include と using namespace 福待 int main(void){ typedef std::map<std::string, std::string> Config; Config config; std::string input(&quot;Boost.Spirit = extraordinary C++er = ...&quot;); phrase_parse(input.begin(), input.end(), *(lexeme[*(graph - char_('='))] >> lit('=') >> lexeme[*graph]), space, config); BOOST_FOREACH(Config::value_type &kv, config) { std::cout << kv.first << '=' << kv.second << std::endl; } } 竃薦 Boost.Spirit=extraordinary C++er=... <key>=<value> が std::map に融っzまれる 侏と竃薦篳協x 秘薦協x 竃薦 へ ん た い
  • 8. Boost Spirit とは Boost ライブラリの嶄でも恷互桁の匯つ┳暴 Optional, Variant, Fusion, Proto, Phoenix, MPL 吉、 麿の Boost ライブラリをふんだんに聞喘 C++ でできることのベンチマ`ク議了崔づけ どんなものか岑っとくだけでも吭龍はあるかと Qi, Karma, Lex で撹 Qi: 猟盾裂猟忖双->デ`タ夛 Karma 竃薦┘禰`タ夛->猟忖双 Lex 忖鞘盾裂猟忖双->ト`クン双 ○ 書指のテ`マ
  • 9. Spirit Qi 秘T Tutorial 灼
  • 10. アジェンダ 古勣B初 浙┐気譴進垢し修里 來 Directive を徭恬してみる Customization point 敷怎
  • 11. Boost Spirit とは Boost 巷塀サイト LL parser framework represents parsers directly as EBNF grammars in inlined C++ 猟盾裂匂を、 C++ 坪で岷俊 EBNF 猟隈をく 並で恬れるフレ`ムワ`ク
  • 12. 猟盾裂と EBNF 猟盾裂猟忖双->デ`タ夛 あるル`ルにtった猟忖双を盾裂 箭 塀 10 20 30 40 - * + 0 ( - 4 3 0 0 * ) 2 + 0 1
  • 13. 猟盾裂と EBNF EBNF = Extended Backus Normal Form 仝あるル`ル々塾跳┐留輦圭隈 xk | 0指參貧のRり卦し *、1指參貧のRり卦し + 箭 塀 <Expression> ::= <Term> ((`+¨ | `-¨ ) <Term>)* <Term> ::= <Factor> ((`*¨ | `/¨ ) <Factor>)* <Factor> ::= <Integer> | `(` <Expression> `)¨
  • 14. Boost Spirit の rule EBNF による塀の燕F <Expression> ::= <Term> ((`+¨ | `-¨ ) <Term>)* <Term> ::= <Factor> ((`*¨ | `/¨ ) <Factor>)* <Factor> ::= <Integer> | `(` <Expression> `)¨ C++ の塀として嗤 Spirit での塀の燕F expr = term >> *(char_(^+- ̄) >> term); term = factor >> *(char_(^*/ ̄) >> factor); factor = int_ | lit(`(`) >> expr >> lit(`)¨);
  • 15. Boost Spirit の rule 撹勣殆 Parser┿云勣殆 Directive俐 Operator┰Y栽
  • 16. Boost Spirit の rule Parser┿云勣殆 etc. 猟忖双 abc をiむ lit(^abc ̄) abc いずれか 1 猟忖をiむ char_(^abc ̄) a ゛ b の譴 1 猟忖をiむ char_(`a¨, `b¨) isgraph() が true な 1 猟忖をiむ graph a 1 猟忖をiむ lit(`a¨) 屁方、鰌iむ int_ 販吭の 1 猟忖をiむ char_
  • 17. Boost Spirit の rule Directive (俐Parser の咾笋┐) etc. p の N 指のRり卦し repeat(N)[p] p 坪何で寄猟忖、弌猟忖を曝eしない no_case[p] p の N 指參貧のRり卦し repeat(N,inf)[p] p の N ゛ M 指のRり卦し repeat(N,M)[p] p 枠^で腎易をスキップ、 p 坪何では腎易をスキップしない lexeme[p]
  • 18. Boost Spirit の rule Operator (Y栽) etc. p が 0 or 1 指 -a b でない a a - b p の 0 指參貧のRり卦し *a xk a あるいは b a | b b で曝俳られた a のRり卦し a % b p の 1 指參貧のRり卦し +a B俊噸宥に、欧襭 a >> b
  • 19. これが Spirit の薦だ // #include と using namespace 福待 int main(void){ typedef std::map<std::string, std::string> Config; Config config; std::string input(&quot;Boost.Spirit = extraordinary C++er = ...&quot;); phrase_parse(input.begin(), input.end(), *(lexeme[*(graph - char_('='))] >> lit('=') >> lexeme[*graph]), space, config); BOOST_FOREACH(Config::value_type &kv, config) { std::cout << kv.first << '=' << kv.second << std::endl; } } 竃薦 Boost.Spirit=extraordinary C++er=... <key>=<value> が std::map に融っzまれる へ ん た い
  • 20. Boost Spirit の rule *( lexeme[ *( graph - char_('=') )] >> lit('=') >> lexeme[ *graph ]) 0 指參貧のRり卦し 坪何スキップなし 0 指參貧のRり卦し = 參翌の燕幣猟忖 = 坪何スキップなし 燕幣猟忖の 0 指參貧のRり卦し <key>=<value> のRり卦し
  • 22. で、竃薦は Parser には仝奉來々があってその奉來侏の、魴気 int_ -> int / char_ -> char 俐、Y栽されたものは -> Fusion シ`ケンス or STL コンテナが奉來になる char_ >> int_ >> double_ -> tuple<char, int, double> *int_ -> vector<int> int_ >> int_ は -> どっちでも OK ☆ tuple, vector は旗燕で Fusion シ`ケンス / コンテナなら採でも措い ☆ は仝 Quick Reference 々 の仝 Compound Attribute Rules 々を歌孚
  • 23. で、竃薦は pair はアダプタによって Fusion シ`ケンスとなせる ( ヘッダの #include が駅勣 ) 夛悶も Fusion シ`ケンスとなせる BOOST_FUSION_ADAPT_STRUCT BOOST_FUSION_DEFINE_STRUCT で 夛悶協xと ADAPT を匯櫃砲任る ☆ Fusion は念指茶氏の cpp_akira さんのk燕も歌孚 BOOST_FUSION_DEFINE_STRUCT( (yak)(pdf), indirect_ref, (int, number) (int, generation) ) 夛悶 yak::pdf::indirect_ref が tuple<int, int> 犁韻砲覆
  • 24. これが Spirit の薦だ // #include と using namespace 福待 int main(void){ typedef std::map<std::string, std::string> Config; Config config; std::string input(&quot;Boost.Spirit = extraordinary C++er = ...&quot;); phrase_parse(input.begin(), input.end(), *(lexeme[*(graph - char_('='))] >> lit('=') >> lexeme[*graph]), space, config ); BOOST_FOREACH(Config::value_type &kv, config) { std::cout << kv.first << '=' << kv.second << std::endl; } } 竃薦 Boost.Spirit=extraordinary C++er=... <key>=<value> が std::map に融っzまれる へ ん た い
  • 25. 竃薦枠 lexeme は skip の碧圭が笋錣襪世韻琶來は篁しないのです lit はo奉來 (unused_type) 、 graph, char_ は char 、 pa C pb は pa の奉來 vector<tuple<vector<char>, vector<char> > > or vector<vector<char> > ☆ vector<char> と string は札Q ->これらも札Q *(*(graph - char_('=')) >> lit('=') >> *graph) *(*char >> *char) std::map<std::string, std::string> std::pair<std::string, std::string> のコンテナ std::string, std::string の Fusion シ`ケンスのコンテナ Rule の奉來 旗秘枠 *(lexeme[*(graph - char_('='))] >> lit('=') >> lexeme[*graph])
  • 26. Spirit.Qi 秘T 頼 まだ Spirit の Bフェイズは K阻してないぜ。
  • 27. アジェンダ 古勣B初 浙┐気譴進垢し修里 來 Directive を徭恬してみる Customization point 敷怎
  • 28. 來 Spirit ┐B來を屶える嶷勣な勣殆 瘁からできるような碧譴韻してある Proto を聞っているので徭念のコンポ`ネントParser吉を恬撹できる ->Directive の徭恬 I尖にフックが喘吭してある ->Customization point
  • 29. Boost Spirit の rule 壅 Directive (俐Parser の咾笋┐) etc. p の N 指のRり卦し repeat(N)[p] p 坪何で寄猟忖、弌猟忖を曝eしない no_case[p] p の N 指參貧のRり卦し repeat(N,inf)[p] p の N ゛ M 指のRり卦し repeat(N,M)[p] p 枠^で腎易をスキップ、 p 坪何では腎易をスキップしない lexeme[p]
  • 30. Directive の徭恬 Parser の徭恬は boost-spirit.com に並嗤り http://bit.ly/ikdvQt 恬る麗 delimited (delimiter)[parser] 箭 delimited(std::string(^endstream ̄))[char_] endstream という猟忖双にぶつかるまで char をiみ竃す せっかくなので char 掲浙┐牌撹 std::vector<int> delim(2, -1); delimited(delim)[int_] で -1 -1 にぶつかるまで int をiみ竃す
  • 31. Directive の徭恬 徭恬コンポ`ネントの勣殆 K極催の傚冱 Parser 云悶の協x 奉來の侏 gHの盾裂I尖 Parser generator の協x(rule -> Parser のQ) 嗤浸 コンポ`ネント徭附 Semantic action ☆ 書指 semantic action には畠く乾れませんので Tutorial 歌孚
  • 32. Directive の徭恬 K極催の傚冱 namespace mine { BOOST_SPIRIT_TERMINAL_EX( delimited ) }
  • 33. Directive の徭恬 Parser 云悶 namespace mine { // 坪何 parser が 1 つの parser 侏を協x (CRTP を旋喘 ) template<typename Subject , typename Delimiter> struct delimited_parser : boost::spirit::qi::unary_parser<delimited_parser< Subject , Delimiter> > { // メンバテンプレ`トクラス attribute を協x type が 奉來の侏 template <typename Context, typename Iterator> struct attribute { typedef typename boost::spirit::traits::build_std_vector< typename boost::spirit::traits::attribute_of<Subject, Context, Iterator>::type >::type type ; }; // コンストラクタ parser generator から柵ばれる delimited_parser( Subject const &subject, Delimiter const &delimiter) : subject(subject), delimiter(delimiter) {} ☆ Directive 坪何の Parser の侏 delimited(delimiter)[parser]
  • 34. Directive の徭恬 Parser 云悶 namespace mine { // gHの盾裂ル`チン template<typename Iterator, typename Context, typename Skipper, typename Attribute> bool parse (Iterator &first, Iterator const &last, Context &context, Skipper const &skipper, Attribute &attribute) const { // 待 subject.parse() を聞って KMP 隈議にI尖。 // 喘議にやるならコンテナ荷恬には traits を聞う。 // traits::container_value<Attribute>::type // traits::container_iterator<const Delimiter>::type // traits::begin(delimiter); } template <typename Context> boost::spirit::info what(Context& context) const { return boost::spirit::info(^delimited ̄, subject.what(context)); } Subject subject; // Directive 坪何のパ`サ`隠隔喘 Delimiter delimiter; // デリミタ隠隔喘 }; ☆ 奉來
  • 35. Directive の徭恬 Parser generator の協x (rule -> Parser のQ ) namespace boost { namespace spirit { namespace qi { template <typename Delimiter, typename Subject, typename Modifiers> struct make_directive < terminal_ex<mine::tag:: delimited , fusion::vector1<Delimiter> >, Subject, Modifiers> { // Parser の侏 typedef mine:: delimited_parser <Subject, Delimiter> result_type ; // Parser を卦す operator() template <typename Terminal> result_type operator() (Terminal const& term, Subject const& subject, unused_type) const { return result_type(subject, fusion::at_c<0>(term.args) ); } }; }}} 哈方の 0 桑朕勣殆 Directive の哈方の侏 Delimiter 1 つ delimited (delimiter) [parser] Parser の コンストラクタ柵び竃し
  • 36. Directive の徭恬 嗤浸 (Proto にJRさせる namespace boost { namespace spirit { // 宥械喘 template<typename Delimiter> struct use_directive <qi::domain, terminal_ex<mine::tag:: delimited , fusion::vector1<Delimiter> > > : mpl::true_ {}; // Phoenix (Lambda みたいなもの ) 喘 template<> struct use_lazy_directive <qi::domain, mine::tag::delimited, 1 // arity > : mpl::true_ {};
  • 37. Directive の徭恬 // #include と using namespace 福待 int main(void){ typedef std::map<std::string, std::string> Config; Config config; std::string input(&quot;Boost.Spirit= extraordinary C++er= ...&quot;); phrase_parse(input.begin(), input.end(), *(lexeme[ delimited(std::string(^=^))[graph] ] >> lexeme[*graph]), space, config); BOOST_FOREACH(Config::value_type &kv, config) { std::cout << kv.first << '=' << kv.second << std::endl; } } 竃薦 Boost.Spirit=extraordinary C++er=... ☆ 秘薦を裏虫に筝
  • 39. 旗紋返粁 哈方 (Inherit attribute) 原きル`ルを協x rule<Iterator, std::string(std::string)> delimited; delimited = *(graph_ - _r1) >> omit[_r1]; 聞い圭 phrase_parse(input.begin(), input.end(), *(lexeme[ delimited(^=^) ] >> lexeme[*graph]), space, config); 哈方 哈方 、里討 哈方の侏 奉來
  • 41. Customization point いちいち Parser とか Directive とか 恬ってらんないけど咾鬟スタマイズしたい ->それ、 Spirit ならできるよ traits を蒙歩晒することで咾筝
  • 42. Customization point boost::spirit::traits 參和に喘吭されている。 SFINAE 喘の Enabler は福待 is_container<Container> >> 狼喘 vB container_value<Container> etc. handles_container<Component, Attr> >> 狼喘 transform_attribute<Exposed, Transformed, Domain> rule 狼喘 assign_to_attribute_from_iterators<Attr, Iterator> 喘 assign_to_attribute_from_value<Attr, T> 喘 assign_to_container_from_value<Attr, T> 喘 push_back_container<Container, Attr> R卦狼喘 clear_value<Attr> R卦狼喘 etc. create_parser<T> auto_ 喘 cf. http://slashdot.jp/~Yak!/journal/525693
  • 43. Customization point のvS 箭 Foo >> *Bar のY惚のし枠として侏 Qux の篳 qux が局された栽    ☆ Foo >> *Bar の奉來が Qux 侏であるとは泙蕕覆ぃ    ☆ 寄だけ輅勝 ::type や ::call も福待 is_container<Qux> handles_container<Foo> handles_container<*Bar> push_back_container<Qux,Foo_temp>(qux, foo_temp); foo_temp ○ Foo iみ竃し container_value<Qux>::type foo_temp; true true qux ○ Foo iみ竃し false true qux ○ *Bar iみ竃し ☆ * ならデフォルト true   false なら●と揖のI尖 clear_value<Bar> push_back_container<Qux,Bar_attr> を坪何で旋喘
  • 44. Customization point のvS 箭 Foo >> *Bar のY惚のし枠として侏 Qux の篳 qux が局された栽    ☆ Foo >> *Bar の奉來が Qux 侏であるとは泙蕕覆ぃ    ☆ 寄だけ輅勝 ::type や ::call も福待 is_container<Qux> is_container<QA> transform_attribute<QA, Foo_attr>::type foo_temp = transform_attribute<QA, Foo_attr>::pre(qa); false true 念ペ`ジと揖のI尖 false Qux は 2 勣殆の Fusion シ`ケンス tuple<QA, QB> とする foo_temp ○ Foo iみ竃し transform_attribute<QA, Foo_attr>::post(qa, foo_temp); QB と *Bar の奉來について貧と揖のI尖 Foo は採 rule や attr_cast Foo_attr foo_temp; 麿 ☆ デフォルトは坪何で assign_to を聞喘 ☆ 坪何で assign_to_* 怛を聞喘 assign_to(foo_temp, qa); foo_temp ○ Foo iみ竃し
  • 45. アジェンダ 古勣B初 浙┐気譴進垢し修里 來 Directive を徭恬してみる Customization point 敷怎
  • 46. Spirit Qi とうまく原き栽うために コンパイルrgが Boost!!!   ->コ`ヒ`でもんで囘に棋つといいよ ☆ axpdf--.spi だとフルビルドにs 10 蛍 Spirit vB何蛍を蛍xして猟隈が笋錣蕕覆は泙袵戰灰鵐僖ぅ覯子にする Parser はあくまで parser に莂靴 猟盾裂Y惚にするI尖はeに蛍けるとか
  • 47. Spirit Qi とうまく原き栽うために エラ`メッセ`ジ楚が Boost!!! ->箭 3.3MB
  • 48. えてる 20% s弌燕幣 鮫駱a屎しないと院くて猟忖が 蛍からないレベル
  • 49. Spirit Qi とうまく原き栽うために エラ`メッセ`ジ楚が Boost!!! ->箭 3.3MB テンプレ`トのインスタンス晒秤鵑ほとんど まずは error で碧
  • 50. error で碧 ココ 20% s弌燕幣
  • 51. Spirit Qi とうまく原き栽うために エラ`メッセ`ジ楚が Boost!!! ->箭 3.3MB テンプレ`トのインスタンス晒秤鵑ほとんど まずは error で碧 瘁はどこが寔咀かインスタンス晒秤鵑鰡iる´念に 匯業エラ`w侭をてみるといいことがあるかも
  • 52. ケ`ス 1. static_assert エラ`メッセ`ジ spirit7.cpp:30: instantiated from here /usr/local/include/boost/spirit/home/qi/nonterminal/grammar.hpp:75: error: no matching function for call to `assertion_failed( mpl_::failed** (boost::spirit::qi::grammar<Iterator, T1, T2, T3, T4>::grammar(const boost::spirit::qi::rule<Iterator_, T1_, T2_, T3_, T4_>&, const std::string&) [ 採か匯鵜 ]:: incompatible_start_rule::** )( 採か匯鵜 ))¨ Spirit Qi とうまく原き栽うために
  • 53. ケ`ス 2. コメント エラ`メッセ`ジ spirit7.cpp:39: instantiated from here /usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:277: error: no match for call to ` 採か匯鵜¨ /usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp // If you are seeing a compilation error here stating that the // forth parameter can't be converted to a required target type // then you are probably trying to use a rule or a grammar with // an incompatible skipper type. if (f(first, last, context, skipper)) Spirit Qi とうまく原き栽うために 277 佩朕
  • 54. 枠伏.灰鵐僖ぅ詬┐辰燭韻彬爾辰人┐蠅 咾ません Spirit Qi とうまく原き栽うために   ->プログラムは房った宥りに咾ない。   いたとおりに咾。 debug(rule); を聞うと猟盾裂の徨がトレ`ス できる http://boost- spirit.com /home/articles/doc-addendum/debugging/ 奉來に operator<< が駅勣
  • 55. まとめ Spirit はB 寔中朕に Spirit やりたい繁は Tutorial をiみながら匯宥りg佩する boost-spirit.com の並をiむ 昧r Quick Reference を歌孚する