- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
namespace predicate {
using ...;
typedef boost::function<bool (const object &obj)> bool_func;
typedef boost::function<int (const object &obj)> int_func;
// ... скучные реализации операторов ...
template <class I, class S> struct predicate_grammar :
qi::grammar<I, bool_func(), S>
{
predicate_grammar() : predicate_grammar::base_type(bool_expr)
{
identifier = char_("a-z") >> *(char_("a-z_0-9"));
bool_prop = identifier [ _val = bind(&make_bool_prop_reader, _1, _pass) ];
bool_expr = (bool_expr2 >> "||" >> bool_expr) [ _val = bind(&make_logic_op, &op_or, _1, _2) ]
| bool_expr2 [ _val = _1 ];
bool_expr2 = (bool_expr3 >> "&&" >> bool_expr2) [ _val = bind(&make_logic_op, &op_and, _1, _2) ]
| bool_expr3 [ _val = _1 ];
bool_expr3 = ('(' >> bool_expr >> ')') [ _val = _1 ]
| ('!' >> bool_expr3) [ _val = bind(&make_not, _1) ]
| int_comp [ _val = _1 ]
| bool_prop [ _val = _1];
int_comp = (int_expr >> "<" >> int_expr) [ _val = bind(&make_cmp_op, &op_less, _1, _2) ]
| (int_expr >> "<=" >> int_expr) [ _val = bind(&make_cmp_op, &op_less_eq, _1, _2) ]
| (int_expr >> ">" >> int_expr) [ _val = bind(&make_cmp_op, &op_greater, _1, _2) ]
| (int_expr >> ">=" >> int_expr) [ _val = bind(&make_cmp_op, &op_greater_eq, _1, _2) ]
| (int_expr >> "==" >> int_expr) [ _val = bind(&make_cmp_op, &op_eq, _1, _2) ]
| (int_expr >> "!=" >> int_expr) [ _val = bind(&make_cmp_op, &op_not_eq, _1, _2) ];
int_expr = int_prop [ _val = _1 ]
| int_const [ _val = bind(&make_int_const, _1) ];
int_const = int_ [ _val = _1 ];
int_prop = identifier [ _val = bind(&make_int_prop_reader, _1, _pass) ];
}
qi::rule<I, std::string(), S> identifier;
qi::rule<I, int(), S> int_const;
qi::rule<I, int_func(), S> int_expr, int_prop;
qi::rule<I, bool_func(), S> bool_expr, bool_expr2, bool_expr3, int_comp, bool_prop;
};
boost::function<bool (const object &)> parse(const std::string &src) {
if (src.empty())
return make_bool_const(true);
bool_func p;
std::string::const_iterator b = src.begin(), e = src.end();
predicate_grammar<std::string::const_iterator, boost::spirit::ascii::space_type> grammar;
if (!phrase_parse(b, e, grammar, boost::spirit::ascii::space, p) || b != e) {
std::stringstream s;
s << "Predicate parsing failed at " << (b - src.begin()) << " in \"" << src << "\"";
throw std::runtime_error(s.str());
}
return p;
}
LispGovno 26.04.2013 16:39 # −1
bormand 26.04.2013 16:43 # +2
defecate-plusplus 26.04.2013 17:00 # +2
где ast::bin_op только не спрашивай меня как это работает, ибо я не помню уже))
bormand 26.04.2013 17:15 # +1
Да, в принципе, пока недавно с этим копался - ничего сложного. Ленивость вместо bind'а достигнута с помощью boost::phoenix::function'а. Грамматика чище чем у меня, зато сам make_binary получился пострашнее из-за структуры и "вывода типов"...
P.S. Моя примитивная грамматика компилится 20с. Хорошо, что она размещена в отдельном модуле. А сколько компилился этот паскаль?
P.P.S. Там, кстати, вроде бы был еще макрос типа ADAPT_FUNCTION, но теперь уже лень что-то менять, т.к. код работает.
defecate-plusplus 26.04.2013 17:28 # +1
например, повыносить почти всё через extern template struct в отдельные .cpp, благодаря тому, что типы итераторов были очевидны
изрядно помогло (наряду с pch, понятное дело)
LispGovno 26.04.2013 18:06 # 0
А в новом стандарте внешние шаблоны запретили в их старом виде. Да и было то это только в студии.
bormand 26.04.2013 18:10 # 0
>> хоть как-нибудь
Я думаю им в тот момент было насрать на кроссплатформенность, лишь бы собралось и работало...
defecate-plusplus 26.04.2013 18:18 # +2
не рабочий же код, а сраный курсач принести и показать, и промодифицировать на месте по требованию препода типа "а давай ка у тебя в паскале еще будет тернарная операция ?:"
зато по сравнению с yacc/bison было интересно разобраться
bormand 26.04.2013 18:56 # +2
Ну вот собственно поэтому и решил написать этот микропарсер используя ускорение::дух::ки. С флексом+бизоном я бы его, конечно, написал быстрее, т.к. уже есть опыт, но хотелось чего-то нового. Да и не хотелось лишних зависимостей.
P.S. После 40кб ошибок спирита, типичные бустоошибки кажутся маленькими и понятными, а обычные с++ные - ничтожными и не заслуживающими внимания...
LispGovno 26.04.2013 21:56 # 0
Как ты это осилил? Это вообще пушка. Я от этого столько плювался в ускорении::духа
bormand 27.04.2013 08:42 # +2
roman-kashitsyn 27.04.2013 09:41 # +1
Померещилось 40 литров спирта
bormand 27.04.2013 10:01 # +1
LispGovno 27.04.2013 11:27 # 0
Stertor 03.10.2013 17:48 # +1
LispGovno 26.04.2013 16:40 # +2
3.14159265 19.01.2014 21:54 # +2
LispGovno 26.04.2013 16:41 # 0
bormand 26.04.2013 16:48 # +1
LispGovno 26.04.2013 16:42 # 0
А можно парочку?
bormand 26.04.2013 16:44 # +1
LispGovno 26.04.2013 16:44 # 0
bormand 26.04.2013 16:46 # +2
LispGovno 26.04.2013 18:06 # −3
LispGovno 19.01.2014 22:49 # +2
Sh1tM4ker 26.04.2013 17:14 # +1
В этом коде еще не так заметно, но вот такое часто вижу http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01437_source.html
bormand 26.04.2013 17:20 # +2
roman-kashitsyn 26.04.2013 18:55 # +1
Certain sets of names and function signatures are always reserved to the implementation:
— Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter
(2.11) is reserved to the implementation for any use.
— Each name that begins with an underscore is reserved to the implementation for use as a name in the global
namespace.