mirror of
https://github.com/boostorg/parser.git
synced 2026-01-19 04:22:13 +00:00
Json basic test passing
This commit is contained in:
100
test/json_test.cpp
Normal file
100
test/json_test.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (C) 2010, 2011 Object Modeling Designs
|
||||
*/
|
||||
|
||||
#include "../yaml/parser/flow_def.hpp"
|
||||
#include "../yaml/parser/scalar_def.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/spirit/include/support_istream_iterator.hpp>
|
||||
#include <boost/spirit/include/support_line_pos_iterator.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename Char>
|
||||
bool parse(
|
||||
std::basic_istream<Char>& is,
|
||||
omd::ast::value_t& result,
|
||||
std::string const& source_file = "")
|
||||
{
|
||||
// no white space skipping in the stream!
|
||||
is.unsetf(std::ios::skipws);
|
||||
|
||||
typedef
|
||||
boost::spirit::basic_istream_iterator<Char>
|
||||
stream_iterator_type;
|
||||
stream_iterator_type sfirst(is);
|
||||
stream_iterator_type slast;
|
||||
|
||||
typedef boost::spirit::line_pos_iterator<stream_iterator_type>
|
||||
iterator_type;
|
||||
iterator_type first(sfirst);
|
||||
iterator_type last(slast);
|
||||
|
||||
omd::parser::flow<iterator_type> p(source_file);
|
||||
omd::parser::white_space<iterator_type> ws;
|
||||
|
||||
using boost::spirit::qi::phrase_parse;
|
||||
return phrase_parse(first, last, p, ws, result);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Main program
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char const* filename = NULL;
|
||||
if (argc > 1)
|
||||
{
|
||||
filename = argv[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Error: No input file provided." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::ifstream in(filename, std::ios_base::in);
|
||||
|
||||
if (!in)
|
||||
{
|
||||
std::cerr << "Error: Could not open input file: "
|
||||
<< filename << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ignore the BOM marking the beginning of a UTF-8 file in Windows
|
||||
char c = in.peek();
|
||||
if (c == '\xef')
|
||||
{
|
||||
char s[3];
|
||||
in >> s[0] >> s[1] >> s[2];
|
||||
s[3] = '\0';
|
||||
if (s != std::string("\xef\xbb\xbf"))
|
||||
{
|
||||
std::cerr << "Error: Unexpected characters from input file: "
|
||||
<< filename << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
using omd::ast::value_t;
|
||||
namespace qi = boost::spirit::qi;
|
||||
|
||||
value_t result;
|
||||
if (parse(in, result, filename))
|
||||
{
|
||||
std::cout << "success: ";
|
||||
//~ println(std::cout, result);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "parse error" << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
#include "../yaml/parser/scalar_def.hpp"
|
||||
/**
|
||||
* Copyright (C) 2010, 2011 Object Modeling Designs
|
||||
*/
|
||||
|
||||
#include "../yaml/parser/scalar_def.hpp"
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
|
||||
namespace
|
||||
|
||||
14
test/test_files/basic_json_test.json
Normal file
14
test/test_files/basic_json_test.json
Normal file
@@ -0,0 +1,14 @@
|
||||
[
|
||||
123.45,
|
||||
true,
|
||||
false,
|
||||
0xFF,
|
||||
077,
|
||||
"this is a unicode \u20AC string",
|
||||
"Τη γλώσσα μου έδωσαν ελληνική",
|
||||
12345,
|
||||
[
|
||||
92,
|
||||
["another string", "apple", "Sîne"]
|
||||
]
|
||||
]
|
||||
26
yaml/ast.hpp
26
yaml/ast.hpp
@@ -3,8 +3,8 @@
|
||||
* consultomd.com
|
||||
*
|
||||
*/
|
||||
#ifndef OMD_JSON_VALUE_HPP
|
||||
#define OMD_JSON_VALUE_HPP
|
||||
#ifndef OMD_AST_VALUE_HPP
|
||||
#define OMD_AST_VALUE_HPP
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
@@ -20,14 +20,14 @@ namespace omd { namespace ast
|
||||
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; }
|
||||
};
|
||||
{};
|
||||
|
||||
// nulls always compare
|
||||
inline bool operator==(null_t a, null_t b) { return true; }
|
||||
inline bool operator!=(null_t a, null_t b) { return false; }
|
||||
|
||||
struct value_t;
|
||||
typedef std::map<std::string, value_t> object_t;
|
||||
typedef std::map<value_t, value_t> object_t;
|
||||
typedef std::vector<value_t> array_t;
|
||||
|
||||
struct value_t
|
||||
@@ -37,7 +37,8 @@ namespace omd { namespace ast
|
||||
string_t,
|
||||
double_t,
|
||||
int_t,
|
||||
object_t
|
||||
object_t,
|
||||
array_t
|
||||
>
|
||||
{
|
||||
value_t(string_t const& val) : base_type(val) {}
|
||||
@@ -45,12 +46,19 @@ namespace omd { namespace ast
|
||||
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(object_t const& val) : base_type(val) {}
|
||||
value_t(array_t const& val) : base_type(val) {}
|
||||
|
||||
value_t(value_t const& rhs)
|
||||
: base_type(rhs.get()) {}
|
||||
};
|
||||
|
||||
bool operator==(value_t const& a, value_t const& b);
|
||||
bool operator!=(value_t const& a, value_t const& b);
|
||||
bool operator<(value_t const& a, value_t const& b);
|
||||
|
||||
// ---------------------------------------------------
|
||||
}}
|
||||
|
||||
#include "detail/ast_impl.hpp"
|
||||
#endif
|
||||
|
||||
108
yaml/detail/ast_impl.hpp
Normal file
108
yaml/detail/ast_impl.hpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright (C) 2010, 2011 Michael Caisse, Object Modeling Designs
|
||||
* consultomd.com
|
||||
*
|
||||
*/
|
||||
#ifndef OMD_AST_VALUE_IMPL_HPP
|
||||
#define OMD_AST_VALUE_IMPL_HPP
|
||||
|
||||
#include "../ast.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace omd { namespace ast
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct value_equal
|
||||
{
|
||||
typedef bool result_type;
|
||||
|
||||
template <typename A, typename B>
|
||||
bool operator()(A const& a, B const& b) const
|
||||
{
|
||||
BOOST_ASSERT(false); // this should not happen. We cannot compare different types
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator()(T const& a, T const& b) const
|
||||
{
|
||||
return a == b;
|
||||
}
|
||||
|
||||
bool operator()(object_t const& a, object_t const& b)
|
||||
{
|
||||
if (a.size() != b.size())
|
||||
return false;
|
||||
object_t::const_iterator ii = b.begin();
|
||||
for (object_t::const_iterator i = a.begin(); i != a.end(); ++i)
|
||||
{
|
||||
if (*i != *ii++)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(array_t const& a, array_t const& b)
|
||||
{
|
||||
if (a.size() != b.size())
|
||||
return false;
|
||||
array_t::const_iterator ii = b.begin();
|
||||
for (array_t::const_iterator i = a.begin(); i != a.end(); ++i)
|
||||
{
|
||||
if (*i != *ii++)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline bool operator==(value_t const& a, value_t const& b)
|
||||
{
|
||||
return boost::apply_visitor(detail::value_equal(), a.get(), b.get());
|
||||
}
|
||||
|
||||
inline bool operator!=(value_t const& a, value_t const& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct value_compare
|
||||
{
|
||||
typedef bool result_type;
|
||||
|
||||
template <typename A, typename B>
|
||||
bool operator()(A const& a, B const& b) const
|
||||
{
|
||||
BOOST_ASSERT(false); // this should not happen. We cannot compare different types
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator()(T const& a, T const& b) const
|
||||
{
|
||||
return a < b;
|
||||
}
|
||||
|
||||
bool operator()(object_t const& a, object_t const& b)
|
||||
{
|
||||
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
|
||||
}
|
||||
|
||||
bool operator()(array_t const& a, array_t const& b)
|
||||
{
|
||||
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline bool operator<(value_t const& a, value_t const& b)
|
||||
{
|
||||
return boost::apply_visitor(detail::value_compare(), a.get(), b.get());
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
56
yaml/parser/error_handler.hpp
Normal file
56
yaml/parser/error_handler.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (C) 2010, 2011 Object Modeling Designs
|
||||
* Copyright (c) 2010 Joel de Guzman
|
||||
*/
|
||||
|
||||
#if !defined(OMD_COMMON_ERROR_HANDLER_HPP)
|
||||
#define OMD_COMMON_ERROR_HANDLER_HPP
|
||||
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/support_line_pos_iterator.hpp>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
namespace omd { namespace parser
|
||||
{
|
||||
template <typename Iterator>
|
||||
struct error_handler
|
||||
{
|
||||
template <typename, typename, typename, typename>
|
||||
struct result { typedef void type; };
|
||||
|
||||
std::string source_file;
|
||||
error_handler(std::string const& source_file = "")
|
||||
: source_file(source_file) {}
|
||||
|
||||
void operator()(
|
||||
Iterator first, Iterator last,
|
||||
Iterator err_pos, boost::spirit::info const& what) const
|
||||
{
|
||||
Iterator eol = err_pos;
|
||||
int line = boost::spirit::get_line(err_pos);
|
||||
|
||||
if (source_file != "")
|
||||
std::cerr << source_file;
|
||||
|
||||
if (line != -1)
|
||||
std::cerr << '(' << line << ')';
|
||||
|
||||
std::cerr << " : Error! Expecting " << what;
|
||||
|
||||
std::cerr << " got:\"";
|
||||
for (Iterator i = err_pos; i != last; ++i)
|
||||
{
|
||||
Iterator::value_type c = *i;
|
||||
if (c == '\r' || c == '\n')
|
||||
break;
|
||||
std::cerr << c;
|
||||
}
|
||||
|
||||
std::cerr << "\"" << std::endl;
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
||||
41
yaml/parser/flow.hpp
Normal file
41
yaml/parser/flow.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (C) 2010, 2011 Object Modeling Designs
|
||||
*/
|
||||
|
||||
#if !defined(OMD_PARSER_FLOW_HPP)
|
||||
#define OMD_PARSER_FLOW_HPP
|
||||
|
||||
#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
|
||||
|
||||
#include <string>
|
||||
#include "scalar.hpp"
|
||||
|
||||
namespace omd { namespace parser
|
||||
{
|
||||
template <typename Iterator>
|
||||
struct white_space : qi::grammar<Iterator>
|
||||
{
|
||||
white_space();
|
||||
qi::rule<Iterator> start;
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
struct flow : qi::grammar<Iterator, ast::value_t(), white_space<Iterator> >
|
||||
{
|
||||
flow(std::string const& source_file = "");
|
||||
|
||||
typedef std::pair<ast::value_t, ast::value_t> element_t;
|
||||
typedef white_space<Iterator> white_space;
|
||||
|
||||
qi::rule<Iterator, ast::value_t(), white_space> value;
|
||||
qi::rule<Iterator, ast::object_t(), white_space> object;
|
||||
qi::rule< Iterator, element_t(), white_space > member_pair;
|
||||
qi::rule<Iterator, ast::array_t(), white_space> array;
|
||||
scalar<Iterator> scalar_value;
|
||||
|
||||
typedef omd::parser::error_handler<Iterator> error_handler_t;
|
||||
boost::phoenix::function<error_handler_t> const error_handler;
|
||||
};
|
||||
}}
|
||||
|
||||
#endif
|
||||
73
yaml/parser/flow_def.hpp
Normal file
73
yaml/parser/flow_def.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (C) 2010, 2011 Object Modeling Designs
|
||||
*/
|
||||
|
||||
#if !defined(OMD_PARSER_FLOW_DEF_HPP)
|
||||
#define OMD_PARSER_FLOW_DEF_HPP
|
||||
|
||||
#include "flow.hpp"
|
||||
|
||||
#include <boost/fusion/adapted/std_pair.hpp>
|
||||
|
||||
namespace omd { namespace parser
|
||||
{
|
||||
template <typename Iterator>
|
||||
white_space<Iterator>::white_space()
|
||||
: white_space::base_type(start)
|
||||
{
|
||||
qi::char_type char_;
|
||||
qi::eol_type eol;
|
||||
qi::space_type space;
|
||||
|
||||
start =
|
||||
space // tab/space/cr/lf
|
||||
| '#' >> *(char_ - eol) >> eol // comments
|
||||
;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
flow<Iterator>::flow(std::string const& source_file)
|
||||
: flow::base_type(value),
|
||||
scalar_value(source_file),
|
||||
error_handler(error_handler_t(source_file))
|
||||
{
|
||||
value =
|
||||
scalar_value
|
||||
| object
|
||||
| array
|
||||
;
|
||||
|
||||
object =
|
||||
'{'
|
||||
> -(member_pair % ',')
|
||||
> '}'
|
||||
;
|
||||
|
||||
member_pair =
|
||||
scalar_value
|
||||
>> ':'
|
||||
>> value
|
||||
;
|
||||
|
||||
array =
|
||||
'['
|
||||
> -(value % ',')
|
||||
> ']'
|
||||
;
|
||||
|
||||
BOOST_SPIRIT_DEBUG_NODES(
|
||||
(value)
|
||||
(object)
|
||||
(member_pair)
|
||||
(array)
|
||||
);
|
||||
|
||||
qi::_1_type _1;
|
||||
qi::_2_type _2;
|
||||
qi::_3_type _3;
|
||||
qi::_4_type _4;
|
||||
qi::on_error<qi::fail>(value, error_handler(_1, _2, _3, _4));
|
||||
}
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -1,16 +1,20 @@
|
||||
/**
|
||||
* Copyright (C) 2010, 2011 Object Modeling Designs
|
||||
* Copyright (c) 2010 Joel de Guzman
|
||||
*/
|
||||
|
||||
#if !defined(OMD_PARSER_STRING)
|
||||
#define OMD_PARSER_STRING
|
||||
#if !defined(OMD_PARSER_SCALAR_HPP)
|
||||
#define OMD_PARSER_SCALAR_HPP
|
||||
|
||||
#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include "../ast.hpp" // our AST
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
|
||||
#include "../ast.hpp" // our AST
|
||||
#include "error_handler.hpp" // Our Error Handler
|
||||
|
||||
namespace omd { namespace parser
|
||||
{
|
||||
@@ -32,13 +36,16 @@ namespace omd { namespace parser
|
||||
template <typename Iterator>
|
||||
struct scalar : qi::grammar<Iterator, ast::value_t()>
|
||||
{
|
||||
scalar();
|
||||
scalar(std::string const& source_file = "");
|
||||
|
||||
qi::rule<Iterator, ast::value_t()> value;
|
||||
unicode_string<Iterator> string_value;
|
||||
qi::rule<Iterator, int()> integer_value;
|
||||
qi::symbols<char, bool> bool_value;
|
||||
qi::rule<Iterator, ast::null_t() > null_value;
|
||||
|
||||
typedef omd::parser::error_handler<Iterator> error_handler_t;
|
||||
boost::phoenix::function<error_handler_t> const error_handler;
|
||||
};
|
||||
}}
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
/**
|
||||
* Copyright (C) 2010, 2011 Object Modeling Designs
|
||||
* Copyright (c) 2010 Joel de Guzman
|
||||
*/
|
||||
|
||||
#if !defined(OMD_COMMON_STRING_DEF)
|
||||
#define OMD_COMMON_STRING_DEF
|
||||
#if !defined(OMD_COMMON_SCALAR_DEF_HPP)
|
||||
#define OMD_COMMON_SCALAR_DEF_HPP
|
||||
|
||||
#include "scalar.hpp"
|
||||
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
@@ -99,12 +101,12 @@ namespace omd { namespace parser
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
scalar<Iterator>::scalar()
|
||||
: scalar::base_type(value)
|
||||
scalar<Iterator>::scalar(std::string const& source_file)
|
||||
: scalar::base_type(value),
|
||||
error_handler(error_handler_t(source_file))
|
||||
{
|
||||
qi::_val_type _val;
|
||||
qi::lit_type lit;
|
||||
qi::lexeme_type lexeme;
|
||||
qi::char_type char_;
|
||||
qi::hex_type hex;
|
||||
qi::oct_type oct;
|
||||
@@ -123,8 +125,8 @@ namespace omd { namespace parser
|
||||
;
|
||||
|
||||
integer_value =
|
||||
lexeme[no_case["0x"] > hex]
|
||||
| lexeme['0' >> oct]
|
||||
no_case["0x"] > hex
|
||||
| '0' >> oct
|
||||
| int_
|
||||
;
|
||||
|
||||
@@ -148,6 +150,12 @@ namespace omd { namespace parser
|
||||
(bool_value)
|
||||
(null_value)
|
||||
);
|
||||
|
||||
qi::_1_type _1;
|
||||
qi::_2_type _2;
|
||||
qi::_3_type _3;
|
||||
qi::_4_type _4;
|
||||
qi::on_error<qi::fail>(value, error_handler(_1, _2, _3, _4));
|
||||
}
|
||||
}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user