Boost.Spiritの例(calculator)をBoost.Xpressiveで書ける

  • spirit::grammar<>のようなフレームワークを使わなくていい
  • SemanticActionも使えるようだ


[]#include[][] "stdafx.h"[]

[]#include[][] <iostream>[]
[]#include[][] <string>[]
[]#include[][] <boost/iterator.hpp>[]
[]#include[][] <boost/xpressive/xpressive_static.hpp>[]

[]// See:[]
[]// http://www.boost.org/libs/spirit/doc/semantic_actions.html[]


[]// or http://boost.cppll.jp/HEAD/libs/spirit/doc/semantic_actions.html[]

[]namespace[] []pst[] {
[]using[] []namespace[] []std[];
[]using[] []namespace[] []boost[];
[]using[] []namespace[] []boost[]::[]xpressive[];

[]// semantic actions[]
[]struct[] []printer[] : []action[]<[]printer[]>
{
[]wstring[] []str[];
[]printer[]([]wstring[] []const[]& []str_[]) : []str[]([]str_[]) { }

[]template[]< []class[] []BidiIter[] >
[]bool[] []operator[]()([]match_results[]<[]BidiIter[]> []const[]& []match[], []BidiIter[] []cur[])
{
[]wcout[] << []str[] << []endl[];
[]return[] []true[];
}
};

[]struct[] []digit_printer[] : []action[]<[]digit_printer[]>
{
[]template[]< []class[] []BidiIter[] >
[]bool[] []operator[]()([]match_results[]<[]BidiIter[]> []const[]& []match[], []BidiIter[] []cur[])
{
[]wcout[] << []match[].[]str[](1) << []endl[]; []// print s1[]
[]return[] []true[];
}
};

[]template[]< []class[] []BidiIter[] > []inline[]
[]basic_regex[]<[]BidiIter[]> []make_caluculator_BNF[]()
{
[]basic_regex[]<[]BidiIter[]> []expression[], []moreterms[], []term[], []morefactors[], []factor[];

[]// grammar[]
[]expression[]
= []by_ref[]([]term[]) >> []by_ref[]([]moreterms[])
;
[]moreterms[]
= []L[][]'+'[] >> []by_ref[]([]term[]) [[]printer[]([]L[][]"ADD"[])] >> []by_ref[]([]moreterms[])
| []L[][]'-'[] >> []by_ref[]([]term[]) [[]printer[]([]L[][]"SUBTRACT"[])] >> []by_ref[]([]moreterms[])
| []epsilon[]
;
[]term[]
= []by_ref[]([]factor[]) >> []by_ref[]([]morefactors[])
;
[]morefactors[]
= []L[][]'*'[] >> []by_ref[]([]factor[]) [[]printer[]([]L[][]"MULTIPLY"[])] >> []by_ref[]([]morefactors[])
| []L[][]'/'[] >> []by_ref[]([]factor[]) [[]printer[]([]L[][]"DIVIDE"[])] >> []by_ref[]([]morefactors[])
| []epsilon[]
;
[]factor[]
= ([]s1[]= []_d[])[[]digit_printer[]()] []// s1に保存することを明記[]
| []L[][]'('[] >> []expression[] >> []L[][]')'[]
| []L[][]'+'[] >> []by_ref[]([]factor[])
| []L[][]'-'[] >> []by_ref[]([]factor[]) [[]printer[]([]L[][]"NEGATE"[])]
;

[]return[] []expression[];
}

[]template[]< []class[] []BidiIter[] > []inline[]
[]basic_regex[]<[]BidiIter[]> []make_caluculator_EBNF[]()
{
[]basic_regex[]<[]BidiIter[]> []expression[], []term[], []factor[];

[]expression[]
= []by_ref[]([]term[])
>> *( []L[][]'+'[] >> []by_ref[]([]term[]) [[]printer[]([]L[][]"ADD"[])]
| []L[][]'-'[] >> []by_ref[]([]term[]) [[]printer[]([]L[][]"SUBTRACT"[])]
)
;
[]term[]
= []by_ref[]([]factor[])
>> *( []L[][]'*'[] >> []by_ref[]([]factor[]) [[]printer[]([]L[][]"MULTIPLY"[])]
| []L[][]'/'[] >> []by_ref[]([]factor[]) [[]printer[]([]L[][]"DIVIDE"[])]
)
;
[]factor[]
= ([]s1[]= +[]_d[])[[]digit_printer[]()]
| []L[][]'('[] >> []expression[] >> []L[][]')'[]
| []L[][]'+'[] >> []by_ref[]([]factor[])
| []L[][]'-'[] >> []by_ref[]([]factor[]) [[]printer[]([]L[][]"NEGATE"[])]
;

[]return[] []expression[];
}

[]struct[] []is_not_space[]
{ []// I forgot isspace[]
[]bool[] []operator[]()([]wchar_t[] []ch[]) { []return[] []regex_match[]([]wstring[](1,[]ch[]), ~[]_s[]); }
};

[]inline[] []void[] []test[]() {
[]wstring[] []input[]([]L[][]"(-1 + 2) * (3 + -4)"[]);

[]typedef[] []filter_iterator[]<[]is_not_space[], []wstring[]::[]const_iterator[]> []filter_iter_t[];

[]if[] ( ![]regex_match[](
[]filter_iter_t[]([]input[].[]begin[](), []input[].[]end[]()),
[]filter_iter_t[]([]input[].[]end[](), []input[].[]end[]()),
[]make_caluculator_EBNF[]<[]filter_iter_t[]>()) )
{
[]wcout[] << []L[][]"error!"[] << []endl[];
}
}
} []// namespace pst[]

[]int[] []main[]()
{
[]pst[]::[]test[]();
[]std[]::[]wcin[].[]ignore[]();
[]return[] 0;
}