25 #ifndef WSTRUCTUREDTEXTPARSER_H
26 #define WSTRUCTUREDTEXTPARSER_H
38 #include <boost/config/warning_disable.hpp>
39 #include <boost/spirit/include/qi.hpp>
40 #include <boost/spirit/include/phoenix_core.hpp>
41 #include <boost/spirit/include/phoenix_operator.hpp>
42 #include <boost/spirit/include/phoenix_fusion.hpp>
43 #include <boost/spirit/include/phoenix_stl.hpp>
44 #include <boost/spirit/include/phoenix_object.hpp>
45 #include <boost/fusion/include/adapt_struct.hpp>
46 #include <boost/fusion/include/io.hpp>
47 #include <boost/variant/recursive_variant.hpp>
50 #include <boost/filesystem/path.hpp>
52 #include "WStringUtils.h"
53 #include "exceptions/WTypeMismatch.h"
54 #include "exceptions/WNotFound.h"
63 namespace qi = boost::spirit::qi;
66 namespace fusion = boost::fusion;
69 namespace ascii = boost::spirit::ascii;
72 namespace phoenix = boost::phoenix;
75 namespace spirit = boost::spirit;
117 boost::recursive_wrapper< ObjectType >,
149 BOOST_FUSION_ADAPT_STRUCT(
151 ( std::string, m_name )
152 ( std::vector< WStructuredTextParser::MemberType >, m_nodes )
158 BOOST_FUSION_ADAPT_STRUCT(
160 ( std::string, m_name )
161 ( std::string, m_value )
180 template <
typename Iterator>
181 struct Grammar: qi::grammar<Iterator, FileType(), ascii::space_type >
188 explicit Grammar( std::ostream& error ): Grammar::base_type( file,
"WStructuredTextParser::Grammar" )
191 key %= qi::char_(
"a-zA-Z_" ) >> *qi::char_(
"a-zA-Z_0-9" );
193 value %=
'"' >> *( ~qi::char_(
"\"" ) | qi::char_(
" " ) ) >>
'"';
196 kvpair %= key >>
'=' >> value >>
';';
198 comment %= qi::lexeme[ qi::char_(
"/" ) >> qi::char_(
"/" ) >> *qi::char_(
"a-zA-Z_0-9!\"#$%&'()*,:;<>?@\\^`{|}~/ .@=[]ยง!+-" ) ];
200 object %= ( key | value ) >>
'{' >> *(
object | kvpair | comment ) >>
'}' >> *qi::char_(
";" );
202 file %= *(
object | kvpair | comment );
205 object.name(
"object" );
206 kvpair.name(
"key-value pair" );
208 value.name(
"value" );
210 comment.name(
"comment" );
214 qi::on_error< qi::fail >(
object, error << phoenix::val(
"Error: " ) << qi::_4 );
215 qi::on_error< qi::fail >( kvpair, error << phoenix::val(
"Error: " ) << qi::_4 );
216 qi::on_error< qi::fail >( key, error << phoenix::val(
"Error: " ) << qi::_4 );
217 qi::on_error< qi::fail >( value, error << phoenix::val(
"Error: " ) << qi::_4 );
218 qi::on_error< qi::fail >( comment, error << phoenix::val(
"Error: " ) << qi::_4 );
219 qi::on_error< qi::fail >( file, error << phoenix::val(
"Error: " ) << qi::_4 );
227 qi::rule< Iterator, ObjectType(), ascii::space_type > object;
232 qi::rule< Iterator,
FileType(), ascii::space_type > file;
237 qi::rule< Iterator,
CommentType(), ascii::space_type > comment;
242 qi::rule< Iterator, KeyValueType(), ascii::space_type > kvpair;
247 qi::rule< Iterator,
KeyType() > key;
269 class StructuredValueTree
276 static const std::string Separator;
283 explicit StructuredValueTree(
const FileType& file );
290 explicit StructuredValueTree(
const std::string& toParse );
297 explicit StructuredValueTree(
const boost::filesystem::path& file );
302 StructuredValueTree();
307 virtual ~StructuredValueTree();
319 bool exists( std::string key,
bool valuesOnly =
false )
const;
329 size_t count( std::string key,
bool valuesOnly =
false )
const;
344 template<
typename T >
345 T getValue( std::string key,
const T& defaultValue )
const;
360 template<
typename T >
361 std::vector< T > getValues( std::string key,
const std::vector< T >& defaults )
const;
375 template<
typename T >
376 std::vector< T > getValues( std::string key )
const;
389 template<
typename T >
390 T operator[]( std::string key )
const;
401 StructuredValueTree getSubTree( std::string key )
const;
412 std::vector< StructuredValueTree > getSubTrees( std::string key )
const;
431 void traverse(
MemberType current, std::vector< std::string >::const_iterator keyIter,
432 std::vector< std::string >::const_iterator keyEnd,
433 std::vector< ObjectType >& resultObjects,
434 std::vector< KeyValueType >& resultValues )
const;
445 void traverse(
FileType current, std::string key,
446 std::vector< ObjectType >& resultObjects,
447 std::vector< KeyValueType >& resultValues )
const;
459 FileType parseFromString( std::string input );
471 FileType parseFromFile( boost::filesystem::path path );
473 template<
typename T >
474 T StructuredValueTree::getValue( std::string key,
const T& defaultValue )
const
477 return *getValues< T >( key, std::vector< T >( 1, defaultValue ) ).begin();
480 template<
typename T >
481 std::vector< T > StructuredValueTree::getValues( std::string key,
const std::vector< T >& defaults )
const
483 std::vector< T > r = getValues< T >( key );
494 template<
typename T >
495 T StructuredValueTree::operator[]( std::string key )
const
497 std::vector< T > r = getValues< T >( key );
504 throw WNotFound(
"The key \"" + key +
"\" was not found." );
511 class IsLeafVisitor:
public boost::static_visitor< bool >
519 bool operator()(
const KeyValueType& )
const
530 template<
typename T >
531 bool operator()(
const T& )
const
540 class IsCommentVisitor:
public boost::static_visitor< bool >
559 template<
typename T >
560 bool operator()(
const T& )
const
569 class NameQueryVisitor:
public boost::static_visitor< std::string >
590 template<
typename T >
591 std::string operator()(
const T& element )
const
593 return element.m_name;
597 template<
typename T >
598 std::vector< T > StructuredValueTree::getValues( std::string key )
const
601 std::vector< ObjectType > rObj;
602 std::vector< KeyValueType > rKV;
605 traverse( m_file, key, rObj, rKV );
609 for( std::vector< KeyValueType >::const_iterator i = rKV.begin(); i != rKV.end(); ++i )
613 r.push_back( string_utils::fromString< T >( ( *i ).m_value ) );
618 throw WTypeMismatch(
"Cannot convert element \"" + key +
"\" to desired type." );
Indicates invalid value which could not be found.
Test parsing and query functionality.
Indicates invalid type of something.
This namespace contains the WStructuredTextParser data types and the parser.
std::vector< MemberType > FileType
An object representing all objects and comments on file level.
std::string ValueType
The type used for values.
std::string KeyType
we use these quite often, so define some short alias for them:
std::string CommentType
The type used for comments.
boost::variant< boost::recursive_wrapper< ObjectType >, KeyValueType, CommentType > MemberType
A node inside the AST is either another object or a key-value pair.
KeyValueType - a tuple containing name and value.
std::string m_value
Value string.
std::string m_name
Name string.
An object is always a name and contains several further nodes.
std::string m_name
Name of the object.
std::vector< MemberType > m_nodes
Object's members.