#ifndef __CRUSH_GRAMMAR
#define __CRUSH_GRAMMAR
+#define BOOST_SPIRIT_DEBUG
+
+#include <boost/spirit/core.hpp>
+#include <boost/spirit/tree/ast.hpp>
+#include <boost/spirit/tree/tree_to_xml.hpp>
using namespace boost::spirit;
struct crush_grammar : public grammar<crush_grammar>
{
- static const int integerID = 1;
- static const int factorID = 2;
- static const int termID = 3;
- static const int expressionID = 4;
-
- static const int _posint = 10;
- static const int _name = 11;
+ static const int _int = 1;
+ static const int _posint = 2;
+ static const int _negint = 3;
+ static const int _name = 4;
+
static const int _device = 12;
static const int _bucket_type = 13;
static const int _bucket_id = 14;
template <typename ScannerT>
struct definition
{
- rule<ScannerT, parser_context<>, parser_tag<expressionID> > expression;
- rule<ScannerT, parser_context<>, parser_tag<termID> > term;
- rule<ScannerT, parser_context<>, parser_tag<factorID> > factor;
- rule<ScannerT, parser_context<>, parser_tag<integerID> > integer;
-
+ rule<ScannerT, parser_context<>, parser_tag<_int> > integer;
rule<ScannerT, parser_context<>, parser_tag<_posint> > posint;
+ rule<ScannerT, parser_context<>, parser_tag<_negint> > negint;
rule<ScannerT, parser_context<>, parser_tag<_name> > name;
rule<ScannerT, parser_context<>, parser_tag<_device> > device;
(!ch_p('-') >> +digit_p)
] ];
posint = leaf_node_d[ lexeme_d[ +digit_p ] ];
- name = +alnum_p;
+ negint = leaf_node_d[ lexeme_d[ ch_p('-') >> +digit_p ] ];
+ name = leaf_node_d[ lexeme_d[ +alnum_p ] ];
// devices
- device = str_p("device") >> posint >> name >> *(str_p("overload") >> real_p);
+ device = str_p("device") >> posint >> name >> !( str_p("overload") >> real_p );
// bucket types
bucket_type = str_p("buckettype") >> posint >> name;
// buckets
- bucket_id = str_p("id") >> ch_p('-') >> posint;
+ bucket_id = str_p("id") >> negint;
bucket_alg = str_p("alg") >> ( str_p("uniform") | str_p("list") | str_p("tree") | str_p("straw") );
bucket_item = str_p("item") >> name
>> !( str_p("weight") >> real_p )
// the whole crush map
crushmap = *(device | bucket_type) >> *bucket >> *crushrule;
-
-
-
- // Start grammar definition
- factor = integer
- | inner_node_d[ch_p('(') >> expression >> ch_p(')')]
- | (root_node_d[ch_p('-')] >> factor);
-
- term = factor >>
- *( (root_node_d[ch_p('*')] >> factor)
- | (root_node_d[ch_p('/')] >> factor)
- );
-
- expression = term >>
- *( (root_node_d[ch_p('+')] >> term)
- | (root_node_d[ch_p('-')] >> term)
- );
- // End grammar definition
-
- // turn on the debugging info.
- BOOST_SPIRIT_DEBUG_RULE(integer);
- BOOST_SPIRIT_DEBUG_RULE(factor);
- BOOST_SPIRIT_DEBUG_RULE(term);
- BOOST_SPIRIT_DEBUG_RULE(expression);
}
- rule<ScannerT, parser_context<>, parser_tag<expressionID> > const&
- start() const { return expression; }
+ rule<ScannerT, parser_context<>, parser_tag<_crushmap> > const&
+ start() const { return crushmap; }
};
};
device 1 osd001
device 2 osd002
device 3 osd003
-device 4 osd004 overload 0 # 0.0 -> normal, 1.0 -> failed
-device 5 osd005 overload .1
+device 4 osd004 overload 0 # 0.0 -> normal, 1.0 -> failed
+device 5 osd005 overload 0.1
# hierarchy
buckettype 2 cab
buckettype 3 row
buckettype 10 pool
-cab cab-d2 {
+cab cabd2 {
id -1 # optional
alg straw # required
item osd001
item osd002 weight 600 pos 1
item osd003 weight 600 pos 2
item osd004 weight 600 pos 3
- item osd005 pos 4 weight 600
+ item osd005 weight 600 pos 4
}
# rules
*
*/
-#include <boost/spirit/core.hpp>
-#include <boost/spirit/tree/ast.hpp>
-#include <boost/spirit/tree/tree_to_xml.hpp>
-
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <map>
using namespace std;
-
-using namespace boost::spirit;
-
-typedef char const* iterator_t;
+/*typedef char const* iterator_t;
typedef tree_match<iterator_t> parse_tree_match_t;
typedef parse_tree_match_t::tree_iterator iter_t;
-
+*/
//
+/*
long evaluate(parse_tree_match_t hit);
long eval_expression(iter_t const& i);
return 0;
}
+*/
+
////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
- // look in tree_calc_grammar for the definition of crush_grammar
- crush_grammar calc;
-
- cout << "/////////////////////////////////////////////////////////\n\n";
- cout << "\t\tThe simplest working crush_grammar...\n\n";
- cout << "/////////////////////////////////////////////////////////\n\n";
- cout << "Type an expression...or [q or Q] to quit\n\n";
+ cout << "go" << std::endl;
+ string big;
string str;
- while (getline(cin, str))
- {
- if (str.empty() || str[0] == 'q' || str[0] == 'Q')
- break;
-
- tree_parse_info<> info = ast_parse(str.c_str(), calc);
-
- if (info.full)
- {
-#if defined(BOOST_SPIRIT_DUMP_PARSETREE_AS_XML)
- // dump parse tree as XML
- std::map<parser_id, std::string> rule_names;
- rule_names[crush_grammar::integerID] = "integer";
- rule_names[crush_grammar::factorID] = "factor";
- rule_names[crush_grammar::termID] = "term";
- rule_names[crush_grammar::expressionID] = "expression";
- tree_to_xml(cout, info.trees, str.c_str(), rule_names);
-#endif
-
- // print the result
- cout << "parsing succeeded\n";
- cout << "result = " << evaluate(info) << "\n\n";
- }
- else
- {
- cout << "parsing failed\n";
- }
- }
-
- cout << "Bye... :-) \n\n";
+ int line = 1;
+ while (getline(cin, str)) {
+ // fixme: strip out comments
+ int l = str.length();
+ if (l && str[l] == '\n')
+ str.erase(l-1, 1);
+ int n = str.find("#");
+ if (n >= 0)
+ str.erase(n, str.length()-n);
+ cout << line++ << ": " << str << std::endl;
+ if (big.length()) big += " ";
+ big += str;
+ }
+
+ cout << "whole file is: \"" << big << "\"" << std::endl;
+
+ crush_grammar crushg;
+ //bool parsed = parse(big.c_str(), crushg, space_p).full;
+ tree_parse_info<> info = ast_parse(big.c_str(), crushg, space_p);
+ bool parsed = info.full;
+
+ if (parsed) {
+ // dump parse tree as XML
+ std::map<parser_id, std::string> rule_names;
+ rule_names[crush_grammar::_int] = "int";
+ rule_names[crush_grammar::_posint] = "posint";
+ rule_names[crush_grammar::_name] = "name";
+ rule_names[crush_grammar::_device] = "device";
+ rule_names[crush_grammar::_bucket_type] = "bucket_type";
+ rule_names[crush_grammar::_bucket_id] = "bucket_id";
+ rule_names[crush_grammar::_bucket_alg] = "bucket_alg";
+ rule_names[crush_grammar::_bucket_item] = "bucket_item";
+ rule_names[crush_grammar::_bucket] = "bucket";
+ rule_names[crush_grammar::_step_take] = "step_take";
+ rule_names[crush_grammar::_step_choose_indep] = "step_choose_indep";
+ rule_names[crush_grammar::_step_choose_firstn] = "step_choose_firstn";
+ rule_names[crush_grammar::_step_emit] = "step_emit";
+ rule_names[crush_grammar::_crushrule] = "rule";
+ rule_names[crush_grammar::_crushmap] = "map";
+ tree_to_xml(cout, info.trees, big.c_str(), rule_names);
+
+ // print the result
+ cout << "parsing succeeded\n";
+ //cout << "result = " << evaluate(info) << "\n\n";
+ } else {
+ cout << "did not parse" << std::endl;
+ }
+
return 0;
}