From ccb47ab934cdc4391534ca8f92fb52c30c7928a3 Mon Sep 17 00:00:00 2001 From: Joel de Guzman Date: Wed, 9 Nov 2011 13:49:20 +0800 Subject: [PATCH] scalar parsers --- yaml/ast.hpp | 59 ++++++++------ yaml/parser/scalar.hpp | 45 +++++++++++ yaml/parser/scalar_def.hpp | 153 +++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 24 deletions(-) create mode 100644 yaml/parser/scalar.hpp create mode 100644 yaml/parser/scalar_def.hpp diff --git a/yaml/ast.hpp b/yaml/ast.hpp index 22bf6634..48d4bef1 100644 --- a/yaml/ast.hpp +++ b/yaml/ast.hpp @@ -9,37 +9,48 @@ #include #include #include -#include +#include - -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, - std::vector - >::type value_t; + struct value_t; + typedef std::map object_t; + typedef std::vector array_t; - typedef std::map object_t; - typedef std::vector 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 diff --git a/yaml/parser/scalar.hpp b/yaml/parser/scalar.hpp new file mode 100644 index 00000000..28965a96 --- /dev/null +++ b/yaml/parser/scalar.hpp @@ -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 + +#include +#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 + struct unicode_string : qi::grammar + { + unicode_string(); + + qi::rule char_esc; + qi::rule char_lit; + qi::rule start; + }; + + template + struct scalar : qi::grammar + { + scalar(); + + qi::rule value; + unicode_string string_value; + qi::rule integer_value; + qi::symbols bool_value; + qi::rule null_value; + }; +}} + +#endif diff --git a/yaml/parser/scalar_def.hpp b/yaml/parser/scalar_def.hpp new file mode 100644 index 00000000..393e07cc --- /dev/null +++ b/yaml/parser/scalar_def.hpp @@ -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 +#include +#include +#include +#include +#include +#include + +namespace omd { namespace parser +{ + namespace detail + { + struct push_utf8 + { + template + struct result { typedef void type; }; + + void operator()(std::string& utf8, uchar code_point) const + { + typedef std::back_insert_iterator insert_iter; + insert_iter out_iter(utf8); + boost::utf8_output_iterator utf8_iter(out_iter); + *utf8_iter++ = code_point; + } + }; + + struct push_esc + { + template + 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 + unicode_string::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 hex4; + uint_parser hex8; + function push_utf8; + function 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 + scalar::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_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