blob: 7bfc17dfd74d8543cb202482ce1663764920ef0e [file] [log] [blame]
/*=============================================================================
Copyright (c) 1998-2003 Joel de Guzman
http://spirit.sourceforge.net/
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#include <iostream>
#include <boost/detail/lightweight_test.hpp>
using namespace std;
//#define BOOST_SPIRIT_DEBUG
#define BOOST_SPIRIT_RULE_SCANNERTYPE_LIMIT 3
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_stored_rule.hpp>
using namespace BOOST_SPIRIT_CLASSIC_NS;
///////////////////////////////////////////////////////////////////////////////
//
// Rule tests
//
///////////////////////////////////////////////////////////////////////////////
void
aliasing_tests()
{
rule<> a = ch_p('a');
rule<> b = ch_p('b');
rule<> c = ch_p('c');
cout << "sizeof(rule<>): " << sizeof(rule<>) << endl;
BOOST_SPIRIT_DEBUG_RULE(a);
BOOST_SPIRIT_DEBUG_RULE(b);
BOOST_SPIRIT_DEBUG_RULE(c);
rule<> start;
BOOST_SPIRIT_DEBUG_RULE(start);
rule<> d;
d = start; // aliasing
parse_info<char const*> pi;
start = *(a | b | c);
pi = parse("abcabcacb", d);
BOOST_TEST(pi.hit);
BOOST_TEST(pi.full);
BOOST_TEST(pi.length == 9);
BOOST_TEST(*pi.stop == 0);
start = (a | b) >> (start | b);
pi = parse("aaaabababaaabbb", d);
BOOST_TEST(pi.hit);
BOOST_TEST(pi.full);
BOOST_TEST(pi.length == 15);
BOOST_TEST(*pi.stop == 0);
}
void
rule_template_param_tests()
{
// test that rules can be issued its template params in any order:
rule<> rx1;
rule<scanner<> > rx2;
rule<scanner<>, parser_context<> > rx3;
rule<scanner<>, parser_context<>, parser_address_tag> rx4;
rule<parser_context<> > rx5;
rule<parser_context<>, parser_address_tag> rx6;
rule<parser_context<>, parser_address_tag, scanner<> > rx7;
rule<parser_address_tag> rx8;
rule<parser_address_tag, scanner<> > rx9;
rule<parser_address_tag, scanner<>, parser_context<> > rx10;
rule<parser_address_tag, parser_context<> > rx11;
rule<parser_address_tag, parser_context<>, scanner<> > rx12;
rule<parser_context<>, scanner<> > rx13;
rule<parser_context<>, scanner<>, parser_address_tag> rx14;
}
struct my_grammar : public grammar<my_grammar>
{
template <typename ScannerT>
struct definition
{
definition(my_grammar const& /*self*/)
{
r = lower_p;
rr = +(lexeme_d[r] >> as_lower_d[r] >> r);
}
typedef scanner_list<
ScannerT
, typename lexeme_scanner<ScannerT>::type
, typename as_lower_scanner<ScannerT>::type
> scanners;
rule<scanners> r;
rule<ScannerT> rr;
rule<ScannerT> const& start() const { return rr; }
};
};
void
rule_2_or_more_scanners_tests()
{
{ // 2 scanners
typedef scanner_list<scanner<>, phrase_scanner_t> scanners;
rule<scanners> r = +anychar_p;
BOOST_TEST(parse("abcdefghijk", r).full);
BOOST_TEST(parse("a b c d e f g h i j k", r, space_p).full);
}
{ // 3 scanners
my_grammar g;
BOOST_TEST(parse("abcdef aBc d e f aBc d E f", g, space_p).full);
}
}
void
rule_basic_tests()
{
rule<> a = ch_p('a');
rule<> b = ch_p('b');
rule<> c = ch_p('c');
BOOST_SPIRIT_DEBUG_RULE(a);
BOOST_SPIRIT_DEBUG_RULE(b);
BOOST_SPIRIT_DEBUG_RULE(c);
parse_info<char const*> pi;
rule<> start = *(a | b | c);
BOOST_SPIRIT_DEBUG_RULE(start);
pi = parse("abcabcacb", start);
BOOST_TEST(pi.hit);
BOOST_TEST(pi.full);
BOOST_TEST(pi.length == 9);
BOOST_TEST(*pi.stop == 0);
start = (a | b) >> (start | b);
pi = parse("aaaabababaaabbb", start);
BOOST_TEST(pi.hit);
BOOST_TEST(pi.full);
BOOST_TEST(pi.length == 15);
BOOST_TEST(*pi.stop == 0);
pi = parse("aaaabababaaabba", start);
BOOST_TEST(pi.hit);
BOOST_TEST(!pi.full);
BOOST_TEST(pi.length == 14);
rule<> r = anychar_p;
r.copy(); // copy test (compile only)
}
void
stored_rule_basic_tests()
{
stored_rule<> a = ch_p('a');
stored_rule<> b = ch_p('b');
stored_rule<> c = ch_p('c');
BOOST_SPIRIT_DEBUG_RULE(a);
BOOST_SPIRIT_DEBUG_RULE(b);
BOOST_SPIRIT_DEBUG_RULE(c);
parse_info<char const*> pi;
stored_rule<> start = *(a | b | c);
BOOST_SPIRIT_DEBUG_RULE(start);
pi = parse("abcabcacb", start);
BOOST_TEST(pi.hit);
BOOST_TEST(pi.full);
BOOST_TEST(pi.length == 9);
BOOST_TEST(*pi.stop == 0);
start = (a | b) >> (start | b);
pi = parse("aaaabababaaabbb", start);
BOOST_TEST(pi.hit);
BOOST_TEST(pi.full);
BOOST_TEST(pi.length == 15);
BOOST_TEST(*pi.stop == 0);
pi = parse("aaaabababaaabba", start);
BOOST_TEST(pi.hit);
BOOST_TEST(!pi.full);
BOOST_TEST(pi.length == 14);
}
void
stored_rule_dynamic_tests()
{
rule<> a = ch_p('a');
rule<> b = ch_p('b');
rule<> c = ch_p('c');
BOOST_SPIRIT_DEBUG_RULE(a);
BOOST_SPIRIT_DEBUG_RULE(b);
BOOST_SPIRIT_DEBUG_RULE(c);
parse_info<char const*> pi;
// The FF is the dynamic equivalent of start = *(a | b | c);
stored_rule<> start = a;
start = start.copy() | b;
start = start.copy() | c;
start = *(start.copy());
cout << "sizeof(stored_rule<>): " << sizeof(stored_rule<>) << endl;
BOOST_SPIRIT_DEBUG_RULE(start);
pi = parse("abcabcacb", start);
BOOST_TEST(pi.hit);
BOOST_TEST(pi.full);
BOOST_TEST(pi.length == 9);
BOOST_TEST(*pi.stop == 0);
// The FF is the dynamic equivalent of start = (a | b) >> (start | b);
start = b;
start = a | start.copy();
start = start.copy() >> (start | b);
pi = parse("aaaabababaaabbb", start);
BOOST_TEST(pi.hit);
BOOST_TEST(pi.full);
BOOST_TEST(pi.length == 15);
BOOST_TEST(*pi.stop == 0);
pi = parse("aaaabababaaabba", start);
BOOST_TEST(pi.hit);
BOOST_TEST(!pi.full);
BOOST_TEST(pi.length == 14);
}
///////////////////////////////////////////////////////////////////////////////
//
// Main
//
///////////////////////////////////////////////////////////////////////////////
int
main()
{
rule_basic_tests();
aliasing_tests();
rule_template_param_tests();
rule_2_or_more_scanners_tests();
stored_rule_basic_tests();
stored_rule_dynamic_tests();
return boost::report_errors();
}