spirit/repository/example/qi/keywords.cpp
2015-03-29 13:30:24 +03:00

215 lines
6.7 KiB
C++

/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
http://spirit.sourceforge.net/
Distributed under 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)
=============================================================================*/
//[reference_includes
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/repository/include/qi_kwd.hpp>
#include <boost/spirit/repository/include/qi_keywords.hpp>
#include <iostream>
#include <string>
#include <cstdlib>
#include <iterator>
//]
//[reference_test
template <typename P>
void test_parser(
char const* input, P const& p, bool full_match = true)
{
using boost::spirit::qi::parse;
char const* f(input);
char const* l(f + strlen(f));
if (parse(f, l, p) && (!full_match || (f == l)))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
template <typename P>
void test_phrase_parser(
char const* input, P const& p, bool full_match = true)
{
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::ascii::space;
char const* f(input);
char const* l(f + strlen(f));
if (phrase_parse(f, l, p, space) && (!full_match || (f == l)))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
//]
//[reference_test_attr
template <typename P, typename T>
void test_parser_attr(
char const* input, P const& p, T& attr, bool full_match = true)
{
using boost::spirit::qi::parse;
char const* f(input);
char const* l(f + strlen(f));
if (parse(f, l, p, attr) && (!full_match || (f == l)))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
template <typename P, typename T>
void test_phrase_parser_attr(
char const* input, P const& p, T& attr, bool full_match = true)
{
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::ascii::space;
char const* f(input);
char const* l(f + strlen(f));
if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
//]
//[reference_keyword_list_test_data_structure
// Data structure definitions to test the kwd directive
// and the keywords list operator
struct person {
std::string name;
int age;
double size;
std::vector<std::string> favorite_colors;
};
std::ostream &operator<<(std::ostream &os, const person &p)
{
os<<"Person : "<<p.name<<", "<<p.age<<", "<<p.size<<std::endl;
std::copy(p.favorite_colors.begin(),p.favorite_colors.end(),std::ostream_iterator<std::string>(os,"\n"));
return os;
}
BOOST_FUSION_ADAPT_STRUCT( person,
(std::string, name)
(int, age)
(double, size)
(std::vector<std::string>, favorite_colors)
)
//]
int
main()
{
// keyword_list
{
//[reference_using_declarations_keyword_list
using boost::spirit::repository::qi::kwd;
using boost::spirit::qi::inf;
using boost::spirit::ascii::space_type;
using boost::spirit::ascii::char_;
using boost::spirit::qi::double_;
using boost::spirit::qi::int_;
using boost::spirit::qi::rule;
//]
//[reference_keyword_list_rule_declarations
rule<const char *, std::string(), space_type> parse_string;
rule<const char *, person(), space_type> no_constraint_person_rule, constraint_person_rule;
parse_string %= '"'> *(char_-'"') > '"';
//]
//[reference_keyword_list_no_constraint_rule
no_constraint_person_rule %=
kwd("name")['=' > parse_string ]
/ kwd("age") ['=' > int_]
/ kwd("size") ['=' > double_ > 'm']
;
//]
//[reference_keyword_list
//`Parsing a keyword list:
// Let's declare a small list of people for which we want to collect information.
person John,Mary,Mike,Hellen,Johny;
test_phrase_parser_attr(
"name = \"John\" \n age = 10 \n size = 1.69m "
,no_constraint_person_rule
,John); // full in orginal order
std::cout<<John;
test_phrase_parser_attr(
"age = 10 \n size = 1.69m \n name = \"Mary\""
,no_constraint_person_rule
,Mary); // keyword oder doesn't matter
std::cout<<Mary;
test_phrase_parser_attr(
"size = 1.69m \n name = \"Mike\" \n age = 10 "
,no_constraint_person_rule
,Mike); // still the same result
std::cout<<Mike;
/*`The code above will print:[teletype]
Person : John, 10, 1.69
Person : Mary, 10, 1.69
Person : Mike, 10, 1.69
*/
//]
//[reference_keyword_list_constraint_rule
/*`The parser definition below uses the kwd directive occurrence constraint variants to
make sure that the name and age keyword occur only once and allows the favorite color
entry to appear 0 or more times. */
constraint_person_rule %=
kwd("name",1) ['=' > parse_string ]
/ kwd("age" ,1) ['=' > int_]
/ kwd("size" ,1) ['=' > double_ > 'm']
/ kwd("favorite color",0,inf) [ '=' > parse_string ]
;
//]
//[reference_keyword_list_constraints
// Here all the give constraint are resepected : parsing will succeed.
test_phrase_parser_attr(
"name = \"Hellen\" \n age = 10 \n size = 1.80m \n favorite color = \"blue\" \n favorite color = \"green\" "
,constraint_person_rule
,Hellen);
std::cout<<Hellen;
// Parsing this string will fail because the age and size minimum occurrence requirements aren't met.
test_phrase_parser_attr(
"name = \"Johny\" \n favorite color = \"blue\" \n favorite color = \"green\" "
,constraint_person_rule
,Johny );
/*`Parsing the first string will succeed but fail for the second string as the
occurrence constraints aren't met. This code should print:[teletype]
Person : Hellen, 10, 1.8
blue
green
*/
//]
}
return 0;
}