2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-19 04:22:13 +00:00

scalar parsers

This commit is contained in:
Joel de Guzman
2011-11-09 13:49:20 +08:00
parent f7b96761c7
commit ccb47ab934
3 changed files with 233 additions and 24 deletions

View File

@@ -9,37 +9,48 @@
#include <string>
#include <map>
#include <vector>
#include <boost/variant.hpp>
#include <boost/spirit/include/support_extended_variant.hpp>
namespace omd{ namespace json
namespace omd { namespace ast
{
// ------------------- json types --------------------
//
typedef std::string string_t;
typedef double number_t;
typedef bool bool_t;
struct null_t
{
// ------------------- AST types --------------------
//
typedef std::string string_t;
typedef double double_t;
typedef int int_t;
typedef bool bool_t;
struct null_t
{
// nulls always compare
bool operator==(const null_t&) const{ return true; }
bool operator!=(const null_t&) const{ return false; }
};
};
typedef boost::make_recursive_variant<
null_t,
bool_t,
string_t,
number_t,
std::map<string_t,
boost::recursive_variant_>,
std::vector<boost::recursive_variant_>
>::type value_t;
struct value_t;
typedef std::map<std::string, value_t> object_t;
typedef std::vector<value_t> array_t;
typedef std::map<std::string, value_t> object_t;
typedef std::vector<value_t> array_t;
struct value_t
: boost::spirit::extended_variant<
null_t,
bool_t,
string_t,
double_t,
int_t,
object_t
>
{
value_t(string_t const& val) : base_type(val) {}
value_t(double_t val) : base_type(val) {}
value_t(int_t val) : base_type(val) {}
value_t(bool_t val) : base_type(val) {}
value_t(null_t val = null_t()) : base_type(val) {}
// ---------------------------------------------------
value_t(value_t const& rhs)
: base_type(rhs.get()) {}
};
// ---------------------------------------------------
}}
#endif

45
yaml/parser/scalar.hpp Normal file
View File

@@ -0,0 +1,45 @@
/**
* Copyright (C) 2010, 2011 Object Modeling Designs
*/
#if !defined(OMD_PARSER_STRING)
#define OMD_PARSER_STRING
#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
#include <string>
#include <boost/spirit/include/qi.hpp>
#include "../ast.hpp" // our AST
namespace omd { namespace parser
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef boost::uint32_t uchar; // a unicode code point
template <typename Iterator>
struct unicode_string : qi::grammar<Iterator, std::string()>
{
unicode_string();
qi::rule<Iterator, void(std::string&)> char_esc;
qi::rule<Iterator, std::string()> char_lit;
qi::rule<Iterator, std::string()> start;
};
template <typename Iterator>
struct scalar : qi::grammar<Iterator, ast::value_t(), ascii::space_type>
{
scalar();
qi::rule<Iterator, ast::value_t(), ascii::space_type> value;
unicode_string<Iterator> string_value;
qi::rule<Iterator, int()> integer_value;
qi::symbols<bool, std::string> bool_value;
qi::rule<Iterator, ast::null_t(), ascii::space_type > null_value;
};
}}
#endif

153
yaml/parser/scalar_def.hpp Normal file
View File

@@ -0,0 +1,153 @@
/**
* Copyright (C) 2010, 2011 Object Modeling Designs
*/
#if !defined(OMD_COMMON_STRING_DEF)
#define OMD_COMMON_STRING_DEF
#include "scalar.hpp"
#include <boost/cstdint.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_container.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/regex/pending/unicode_iterator.hpp>
namespace omd { namespace parser
{
namespace detail
{
struct push_utf8
{
template <typename S, typename C>
struct result { typedef void type; };
void operator()(std::string& utf8, uchar code_point) const
{
typedef std::back_insert_iterator<std::string> insert_iter;
insert_iter out_iter(utf8);
boost::utf8_output_iterator<insert_iter> utf8_iter(out_iter);
*utf8_iter++ = code_point;
}
};
struct push_esc
{
template <typename S, typename C>
struct result { typedef void type; };
void operator()(std::string& utf8, uchar c) const
{
switch (c)
{
case 'b': utf8 += '\b'; break;
case 't': utf8 += '\t'; break;
case 'n': utf8 += '\n'; break;
case 'f': utf8 += '\f'; break;
case 'r': utf8 += '\r'; break;
case '"': utf8 += '"'; break;
case '/': utf8 += '/'; break;
case '\\': utf8 += '\\'; break;
}
}
};
}
template <typename Iterator>
unicode_string<Iterator>::unicode_string()
: unicode_string::base_type(start)
{
qi::char_type char_;
qi::_val_type _val;
qi::_r1_type _r1;
qi::_1_type _1;
using boost::spirit::qi::uint_parser;
using boost::phoenix::function;
uint_parser<uchar, 16, 4, 4> hex4;
uint_parser<uchar, 16, 8, 8> hex8;
function<detail::push_utf8> push_utf8;
function<detail::push_esc> push_esc;
char_esc
= '\\'
> ( ('u' > hex4) [push_utf8(_r1, _1)]
| ('U' > hex8) [push_utf8(_r1, _1)]
| char_("btnfr/\\\"'") [push_esc(_r1, _1)]
)
;
char_lit
= '\''
> (char_esc(_val) | (~char_('\'')) [_val += _1])
> '\''
;
start
= '"'
> *(char_esc(_val) | (~char_('"')) [_val += _1])
> '"'
;
BOOST_SPIRIT_DEBUG_NODES(
(char_esc)
(char_lit)
(start)
);
}
template <typename Iterator>
scalar<Iterator>::scalar()
: scalar::base_type(value)
{
qi::_val_type _val;
qi::lit_type lit;
qi::lexeme_type lexeme;
qi::char_type char_;
qi::hex_type hex;
qi::oct_type oct_;
qi::no_case_type no_case;
qi::lexeme_type lexeme;
real_parser<double, strict_real_policies<double> > double_value;
value =
string_value
| double_value
| integer_value
| no_case[bool_value]
| no_case[null_value]
;
integer_value =
lexeme[no_case["0x"] > hex]
| lexeme['0' >> oct]
| int_
;
bool_value.add
("true", true)
("false", false)
("on", true)
("off", false)
("yes", true)
("no", false)
;
null_value =
(lit("null") | '~')
>> qi::attr(ast::null_t())
;
BOOST_SPIRIT_DEBUG_NODES(
(value)
(integer_value)
(bool_value)
(null_value)
);
}
}}
#endif