/////////////////////////////////////////////////////////////////////////////// // // Basic Parser Grammar for Spirit (http://spirit.sourceforge.net/) // // Written by: Willem Hengeveld itsme@xs4all.nl // /////////////////////////////////////////////////////////////////////////////// #define BOOST_SPIRIT_DEBUG ///$$$ DEFINE THIS WHEN DEBUGGING $$$/// #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// using namespace std; using namespace boost::spirit; #define BOOST_SPIRIT_ASSERT_EXCEPTION basic_exception class basic_exception { public: basic_exception(const char *msg) : m_msg(msg) { } std::string m_msg; }; /////////////////////////////////////////////////////////////////////////////// // // Our Basic grammar // /////////////////////////////////////////////////////////////////////////////// struct basic_grammar : public grammar { basic_grammar() {} template struct definition { definition(basic_grammar const& /*self*/) { #ifdef BOOST_SPIRIT_DEBUG debug(); // define the debug names #endif //----------------------------------------------------------------- // TOKENS //----------------------------------------------------------------- typedef inhibit_case > token_t; chlit<> EQUAL('='); strlit<> NOT_EQUAL("<>"); chlit<> LT('<'); strlit<> LE("<="); strlit<> GE(">="); chlit<> GT('>'); chlit<> LPAREN('('); chlit<> RPAREN(')'); token_t AND = as_lower_d["and"]; token_t OR = as_lower_d["or"]; token_t NOT = as_lower_d["not"]; token_t TRUE = as_lower_d["true"]; token_t FALSE = as_lower_d["false"]; token_t LOGICALAND = AND; token_t LOGICALNOT = NOT; token_t LOGICALOR = OR; relationalOperator = EQUAL | NOT_EQUAL | GE | LE | LT | GT ; boolean_atom = LPAREN >> boolean_expression >> RPAREN | TRUE | FALSE | expression >> relationalOperator >> expression ; boolean_factor = !LOGICALNOT >> boolean_atom ; boolean_term = boolean_factor % LOGICALAND ; boolean_expression = boolean_term % LOGICALOR ; expression = boolean_expression ; end_of_line = eol_p ; program = *(expression >> end_of_line) ; //----------------------------------------------------------------- // End grammar definition //----------------------------------------------------------------- } #ifdef BOOST_SPIRIT_DEBUG void debug() { BOOST_SPIRIT_DEBUG_RULE(end_of_line); BOOST_SPIRIT_DEBUG_RULE(expression); BOOST_SPIRIT_DEBUG_RULE(program); BOOST_SPIRIT_DEBUG_RULE(boolean_atom); BOOST_SPIRIT_DEBUG_RULE(boolean_expression); BOOST_SPIRIT_DEBUG_RULE(boolean_factor); BOOST_SPIRIT_DEBUG_RULE(boolean_term); BOOST_SPIRIT_DEBUG_RULE(relationalOperator); } #endif rule const& start() const { return program; } symbols<> keywords; rule boolean_atom, boolean_expression, boolean_factor, boolean_term, relationalOperator, end_of_line, expression, program; }; }; /////////////////////////////////////////////////////////////////////////////// // // The Basic White Space Skipper // /////////////////////////////////////////////////////////////////////////////// struct basic_skipper : public grammar { basic_skipper() {} template struct definition { definition(basic_skipper const& /*self*/) { chlit<> SPACE(' '); chlit<> TAB('\t'); skip = SPACE | TAB ; #ifdef BOOST_SPIRIT_DEBUG BOOST_SPIRIT_DEBUG_RULE(skip); #endif } rule skip; rule const& start() const { return skip; } }; }; /////////////////////////////////////////////////////////////////////////////// // // Parse a file // /////////////////////////////////////////////////////////////////////////////// static void parse(char const* filename) { ifstream in(filename); if (!in) { cerr << "Could not open input file: " << filename << endl; return; } in.unsetf(ios::skipws); // Turn of white space skipping on the stream vector vec; std::copy( istream_iterator(in), istream_iterator(), std::back_inserter(vec)); vector::const_iterator first = vec.begin(); vector::const_iterator last = vec.end(); basic_skipper skip_p; basic_grammar p; #ifdef BOOST_SPIRIT_DEBUG BOOST_SPIRIT_DEBUG_NODE(skip_p); BOOST_SPIRIT_DEBUG_NODE(p); #endif parse_info::const_iterator> info = parse(first, last, p, skip_p); if (info.full) { cout << "\t\t" << filename << " Parses OK\n\n\n"; } else { cerr << "---PARSING FAILURE---\n"; cerr << string(info.stop, last); } } /////////////////////////////////////////////////////////////////////////////// // // Main program // /////////////////////////////////////////////////////////////////////////////// int main(int argc, char* argv[]) { cout << "/////////////////////////////////////////////////////////\n\n"; cout << "\t\tBasic Grammar For Spirit...\n\n"; cout << "/////////////////////////////////////////////////////////\n\n"; if (argc > 1) { for (int i = 1; i < argc; ++i) { cout << argv[i] << endl; try { parse(argv[i]); } catch( basic_exception e ) { cout << e.m_msg; } } } else { cerr << "---NO FILENAME GIVEN---" << endl; } return 0; }