Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define BOOST_SPIRIT_DEBUG
- #include <boost/spirit/include/qi.hpp>
- #include <boost/spirit/include/phoenix.hpp>
- #include <set>
- namespace qi=boost::spirit::qi;
- namespace phx=boost::phoenix;
- typedef boost::optional<boost::variant<std::string, double, int> > variant_t;
- struct object
- {
- std::string name;
- // non-key:
- mutable variant_t value;
- mutable std::set<object> children;
- object(const std::string& aname) : name(aname) { }
- bool operator<(const object& other) const
- { return name < other.name; }
- friend std::ostream& operator<<(std::ostream& os, const object& obj)
- { return obj.dump(os); }
- private:
- std::ostream& dump(std::ostream& os, std::string indent = "") const
- {
- const std::string extra = " ";
- os << "\n" << indent << "name: " << name;
- if (value) os << " (value: " << *value << ")";
- os << "\n" << indent << "{";
- for (auto& o: children) o.dump(os, indent + extra);
- os << "\n" << indent << "}";
- return os;
- }
- };
- namespace state // TODO make non-static for reentrance
- {
- object globals("<globals>");
- const object* current = &globals;
- static void reset()
- { current = &globals; }
- static void setvalue(variant_t value)
- { current->value = value; }
- static void lookup(const std::string& name)
- { current = &*(current->children.insert(object(name)).first); }
- }
- struct grammar : qi::grammar<std::string::iterator, qi::space_type>
- {
- grammar() : grammar::base_type(rule)
- {
- using namespace state;
- using namespace qi;
- using phx::bind;
- qual = as_string [ lexeme [ +(~char_(".") - space) ] ] [ bind(lookup, _1) ];
- name = eps [ reset ] >> (qual % '.');
- value = (as_string ['"' > *~char_('"') > '"'] | double_ | int_) [ setvalue ];
- rule = -("Set" >> (name >> value));
- BOOST_SPIRIT_DEBUG_NODE(qual);
- BOOST_SPIRIT_DEBUG_NODE(rule);
- BOOST_SPIRIT_DEBUG_NODE(name);
- BOOST_SPIRIT_DEBUG_NODE(value);
- }
- private:
- qi::rule<std::string::iterator, qi::space_type> qual;
- qi::rule<std::string::iterator, std::string(), qi::space_type> name;
- qi::rule<std::string::iterator, variant_t(), qi::space_type> value;
- qi::rule<std::string::iterator, qi::space_type> rule;
- };
- int main()
- {
- std::string input;
- while (std::getline(std::cin, input))
- {
- auto f(input.begin()), l(input.end());
- if (!qi::phrase_parse(f,l,grammar(),qi::space))
- std::cout << "failed line '" << input << "'" << std::endl;
- }
- std::cout << state::globals << std::endl;
- }
Add Comment
Please, Sign In to add comment