diff --git a/lib/ERMParser.cpp b/lib/ERMParser.cpp index 62e5c185c..5e6e0522f 100644 --- a/lib/ERMParser.cpp +++ b/lib/ERMParser.cpp @@ -63,14 +63,42 @@ void callme(char const& i) namespace ERM { + //i-expression (identifier expression) - an integral constant, variable symbol or array symbol + struct iexpT + { + typedef boost::optional > valT; + boost::optional varsym; + valT val; + }; - typedef std::vector identifierT; + typedef std::vector identifierT; + + + struct conditionT; + typedef + boost::optional< + boost::recursive_wrapper + > + conditionNodeT; + + struct conditionT + { + enum ECondType{AND = 0, OR, XOR, LAST} ctype; + std::string cond; + conditionNodeT rhs; + }; + + std::ostream & operator << (std::ostream & out, const conditionT & cond) + { + static char sym[] = {'&', '|', 'X', '/'}; + return out << sym[cond.ctype] << cond.cond << cond.rhs; + } struct triggerT { std::string name; boost::optional identifier; - boost::optional condition; + boost::optional condition; }; //a dirty workaround for preprocessor magic that prevents the use types with comma in it in BOOST_FUSION_ADAPT_STRUCT @@ -86,7 +114,7 @@ namespace ERM { std::string name; boost::optional identifier; - boost::optional condition; + boost::optional condition; bodyTbody body; }; @@ -94,14 +122,14 @@ namespace ERM { std::string name; boost::optional identifier; - boost::optional condition; + boost::optional condition; bodyTbody body; }; struct postOBtriggerT { boost::optional identifier; - boost::optional condition; + boost::optional condition; }; typedef boost::variant< @@ -120,9 +148,9 @@ namespace ERM void identifierPrinter(const identifierT & id) { - BOOST_FOREACH(int x, id) + BOOST_FOREACH(iexpT x, id) { - tlog2 << "\\" << x; + tlog2 << "\\" << x.varsym << x.val; } } @@ -192,18 +220,31 @@ namespace ERM } } +BOOST_FUSION_ADAPT_STRUCT( + ERM::iexpT, + (boost::optional, varsym) + (ERM::iexpT::valT, val) + ) + BOOST_FUSION_ADAPT_STRUCT( ERM::triggerT, (std::string, name) (boost::optional, identifier) - (boost::optional, condition) + (boost::optional, condition) ) +BOOST_FUSION_ADAPT_STRUCT( + ERM::conditionT, + (std::string, cond) + (ERM::conditionNodeT, rhs) + ) + + BOOST_FUSION_ADAPT_STRUCT( ERM::instructionT, (std::string, name) (boost::optional, identifier) - (boost::optional, condition) + (boost::optional, condition) (ERM::bodyTbody, body) ) @@ -211,14 +252,14 @@ BOOST_FUSION_ADAPT_STRUCT( ERM::receiverT, (std::string, name) (boost::optional, identifier) - (boost::optional, condition) + (boost::optional, condition) (ERM::bodyTbody, body) ) BOOST_FUSION_ADAPT_STRUCT( ERM::postOBtriggerT, (boost::optional, identifier) - (boost::optional, condition) + (boost::optional, condition) ) namespace ERM @@ -228,17 +269,21 @@ namespace ERM { ERM_grammar() : ERM_grammar::base_type(rline, "ERM script line") { + macro %= qi::lit('$') >> *(qi::char_ - '$') >> qi::lit('$'); + iexp %= -(*qi::char_("a-z") - 'u') >> -(qi::int_ | macro); comment = *(qi::char_); commentLine = ~qi::char_('!') >> comment; - cmdName %= +qi::char_/*qi::repeat(2)[qi::char_]*/; - identifier %= (qi::int_ % qi::lit('/')); - condition %= qi::lit('&') >> +qi::char_("0-9a-zA-Z&/|<>=") >> qi::lit(":;"); - trigger %= cmdName >> -identifier >> -condition; ///// - string %= qi::lexeme['^' >> +(qi::char_ - '^') >> '^']; - body %= *( qi::char_("a-zA-Z0-9/ ") | string); + cmdName %= qi::repeat(2)[qi::char_]; + identifier %= (iexp % qi::lit('/')); + + condition %= (qi::lit('&') | qi::lit('|') | qi::lit('X') | qi::lit('/')) > *qi::char_("0-9a-zA-Z<>=-") > -condition; + + trigger %= cmdName >> -identifier >> -condition > qi::lit(";"); ///// + string %= qi::lexeme['^' >> *(qi::char_ - '^') >> '^']; + body %= qi::lit(":") > *( qi::char_("a-zA-Z0-9/ @*?%+-:|&-") | string | macro) > qi::lit(";"); instruction %= cmdName >> -identifier >> -condition >> body; receiver %= cmdName >> -identifier >> -condition >> body; - postOBtrigger %= qi::lit("$OB") >> -identifier >> -condition; + postOBtrigger %= qi::lit("$OB") >> -identifier >> -condition > qi::lit(";"); command %= (qi::char_('!') >> ( (qi::char_('?') >> trigger) | @@ -256,6 +301,7 @@ namespace ERM //error handling string.name("string constant"); + iexp.name("i-expression"); comment.name("comment"); commentLine.name("comment line"); cmdName.name("name of a command"); @@ -285,11 +331,13 @@ namespace ERM qi::rule string; + qi::rule macro; + qi::rule iexp; qi::rule comment; qi::rule commentLine; qi::rule cmdName; qi::rule identifier; - qi::rule condition; + qi::rule condition; qi::rule trigger; qi::rule body; qi::rule instruction; @@ -311,8 +359,8 @@ void ERMParser::parseLine( std::string line ) bool r = qi::parse(beg, end, ERMgrammar, AST); if(!r || beg != end) { - tlog1 << "Parse error for line " << line << std::endl; - tlog1 << "\tCannot parse: " << std::string(beg, end) << std::endl; + //tlog1 << "Parse error for line " << line << std::endl; + //tlog1 << "\tCannot parse: " << std::string(beg, end) << std::endl; } else {