00001 #ifndef JOBOPTIONSVC_GRAMMAR_H_
00002 #define JOBOPTIONSVC_GRAMMAR_H_
00003
00004
00005
00006
00007
00008 #include <string>
00009 #include <vector>
00010 #include <map>
00011
00012
00013
00014 #include <boost/spirit/include/qi.hpp>
00015 #include <boost/spirit/include/phoenix_core.hpp>
00016 #include <boost/spirit/include/phoenix_fusion.hpp>
00017 #include <boost/spirit/include/phoenix_operator.hpp>
00018 #include <boost/spirit/include/phoenix_stl.hpp>
00019 #include <boost/spirit/repository/include/qi_confix.hpp>
00020
00021 #if BOOST_VERSION <= 104400
00022 #include "iter_pos.hpp"
00023 #else
00024 #include <boost/spirit/repository/include/qi_iter_pos.hpp>
00025 #endif
00026
00027
00028
00029
00030 #include "Node.h"
00031
00032 namespace Gaudi { namespace Parsers {
00033
00034
00035
00036 namespace sp = boost::spirit;
00037 namespace ph = boost::phoenix;
00038 namespace qi = sp::qi;
00039 namespace enc = sp::ascii;
00040 namespace rep = sp::repository;
00041
00042
00043
00044 template<typename Iterator>
00045 struct SkipperGrammar: qi::grammar<Iterator> {
00046 SkipperGrammar() : SkipperGrammar::base_type(comments) {
00047 comments = enc::space
00048 | rep::confix("/*", "*/")[*(qi::char_ - "*/")]
00049 | rep::confix("//", (sp::eol | sp::eoi))[*(qi::char_ - (sp::eol | sp::eoi))];
00050 }
00051 qi::rule<Iterator> comments;
00052 };
00053
00054 template<typename Iterator, typename Skipper>
00055 struct StringGrammar: qi::grammar<Iterator, std::string(), qi::locals<char>,
00056 Skipper> {
00057
00058 typedef std::string ResultT;
00059
00060 StringGrammar() : StringGrammar::base_type(str) {
00061 begin_quote = enc::char_("\"'");
00062 quote = enc::char_(qi::_r1);
00063
00064 str = qi::lexeme[begin_quote[qi::_a = qi::_1] >> *((enc::char_('\\')
00065 >> quote(qi::_a))[qi::_val += qi::_a]
00066 | (enc::char_[qi::_val += qi::_1] - quote(qi::_a)))
00067 >> quote(qi::_a)];
00068 }
00069
00070 qi::rule<Iterator, std::string(), qi::locals<char>, Skipper> str;
00071 qi::rule<Iterator, char()> begin_quote;
00072 qi::rule<Iterator, void(char)> quote;
00073
00074 };
00075
00076 template<typename Iterator, typename Skipper>
00077 struct IdentifierGrammar: qi::grammar<Iterator, Node(), Skipper> {
00078
00079 typedef std::string ResultT;
00080
00081 IdentifierGrammar() : IdentifierGrammar::base_type(ident) {
00082 ident = rep::qi::iter_pos[op(qi::_val, qi::_1)] >> str[op(qi::_val, qi::_1)][op(qi::_val, Node::kIdentifier)];
00083 str = -qi::lit("::")[qi::_val += "::"] >> inner[qi::_val += qi::_1]
00084 >> *(qi::lit("::") >> inner[qi::_val += ("::"+qi::_1)]);
00085 inner = qi::alpha >> *(qi::alnum | qi::char_('_'));
00086 }
00087
00088 qi::rule<Iterator, Node(), Skipper> ident;
00089 qi::rule<Iterator, std::string(), Skipper> str;
00090 qi::rule<Iterator, std::string()> inner;
00091 ph::function<NodeOperations> op;
00092 };
00093
00094 template<typename Iterator, typename Skipper>
00095 struct BoolGrammar: qi::grammar<Iterator, bool(), Skipper> {
00096
00097 typedef bool ResultT;
00098
00099 BoolGrammar() : BoolGrammar::base_type(boolean) {
00100 boolean = enc::no_case[
00101 qi::lit("true")[qi::_val=true]
00102 |
00103 qi::lit("false")[qi::_val=false]
00104 ];
00105 }
00106
00107 qi::rule<Iterator, bool(), Skipper> boolean;
00108 };
00109
00110 template<typename Iterator, typename Skipper>
00111 struct RealGrammar: qi::grammar<Iterator, Node(), Skipper> {
00112
00113 typedef bool ResultT;
00114
00115 RealGrammar() : RealGrammar::base_type(real) {
00116 real = qi::raw[qi::double_][op(qi::_val, qi::_1)]
00117 [op(qi::_val, Node::kReal)]
00118 >> -(-qi::char_('*') >> gunit[op(qi::_val,qi::_1)]);
00119
00120 }
00121
00122 qi::rule<Iterator, Node(), Skipper> real;
00123 IdentifierGrammar<Iterator,Skipper> gunit;
00124 ph::function<NodeOperations> op;
00125 };
00126
00127 template<typename Iterator, typename Skipper>
00128 struct UnitsGrammar: qi::grammar<Iterator, Node(), Skipper> {
00129
00130 UnitsGrammar() : UnitsGrammar::base_type(units) {
00131 units = *unit[op(qi::_val, qi::_1)];
00132 unit = rep::qi::iter_pos[op(qi::_val, qi::_1)] >>
00133 val[op(qi::_val, qi::_1)]
00134 >> -qi::lit('*') >> gunit[op(qi::_val, qi::_1)]
00135 >> qi::lit('=') >> val[op(qi::_val, qi::_1)]
00136 [op(qi::_val, Node::kUnit)];;
00137 val = qi::raw[qi::double_]
00138 [op(qi::_val, qi::_1)][op(qi::_val, Node::kReal)];
00139
00140 }
00141
00142 qi::rule<Iterator, Node(), Skipper> units, unit, val;
00143 IdentifierGrammar<Iterator,Skipper> gunit;
00144 ph::function<NodeOperations> op;
00145 };
00146
00147 template<typename Iterator, typename Skipper>
00148 struct FileGrammar: qi::grammar<Iterator, Node(), Skipper> {
00149 FileGrammar() : FileGrammar::base_type(file) {
00150 file = -shell[op(qi::_val,qi::_1)] >>
00151 *(statement[op(qi::_val, qi::_1)])
00152 [op(qi::_val, Node::kRoot)];
00153 shell = rep::confix("#!", qi::eol)[*(qi::char_[qi::_a += qi::_1]
00154 - qi::eol)][op(qi::_val,Node::kShell)]
00155 [op(qi::_val,qi::_a)];
00156 statement = rep::qi::iter_pos[qi::_a = qi::_1]
00157 >> (include | assign | units | print_options | pragma
00158 | condition)[qi::_val = qi::_1][op(qi::_val,qi::_a)];
00159 condition = (qi::lit("#ifdef")[op(qi::_a,Node::kIfdef)]
00160 | qi::lit("#ifndef")[op(qi::_a,Node::kIfndef)])
00161 >> property[op(qi::_val,qi::_1)]
00162 >> (*statement[op(qi::_a,qi::_1)])[op(qi::_val, qi::_a)]
00163 >> -(qi::lit("#else")[op(qi::_b,Node::kElse)]
00164 >> *statement[op(qi::_b,qi::_1)])[op(qi::_val,qi::_b)]
00165 >> qi::lit("#endif")[op(qi::_val, Node::kCondition)];
00166 include = qi::lit("#include")
00167 >> gstring[op(qi::_val, qi::_1)]
00168 [op(qi::_val, Node::kInclude)];
00169 units = qi::lit("#units")
00170 >> gstring[op(qi::_val, qi::_1)]
00171 [op(qi::_val, Node::kUnits)];
00172 print_options = qi::lit("#printOptions") >> qi::lit("full")
00173 [op(qi::_val, Node::kPrintOptions)];
00174 pragma = qi::lit("#pragma") >> (pragma_print | pragma_tree |
00175 pragma_dump_file);
00176 pragma_print = qi::lit("print") >> enc::no_case[
00177 qi::lit("on")[op(qi::_val, Node::kPrintOn)]
00178 | qi::lit("off")[op(qi::_val, Node::kPrintOff)]
00179 ];
00180 pragma_tree = enc::no_case[
00181 qi::lit("printtree")[op(qi::_val, Node::kPrintTree)]
00182 ];
00183 pragma_dump_file = qi::lit("dumpfile") >> gstring[op(qi::_val, qi::_1)]
00184 [op(qi::_val, Node::kDumpFile)];
00185 assign = property[op(qi::_val, qi::_1)]
00186 [op(qi::_val, Node::kAssign)]
00187 >> oper[op(qi::_val, qi::_1)]
00188 >> value[op(qi::_val, qi::_1)]
00189 >> ';';
00190 property = rep::qi::iter_pos[op(qi::_val, qi::_1)]
00191 >> (gidentifier[op(qi::_val, qi::_1)] % '.')
00192 [op(qi::_val, Node::kProperty)];
00193 property_ref %= -qi::lit('@') >>
00194 property[op(qi::_val, Node::kPropertyRef)];
00195 oper = rep::qi::iter_pos[op(qi::_val, qi::_1)]
00196 >> (qi::lit("=")[op(qi::_val, Node::kEqual)]
00197 |
00198 qi::lit("+=")[op(qi::_val, Node::kPlusEqual)]
00199 |
00200 qi::lit("-=")[op(qi::_val, Node::kMinusEqual)]);
00201 value = rep::qi::iter_pos[qi::_a = qi::_1]
00202 >>
00203 (map_value | vector_value | simple_value | property |
00204 property_ref)
00205 [qi::_val = qi::_1][op(qi::_val, qi::_a)]
00206 ;
00207 begin_vector = enc::char_('(')[qi::_val=')']
00208 |
00209 enc::char_('[')[qi::_val=']']
00210 |
00211 enc::char_('{')[qi::_val='}'];
00212 end_vector = qi::char_(qi::_r1);
00213 vector_value = (begin_vector[qi::_a = qi::_1]
00214 >> -(value[op(qi::_val,qi::_1)] % ',')
00215 >> end_vector(qi::_a)
00216 )[op(qi::_val,Node::kVector)];
00217 map_value = (enc::char_('{')
00218 >> -(pair[op(qi::_val, qi::_1)] % ',')
00219 >> enc::char_('}'))
00220 [op(qi::_val, Node::kMap)];
00221 pair = simple_value[op(qi::_val,qi::_1)] >> ':'
00222 >> value[op(qi::_val,qi::_1)]
00223 [op(qi::_val,Node::kPair)];
00224 simple_value =
00225 (gstring[op(qi::_val, qi::_1)][op(qi::_val, Node::kString)])
00226 |
00227 (gbool[op(qi::_val, qi::_1)][op(qi::_val, Node::kBool)])
00228 |
00229 (greal[qi::_val = qi::_1]);
00230 }
00231 qi::rule<Iterator, Node(), Skipper> file, include, assign, property,
00232 property_ref, oper, map_value, pair_value, simple_value, pair, units,
00233 print_options, pragma, pragma_print, pragma_tree, pragma_dump_file;
00234 qi::rule<Iterator, Node(),qi::locals<std::string> > shell;
00235 qi::rule<Iterator, Node(), qi::locals<Iterator>, Skipper> statement, value;
00236 qi::rule<Iterator, Node(), qi::locals<char>, Skipper> vector_value;
00237 qi::rule<Iterator, Node(), qi::locals<Node, Node>, Skipper> condition;
00238 qi::rule<Iterator, char()> begin_vector;
00239 qi::rule<Iterator, void(char)> end_vector;
00240 StringGrammar<Iterator, Skipper> gstring;
00241 BoolGrammar<Iterator, Skipper> gbool;
00242 RealGrammar<Iterator, Skipper> greal;
00243 IdentifierGrammar<Iterator, Skipper> gidentifier;
00244 ph::function<NodeOperations> op;
00245 };
00246
00247 } }
00248
00249 #endif // JOBOPTIONSVC_GRAMMAR_H_