#include #include #include #include #include // if this gets defined, my parse passes and all input is consumed // #define BOOST_SPIRIT_DEBUG // if it is not defined, my parse passes but not all input is consumed #include #include #include #include "keyword.h" // typedef for stream iterator we will use typedef boost::spirit::istream_iterator LefDefIter; // A skip parser for LEF/DEF comments and spaces // adapted from a presentation at Boostcon 2010 by Michael Caisse template struct lefdefskipper : boost::spirit::qi::grammar< Iterator > { lefdefskipper() : lefdefskipper::base_type(skip_it) { using namespace boost::spirit::qi; comment = '#' >> *( char_ - eol ) >> eol ; skip_it = comment | space ; } boost::spirit::qi::rule skip_it; boost::spirit::qi::rule comment; }; template struct lefparser : boost::spirit::qi::grammar > { lefparser() : lefparser::base_type(lef_file) { using namespace boost::spirit::qi; using namespace distinct; using boost::phoenix::ref; // for storing parsing info into parser var (instead of attributes) // here's MY bug: ">" binds more tightly than "|" // the ON/OFF options need parens // it's in trying to debug this that I noticed the BOOST_SPIRIT_DEBUG problem casesens = keyword["NAMESCASESENSITIVE"] > (string("ON")[ref(case_on) = true] | string("OFF")[ref(case_on) = false]) > ';' ; lef_file = -casesens >> -string("END") ; BOOST_SPIRIT_DEBUG_NODE(casesens); BOOST_SPIRIT_DEBUG_NODE(lef_file); } bool case_on; typedef boost::spirit::qi::rule > NoAttrRule; NoAttrRule lef_file, casesens; }; int main() { lefparser lefParser; lefdefskipper lefdefSkipper; std::stringstream testlef("NAMESCASESENSITIVE ON ;\nEND\n"); testlef.unsetf(std::ios::skipws); LefDefIter beg = LefDefIter(testlef), end; if (!phrase_parse(beg, end, lefParser, lefdefSkipper)) { std::cerr << "parse failed\n"; return 1; } else if (beg != end) { std::cerr << "Not all input consumed. Remaining input:|"; std::copy(beg, end, std::ostream_iterator(std::cerr)); std::cerr << "|\n"; return 1; } std::cerr << "parse passed\n"; return 0; }