diff --git a/test/parse_yaml_test.cpp b/test/parse_yaml_test.cpp index 2f1a455b..5fbf6370 100644 --- a/test/parse_yaml_test.cpp +++ b/test/parse_yaml_test.cpp @@ -2,7 +2,7 @@ * Copyright (C) 2010, 2011 Object Modeling Designs */ -#define BOOST_SPIRIT_DEBUG +//~ #define BOOST_SPIRIT_DEBUG #include "../yaml/parser/yaml_def.hpp" #include "../yaml/parser/flow_def.hpp" diff --git a/test/test_files/basic_yaml_block.yaml b/test/test_files/basic_yaml_block.yaml index cbb12dcf..9f767a8d 100644 --- a/test/test_files/basic_yaml_block.yaml +++ b/test/test_files/basic_yaml_block.yaml @@ -5,4 +5,4 @@ national: - New York Mets - Chicago Cubs - - Atlanta Braves \ No newline at end of file + - Atlanta Braves diff --git a/test/test_files/basic_yaml_flow.yaml b/test/test_files/basic_yaml_flow.yaml index f759afc7..24ae9308 100644 --- a/test/test_files/basic_yaml_flow.yaml +++ b/test/test_files/basic_yaml_flow.yaml @@ -1,14 +1,6 @@  # Now we have comments [ - 123.45, - true, - false, - "this is a unicode \u20AC string", - "Τη γλώσσα μου έδωσαν ελληνική", - [ - 92, - ["another string", apple, Sîne], # We also have plain unquoted strings - 'this is a ''unicode'' string' # and we have single quoted strings - ] + apple , + Sîne ] \ No newline at end of file diff --git a/yaml/detail/ast_impl.hpp b/yaml/detail/ast_impl.hpp index 48cdd152..f0e908d8 100644 --- a/yaml/detail/ast_impl.hpp +++ b/yaml/detail/ast_impl.hpp @@ -21,8 +21,7 @@ namespace omd { namespace ast template bool operator()(A const& a, B const& b) const { - BOOST_ASSERT(false); // this should not happen. We cannot compare different types - return false; + return false; // comparing different types returns false } template diff --git a/yaml/parser/scalar.hpp b/yaml/parser/scalar.hpp index f20bbd53..cfe794ea 100644 --- a/yaml/parser/scalar.hpp +++ b/yaml/parser/scalar.hpp @@ -7,6 +7,7 @@ #define OMD_PARSER_SCALAR_HPP #define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS +#define BOOST_SPIRIT_ACTIONS_ALLOW_ATTR_COMPAT #include @@ -29,6 +30,9 @@ namespace omd { namespace parser // These are not allowed as first plain-style character char const* unsafe_first = ",[]{}#&*!|>\\\"%@`"; + // These are not allowed as non-first plain-style character + char const* unsafe_plain = " \n\r\t-?:,[]{}#&*!|>\\\"%@`"; + template struct unicode_string : qi::grammar { diff --git a/yaml/parser/scalar_def.hpp b/yaml/parser/scalar_def.hpp index 81e40616..d8fd1437 100644 --- a/yaml/parser/scalar_def.hpp +++ b/yaml/parser/scalar_def.hpp @@ -65,6 +65,7 @@ namespace omd { namespace parser qi::_r1_type _r1; qi::_1_type _1; qi::lit_type lit; + qi::raw_type raw; using boost::spirit::qi::uint_parser; using boost::phoenix::function; @@ -76,31 +77,36 @@ namespace omd { namespace parser char_esc = '\\' - > ( ('u' > hex4) [push_utf8(_r1, _1)] - | ('U' > hex8) [push_utf8(_r1, _1)] - | char_("btnfr/\\\"'") [push_esc(_r1, _1)] + > ( ('u' > hex4) [push_utf8(_r1, _1)] + | ('U' > hex8) [push_utf8(_r1, _1)] + | char_("btnfr/\\\"'") [push_esc(_r1, _1)] ) ; double_quoted = '"' - > *(char_esc(_val) | (~char_('"')) [_val += _1]) + > *(char_esc(_val) | (~char_('"')) [_val += _1]) > '"' ; single_quoted = '\'' > *( - lit("''") [_val += '\''] - | (~char_('\'')) [_val += _1] + lit("''") [_val += '\''] + | (~char_('\'')) [_val += _1] ) > '\'' ; + auto space = char_(" \r\n\t"); + auto safe_first = ~char_(unsafe_first); + auto safe_plain = ~char_(unsafe_plain); + unquoted = - ~char_(unsafe_first) - >> *(~char_(indicators)) - ; + raw[ + safe_first + >> *((+space >> safe_plain) | safe_plain) + ]; start = double_quoted diff --git a/yaml/parser/yaml.hpp b/yaml/parser/yaml.hpp index b30cfbc3..b85d9ea5 100644 --- a/yaml/parser/yaml.hpp +++ b/yaml/parser/yaml.hpp @@ -7,8 +7,9 @@ #define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS -#include #include "flow.hpp" +#include +#include namespace omd { namespace parser { @@ -19,18 +20,23 @@ namespace omd { namespace parser typedef white_space white_space_t; typedef flow flow_t; + typedef boost::iterator_range range_t; + typedef std::pair raw_block_t; white_space_t ws; qi::rule start; + qi::rule flow; + qi::rule scalar; + //~ qi::rule block_content; flow_t flow_value; qi::rule indent; qi::rule blank_line; - qi::rule line; - qi::rule first_line; - qi::rule > block; + qi::rule line; + qi::rule first_line; + qi::rule > block; - qi::rule blocks; + qi::rule blocks; typedef omd::parser::error_handler error_handler_t; boost::phoenix::function const error_handler; diff --git a/yaml/parser/yaml_def.hpp b/yaml/parser/yaml_def.hpp index 99d9f3e8..87309de2 100644 --- a/yaml/parser/yaml_def.hpp +++ b/yaml/parser/yaml_def.hpp @@ -24,17 +24,73 @@ namespace omd { namespace parser } }; - //~ struct parse_block - //~ { - //~ template - //~ struct result { typedef void type; }; + struct parse_block + { + template + struct result { typedef void type; }; - //~ template - //~ void operator()(This* g) const - //~ { + template + void operator()(YamlG* g, Attr& attr, Ranges const& rngs, bool& pass) const + { + ast::array_t* arr_p = boost::get(&attr); - //~ } - //~ }; + // hack: + if (arr_p == 0) + { + attr = ast::array_t(); + arr_p = boost::get(&attr); + } + + using boost::spirit::qi::parse; + typedef typename Ranges::second_type::const_iterator iter_t; + + { + //~ ast::value_t value; + //~ iter_t first = rngs.first.begin(); + //~ iter_t last = rngs.first.end(); + + //~ bool is_array = phrase_parse(first, last, '-', g->ws, value); + //~ if (boost::get(&attr)) + //~ { + //~ attr = ast::array_t(); + //~ } + + //~ arr_p = boost::get(&attr); + + //~ if (!arr_p) + //~ { + //~ pass = false; + //~ return; + //~ } + + //~ if (phrase_parse(first, last, g->scalar, g->ws, value)) + //~ { + //~ arr_p->push_back(value); + //~ } + //~ else + //~ { + //~ pass = false; + //~ return; + //~ } + + std::string utf8; + detail::push_utf8 push_back; + BOOST_FOREACH(uchar code_point, rngs.first) + { + push_back(utf8, code_point); + } + arr_p->push_back(utf8); + } + + { + ast::value_t value; + iter_t first = rngs.second.begin(); + iter_t last = rngs.second.end(); + if (parse(first, last, *g, value)) + arr_p->push_back(value); + } + } + }; } template @@ -60,24 +116,36 @@ namespace omd { namespace parser qi::eol_type eol; qi::eoi_type eoi; qi::char_type char_; + qi::raw_type raw; + qi::omit_type omit; + qi::_pass_type _pass; qi::blank_type blank; phx::function count_chars; auto append = _val += _1; - auto pb = phx::push_back(_val, _1); + //~ auto pb = phx::push_back(_val, _1); + phx::function parse_block; start = skip(space)[flow_value] | blocks ; - blocks = +block[pb]; + flow = skip(space)[flow_value]; + scalar = skip(space)[flow_value.scalar_value]; - block = - indent[_a = _1] // indent and save the number of indents - >> first_line[append] // get the rest of the first line - >> *(blank_line | line(_a)[append]) // get the lines + //~ block_content = + //~ '-' >> scalar + //~ | scalar >> ':' + //~ ; + + blocks = +(block[parse_block(this, _val, _1, _pass)]); + + block %= + omit[indent[_a = _1]] // indent and save the number of indents + >> raw[first_line] // get the rest of the first line + >> raw[*(blank_line | line(_a))] // get the lines >> repeat(_a)[blank] // must end with exact indent as started ; @@ -85,12 +153,12 @@ namespace omd { namespace parser line = // a line is: repeat(_r1 + 1, inf)[blank] // at least current indent + 1 blanks - >> (+(char_ - endl)[append]) // one or more non-endl characters + >> (+(char_ - endl)) // one or more non-endl characters >> endl // terminated by endl ; first_line = // the first_line is: - (+(char_ - endl)[append]) // one or more non-endl characters + (+(char_ - endl)) // one or more non-endl characters >> endl // terminated by endl ;