私は最近ブーストスピリットに興味があり、何かを作ろうとしています。Spiritを使用してC++でconstのようなものを実装できますか?たとえば、ユーザーは次のような項目を定義します。
constant var PROG_LANG="Java";
「constantvar」は奇妙に思えます、私は受け入れますが、あなたはその考えを理解しました。インターネットを検索しましたが、何も見つかりませんでした。
私は最近ブーストスピリットに興味があり、何かを作ろうとしています。Spiritを使用してC++でconstのようなものを実装できますか?たとえば、ユーザーは次のような項目を定義します。
constant var PROG_LANG="Java";
「constantvar」は奇妙に思えます、私は受け入れますが、あなたはその考えを理解しました。インターネットを検索しましたが、何も見つかりませんでした。
BigBossが言ったこと:)
セマンティックアクションなしでやるのは私だけです-それをはるかに少なくします...冗長(ブーストスピリット:「セマンティックアクションは悪です」も参照してください):
vdef =
("constant" >> attr(true) | attr(false)) >>
"var" >> identifier >> '=' >> identifier_value >> ';' ;
それで全部です。これはqi::attr
、デフォルト(constant
キーワードがない)を説明するために使用します。
これが出力付きの完全なデモです:
http://liveworkspace.org/code/c9e4bef100d2249eb4d4b88205f85c4b
出力:
parse success: 'var myvariable = "has some value";'
data: false;myvariable;has some value;
parse success: 'constant var myvariable = "has some value";'
data: true;myvariable;has some value;
コード:
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
struct var_definition {
bool is_constant;
std::string name;
std::string value;
var_definition() : is_constant( false ) {}
};
BOOST_FUSION_ADAPT_STRUCT(var_definition, (bool, is_constant)(std::string, name)(std::string, value))
void doParse(const std::string& input)
{
typedef std::string::const_iterator It;
qi::rule<It, std::string()> identifier, identifier_value;
qi::rule<It, var_definition(), qi::space_type> vdef;
{
using namespace qi;
identifier_value = '"' >> lexeme [ +~char_('"') ] > '"';
identifier = lexeme [ +graph ];
vdef =
("constant" >> attr(true) | attr(false)) >>
"var" >> identifier >> '=' >> identifier_value >> ';' ;
}
var_definition data;
It f(std::begin(input)), l(std::end(input));
bool ok = qi::phrase_parse(f,l,vdef,qi::space,data);
if (ok)
{
std::cout << "parse success: '" << input << "'\n";
std::cout << "data: " << karma::format_delimited(karma::auto_, ';', data) << "\n";
}
}
int main()
{
doParse("var myvariable = \"has some value\";");
doParse("constant var myvariable = \"has some value\";");
}
私はあなたの質問を正しく理解spirit
していません、パーサーであり、それはそれをconstant
解析することしかできないという意味とは何の関係もありませんが、あなたがそのようなオプションの変数を解析することを意味するなら、constant
それは何かの行である可能性があります:
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef std::string::const_iterator it;
struct var_definition {
bool is_constant;
std::string name;
std::string value;
var_definition() : is_constant( false ) {}
};
qi::rule<it, std::string()> identifier;
qi::rule<it, std::string()> identifier_value;
qi::rule<it, var_definition(), boost::spirit::ascii::space_type> vdef;
void mark_var_as_constant(var_definition& vd) {vd.is_constant=true;}
void set_var_name(var_definition& vd, std::string const& val) {vd.name=val;}
void set_var_value(var_definition& vd, std::string const& val) {vd.value=val;}
vdef %=
-qi::lit("constant")[phx::bind(mark_var_as_constant, qi::_val)] >>
qi::lit("var") >>
identifier[phx::bind(set_var_name, qi::_val, qi::_1)] >>
qi::char_('=') >>
identifier_value[phx::bind(set_var_value, qi::_val, qi::_1)] >>
qi::char_(';');
もちろん、他の方法もあります。たとえば、次のようになります。
(qi::lit("constant")[phx::bind(mark_var_as_constant, qi::_val)] | qi::eps)
そして最も簡単なのは:
qi::hold[ qi::lit("constant")[phx::bind(mark_var_as_constant, qi::_val)] ]