Skip to content

Commit

Permalink
Improve position handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
ColinH committed Feb 1, 2018
1 parent 5d7b2b2 commit 26088b0
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 39 deletions.
78 changes: 78 additions & 0 deletions include/tao/json/contrib/position.hpp
@@ -0,0 +1,78 @@
// Copyright (c) 2018 Dr. Colin Hirsch and Daniel Frey
// Please see LICENSE for license or visit https://github.com/taocpp/json/

#ifndef TAOCPP_JSON_INCLUDE_CONTRIB_POSITION_HPP
#define TAOCPP_JSON_INCLUDE_CONTRIB_POSITION_HPP

#include <tao/json/events/to_value.hpp>
#include <tao/json/events/transformer.hpp>
#include <tao/json/parse_file.hpp>
#include <tao/json/value.hpp>

namespace tao
{
namespace json
{
struct position
{
std::size_t line;
std::size_t byte_in_line;
std::string source;
};

inline std::ostream& operator<< ( std::ostream& o, const position& p )
{
o << p.source << ':' << p.line << ':' << p.byte_in_line;
return o;
}

inline std::string to_string( const position& p )
{
std::ostringstream o;
o << p;
return o.str();
}

namespace internal
{
template< typename Rule >
struct position_action
: public action< Rule >
{
};

template<>
struct position_action< rules::sor_value >
{
template< typename Input, typename Consumer >
static void apply( const Input& in, Consumer& consumer )
{
const auto p = in.position();
consumer.value.base().line = p.line;
consumer.value.base().byte_in_line = p.byte_in_line;
consumer.value.base().source = p.source;
}
};

} // namespace internal

template< template< typename... > class Traits, template< typename... > class... Transformers >
basic_value< Traits, position > basic_parse_file_with_position( const std::string& filename )
{
events::transformer< events::to_basic_value< Traits, position >, Transformers... > consumer;
json_pegtl::file_input< json_pegtl::tracking_mode::IMMEDIATE > in( filename );
json_pegtl::parse< internal::grammar, internal::position_action, internal::control >( in, consumer );
return std::move( consumer.value );
}

template< template< typename... > class... Transformers >
basic_value< traits, position > parse_file_with_position( const std::string& filename )
{
return basic_parse_file_with_position< traits, Transformers... >( filename );
}

} // namespace json

} // namespace tao

#endif
64 changes: 25 additions & 39 deletions src/test/json/position.cpp
Expand Up @@ -3,60 +3,46 @@

#include "test.hpp"

#include <tao/json/from_string.hpp>
#include <tao/json/parse_file.hpp>
#include <tao/json/value.hpp>
#include <tao/json/contrib/position.hpp>

namespace tao
{
namespace json
{
namespace position
void test_json()
{
struct position_base
{
tao::optional< json_pegtl::position > position;
};
const std::string f = "tests/taocpp/position.json";

// TODO: We can still template over the traits.
using value = basic_value< traits, position_base >;
auto v = parse_file_with_position( f );

namespace internal
{
template< typename Rule >
struct action
: public json::internal::action< Rule >
{
};
TEST_ASSERT( v.base().source == f );
TEST_ASSERT( v.base().line == 1 );
TEST_ASSERT( v.base().byte_in_line == 0 );

template<>
struct action< json::internal::rules::value >
{
template< typename Input, typename Consumer >
static void apply( const Input& in, Consumer& consumer )
{
consumer.value.base().position = in.position();
}
};
TEST_ASSERT( v.at( 0 ).base().source == f );
TEST_ASSERT( v.at( 0 ).base().line == 2 );
TEST_ASSERT( v.at( 0 ).base().byte_in_line == 8 );

} // namespace internal
TEST_ASSERT( v.at( 1 ).base().source == f );
TEST_ASSERT( v.at( 1 ).base().line == 3 );
TEST_ASSERT( v.at( 1 ).base().byte_in_line == 8 );

value parse_file( const std::string& filename )
{
events::to_basic_value< traits, position_base > consumer;
json_pegtl::file_input< json_pegtl::tracking_mode::IMMEDIATE > in( filename );
json_pegtl::parse< json::internal::grammar, internal::action, json::internal::control >( in, consumer );
return std::move( consumer.value );
}
TEST_ASSERT( v.at( 2 ).base().source == f );
TEST_ASSERT( v.at( 2 ).base().line == 4 );
TEST_ASSERT( v.at( 2 ).base().byte_in_line == 8 );

} // namespace position
TEST_ASSERT( v.at( 3 ).base().source == f );
TEST_ASSERT( v.at( 3 ).base().line == 5 );
TEST_ASSERT( v.at( 3 ).base().byte_in_line == 8 );

TEST_ASSERT( v.at( 3 ).at( "hello" ).base().source == f );
TEST_ASSERT( v.at( 3 ).at( "hello" ).base().line == 6 );
TEST_ASSERT( v.at( 3 ).at( "hello" ).base().byte_in_line == 26 );
}

void unit_test()
{
auto v = position::parse_file( "tests/draft4/additionalItems.json" );
// std::cerr << *v[ 1 ][ "description" ].base().position << std::endl;
TEST_ASSERT( v[ 1 ][ "description" ].base().position->line == 22 );
TEST_ASSERT( v[ 1 ][ "description" ].base().position->byte_in_line == 23 );
test_json();
}

} // namespace json
Expand Down
8 changes: 8 additions & 0 deletions tests/taocpp/position.json
@@ -0,0 +1,8 @@
[
11,
null,
33.491938,
{
"hello" : "world"
}
]

0 comments on commit 26088b0

Please sign in to comment.