2
0
mirror of https://github.com/boostorg/spirit.git synced 2026-01-19 04:42:11 +00:00
Files
spirit/example/qi/reference.cpp
Joel de Guzman 4515d9fa87 More docs
[SVN r56052]
2009-09-05 15:01:50 +00:00

446 lines
12 KiB
C++

/*=============================================================================
Copyright (c) 2001-2009 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 <iostream>
#include <string>
//]
//[reference_test
template <typename P>
void test_parser(char const* input, P const& p)
{
using boost::spirit::qi::parse;
std::string s(input);
std::string::iterator f(s.begin());
if (parse(f, s.end(), p))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
template <typename P>
void test_phrase_parser(char const* input, P const& p)
{
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::ascii::space;
std::string s(input);
std::string::iterator f(s.begin());
if (phrase_parse(f, s.end(), p, space))
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)
{
using boost::spirit::qi::parse;
std::string s(input);
std::string::iterator f(s.begin());
if (parse(f, s.end(), p, attr))
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)
{
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::ascii::space;
std::string s(input);
std::string::iterator f(s.begin());
if (phrase_parse(f, s.end(), p, space, attr))
std::cout << "ok" << std::endl;
else
std::cout << "fail" << std::endl;
}
//]
//[reference_test_real_policy
///////////////////////////////////////////////////////////////////////////////
// These policies can be used to parse thousand separated
// numbers with at most 2 decimal digits after the decimal
// point. e.g. 123,456,789.01
///////////////////////////////////////////////////////////////////////////////
template <typename T>
struct ts_real_policies : boost::spirit::qi::ureal_policies<T>
{
// 2 decimal places Max
template <typename Iterator, typename Attribute>
static bool
parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr)
{
return boost::spirit::qi::
extract_uint<T, 10, 1, 2, true>::call(first, last, attr);
}
// No exponent
template <typename Iterator>
static bool
parse_exp(Iterator&, Iterator const&)
{
return false;
}
// No exponent
template <typename Iterator, typename Attribute>
static bool
parse_exp_n(Iterator&, Iterator const&, Attribute&)
{
return false;
}
// Thousands separated numbers
template <typename Iterator, typename Attribute>
static bool
parse_n(Iterator& first, Iterator const& last, Attribute& attr)
{
using boost::spirit::qi::uint_parser;
namespace qi = boost::spirit::qi;
uint_parser<unsigned, 10, 1, 3> uint3;
uint_parser<unsigned, 10, 3, 3> uint3_3;
T result = 0;
if (parse(first, last, uint3, result))
{
bool hit = false;
T n;
Iterator save = first;
while (qi::parse(first, last, ',') && qi::parse(first, last, uint3_3, n))
{
result = result * 1000 + n;
save = first;
hit = true;
}
first = save;
if (hit)
attr = result;
return hit;
}
return false;
}
};
//]
int
main()
{
{
//[reference_using_declarations_lit_char
using boost::spirit::qi::lit;
using boost::spirit::ascii::char_;
//]
//[reference_char_literals
test_parser("x", 'x'); // plain literal
test_parser("x", lit('x')); // explicit literal
test_parser("x", char_('x')); // ascii::char_
//]
//[reference_char_range
char ch;
test_parser_attr("5", char_('0','9'), ch); // ascii::char_ range
std::cout << ch << std::endl; // prints '5'
//]
//[reference_char_set
test_parser_attr("5", char_("0-9"), ch); // ascii::char_ set
std::cout << ch << std::endl; // prints '5'
//]
//[reference_char_phoenix
namespace phx = boost::phoenix;
test_parser("x", phx::val('x')); // direct
test_parser("5",
char_(phx::val('0'),phx::val('9'))); // ascii::char_ range
//]
}
{
//[reference_using_declarations_lit_string
using boost::spirit::qi::lit;
using boost::spirit::ascii::string;
//]
//[reference_string_literals
test_parser("boost", "boost"); // plain literal
test_parser("boost", lit("boost")); // explicit literal
test_parser("boost", string("boost")); // ascii::string
//]
}
{
using boost::spirit::qi::lit;
using boost::spirit::ascii::string;
//[reference_string_std_string
std::string s("boost");
test_parser("boost", s); // direct
test_parser("boost", lit(s)); // explicit
test_parser("boost", string(s)); // ascii::string
//]
}
{
using boost::spirit::qi::lit;
using boost::spirit::ascii::string;
//[reference_string_phoenix
namespace phx = boost::phoenix;
test_parser("boost", phx::val("boost")); // direct
test_parser("boost", lit(phx::val("boost"))); // explicit
test_parser("boost", string(phx::val("boost"))); // ascii::string
//]
}
{
//[reference_using_declarations_symbols
using boost::spirit::qi::symbols;
//]
//[reference_symbols_with_data
symbols<char, int> sym;
sym.add
("Apple", 1)
("Banana", 2)
("Orange", 3)
;
int i;
test_parser_attr("Banana", sym, i);
std::cout << i << std::endl;
//]
}
{
//[reference_using_declarations_lexeme
using boost::spirit::qi::lexeme;
using boost::spirit::qi::lit;
using boost::spirit::ascii::digit;
//]
//[reference_lexeme
/*`The use of lexeme here will prevent skipping in between the
digits and the sign making inputs such as `"1 2 345"` erroneous.*/
test_phrase_parser("12345", lexeme[ -(lit('+') | '-') >> +digit ]);
//]
}
{
//[reference_using_declarations_no_case
using boost::spirit::ascii::no_case;
using boost::spirit::ascii::char_;
using boost::spirit::ascii::alnum;
using boost::spirit::qi::symbols;
//]
//[reference_no_case
test_parser("X", no_case[char_('x')]);
test_parser("6", no_case[alnum]);
//]
//[reference_symbols_with_no_case
symbols<char, int> sym;
sym.add
("apple", 1) // symbol strings are added in lowercase...
("banana", 2)
("orange", 3)
;
int i;
// ...because sym is used for case-insensitive parsing
test_parser_attr("Apple", no_case[ sym ], i);
std::cout << i << std::endl;
test_parser_attr("ORANGE", no_case[ sym ], i);
std::cout << i << std::endl;
//]
}
{
//[reference_using_declarations_omit
using boost::spirit::qi::omit;
using boost::spirit::qi::int_;
using boost::spirit::ascii::char_;
//]
//[reference_omit
/*`This parser ignores the first two characters
and extracts the succeeding `int`:*/
int i;
test_parser_attr("xx345", omit[char_ >> char_] >> int_, i);
std::cout << i << std::endl; // should print 345
//]
}
{
//[reference_using_declarations_raw
using boost::spirit::qi::raw;
using boost::spirit::ascii::alpha;
using boost::spirit::ascii::alnum;
//]
//[reference_raw
//`This parser matches and extracts C++ identifiers:
std::string id;
test_parser_attr("James007", raw[(alpha | '_') >> *(alnum | '_')], id);
std::cout << id << std::endl; // should print James007
//]
}
// attr()
{
//[reference_using_declarations_attr
namespace phx = boost::phoenix;
using boost::spirit::qi::attr;
//]
//[reference_attr
std::string str;
test_parser_attr("", attr("boost"), str);
std::cout << str << std::endl; // will print 'boost'
double d;
test_parser_attr("", attr(1.0), d);
std::cout << d << std::endl; // will print '1.0'
//]
//[reference_attr_phoenix
d = 0.0;
double d1 = 1.2;
test_parser_attr("", attr(phx::ref(d1)), d);
std::cout << d << std::endl; // will print '1.2'
//]
}
// eol
{
//[reference_using_declarations_eol
using boost::spirit::qi::eol;
//]
//[reference_eol
test_parser("\n", eol);
//]
}
// eoi
{
//[reference_using_declarations_eoi
using boost::spirit::qi::eoi;
//]
//[reference_eoi
test_parser("", eoi);
//]
}
// lazy
{
//[reference_using_declarations_lazy
using boost::spirit::qi::lazy;
using boost::spirit::ascii::string;
using boost::phoenix::val;
//]
//[reference_lazy
/*` Here, the phoenix::val expression creates a function
that returns its argument when invoked. The lazy expression
defers the invocation of this function at parse time. Then,
this parser (string parser) is called into action. All this
takes place at parse time.
*/
test_parser("Hello", lazy(val(string("Hello"))));
//` The above is equivalent to:
test_parser("Hello", val(string("Hello")));
//]
}
// char class
{
//[reference_using_declarations_char_class
using boost::spirit::ascii::alnum;
using boost::spirit::ascii::blank;
using boost::spirit::ascii::digit;
using boost::spirit::ascii::lower;
//]
//[reference_char_class
test_parser("1", alnum);
test_parser(" ", blank);
test_parser("1", digit);
test_parser("a", lower);
//]
}
// uint
{
//[reference_using_declarations_uint
using boost::spirit::qi::uint_;
using boost::spirit::qi::uint_parser;
//]
//[reference_uint
test_parser("12345", uint_);
//]
//[reference_thousand_separated
//`Thousand separated number parser:
uint_parser<unsigned, 10, 1, 3> uint3_p; // 1..3 digits
uint_parser<unsigned, 10, 3, 3> uint3_3_p; // exactly 3 digits
test_parser("12,345,678", uint3_p >> *(',' >> uint3_3_p));
//]
}
// int
{
//[reference_using_declarations_int
using boost::spirit::qi::int_;
//]
//[reference_int
test_parser("+12345", int_);
test_parser("-12345", int_);
//]
}
// real
{
//[reference_using_declarations_real
using boost::spirit::qi::double_;
using boost::spirit::qi::real_parser;
//]
//[reference_real
test_parser("+12345e6", double_);
//]
//[reference_custom_real
real_parser<double, ts_real_policies<double> > ts_real;
test_parser("123,456,789.01", ts_real);
//]
}
return 0;
}