// // Experimental Spirit parser // #include #include /////////////////////////////////////////////////////////////////////////////// struct nil_t {}; // As always... Our special nil type... /////////////////////////////////////////////////////////////////////////////// template struct parser { DerivedT const& derived() const { return *static_cast(this); } }; /////////////////////////////////////////////////////////////////////////////// struct match { operator bool() const { return data >= 0; } int data; }; /////////////////////////////////////////////////////////////////////////////// template struct basic_parser_arg { typedef IteratorT iterator_t; typedef match result_t; basic_parser_arg(IteratorT const& first_, IteratorT const& last_) : first(first_), last(last_) {} static match no_match() { match m; m.data = -1; return m; } static match create_match(unsigned len, IteratorT const& first, IteratorT const& last) { match m; m.data = len; return m; } static void concat_match(match& lhs, match const& rhs) { assert(lhs && rhs); lhs.data += rhs.data; } IteratorT first; IteratorT const last; }; /////////////////////////////////////////////////////////////////////////////// template struct char_parser : parser > { char_parser(CharT ch_) : ch(ch_) {} template typename ArgT::result_t parse(ArgT& arg) const { if ((arg.first != arg.last) && (ch == *arg.first)) { typename ArgT::iterator_t s(arg.first); ++arg.first; return arg.create_match(1, s, arg.first); } return arg.no_match(); } CharT ch; }; template char_parser ch_p(CharT ch) { return char_parser(ch); } /////////////////////////////////////////////////////////////////////////////// struct digit_parser : parser { template typename ArgT::result_t parse(ArgT& arg) const { if ((arg.first != arg.last) && std::isdigit(*arg.first)) { typename ArgT::iterator_t s(arg.first); ++arg.first; return arg.create_match(1, s, arg.first); } return arg.no_match(); } }; digit_parser const digit_p = digit_parser(); /////////////////////////////////////////////////////////////////////////////// template struct sequence : public parser > { sequence(LHS const& lhs_, RHS const& rhs_) : lhs(lhs_), rhs(rhs_) {} template typename ArgT::result_t parse(ArgT& arg) const { typename ArgT::result_t ra, rb; if ((ra = lhs.parse(arg)) && (rb = rhs.parse(arg))) { arg.concat_match(ra, rb); return ra; } return arg.no_match(); } LHS lhs; RHS rhs; }; template sequence operator>>(parser const& lhs, parser const& rhs) { return sequence(lhs.derived(), rhs.derived()); } template sequence > operator>>(parser const& lhs, char rhs) { return sequence >(lhs.derived(), rhs); } template sequence, RHS> operator>>(char lhs, parser const& rhs) { return sequence, RHS>(lhs, rhs.derived()); } /////////////////////////////////////////////////////////////////////////////// template struct alternative : public parser > { alternative(LHS const& lhs_, RHS const& rhs_) : lhs(lhs_), rhs(rhs_) {} template typename ArgT::result_t parse(ArgT& arg) const { { // scope for save typename ArgT::iterator_t save = arg.first; if (typename ArgT::result_t r = lhs.parse(arg)) return r; arg.first = save; } return rhs.parse(arg); } LHS lhs; RHS rhs; }; template alternative operator|(parser const& lhs, parser const& rhs) { return alternative(lhs.derived(), rhs.derived()); } /////////////////////////////////////////////////////////////////////////////// template struct kleene_star : public parser > { kleene_star(SubjectT const& subject_) : subject(subject_) {} template typename ArgT::result_t parse(ArgT& arg) const { typename ArgT::result_t r = arg.create_match(0, arg.first, arg.first); while (true) { typename ArgT::iterator_t save = arg.first; if (typename ArgT::result_t next = subject.parse(arg)) { save = arg.first; arg.concat_match(r, next); } else { arg.first = save; return r; } } } SubjectT subject; }; template kleene_star operator*(parser const& subject) { return kleene_star(subject.derived()); } /////////////////////////////////////////////////////////////////////////////// template struct grammar; template struct rule; namespace impl { template struct get_rule { typedef typename get_rule::type type; static type const& get(GrammarT const& g) { return get_rule::get(g.rest); } }; template struct get_rule, RestT> > { typedef rule type; static type const& get(grammar, RestT> const& g) { return g.first; } }; } template struct grammar_arg : public ArgT { grammar_arg(ArgT const& arg, GrammarT const& rules_) : ArgT(arg), rules(rules_) {} template typename ArgT::result_t use_rule() { return impl::get_rule::get(rules).parse(*this); } GrammarT const& rules; }; template struct grammar : parser > { typedef grammar self_t; typedef FirstT first_t; typedef RestT rest_t; grammar(FirstT const& first_, RestT const& rest_) : first(first_), rest(rest_) {} template typename ArgT::result_t parse(ArgT& arg) const { grammar_arg g_arg(arg, *this); return impl::get_rule<0, self_t>::get(*this).parse(g_arg); } FirstT first; RestT rest; }; /////////////////////////////////////////////////////////////////////////////// template struct rule : public parser > { rule(RHS const& rhs_) : rhs(rhs_) {} template typename ArgT::result_t parse(ArgT& arg) const { return rhs.parse(arg); } RHS rhs; }; template grammar, grammar, nil_t> > operator,(rule const& lhs, rule const& rhs) { return grammar, grammar, nil_t> > (lhs, grammar, nil_t>(rhs, nil_t())); } template grammar, grammar > operator,(grammar const& lhs, rule const& rhs) { return grammar, grammar >(rhs, lhs); } /////////////////////////////////////////////////////////////////////////////// template struct rule_id : public parser > { template typename ArgT::result_t parse(ArgT& arg) const { return arg.template use_rule(); } template rule operator=(const parser& rhs) const { return rule(rhs.derived()); } }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // // TEST // /////////////////////////////////////////////////////////////////////////////// #include using namespace std; match parse(char const* first, char const* last) { basic_parser_arg parg(first, last); rule_id<0> expression; rule_id<1> term; rule_id<2> factor; return ( factor = digit_p | '(' >> expression >> ')' | ('-' >> factor) , term = factor >> *( ('*' >> factor) | ('/' >> factor) ) , expression = term >> *( ('+' >> term) | ('-' >> term) ) ).parse(parg); } int main() { while (true) { char str[256]; cin.getline(str, 256); if (str[0] == 'q' || str[0] == 'Q') break; match m = parse(str, str+strlen(str)); cout << "match.length = " << m.data << '\n'; } }