Update JSON example to parse from a UTF-8 encoded JSON file

This is an example of using Lalr to parse UTF-8 encoded input.
This commit is contained in:
Charles Baker 2023-05-29 21:20:09 +12:00 • committed by Charles Baker
parent d03a02d3e5
commit 0dc846f6eb
3 changed files with 67 additions and 35 deletions

View file

@ -15,6 +15,9 @@ for _, cc in toolsets('^cc.*') do
libraries = libraries;
'${lib}/lalr_${platform}_${architecture}';
cc:Cxx '${obj}/%1' {
defines = {
([[LALR_EXAMPLES=\"%s/\"]]):format( pwd() );
};
"lalr_examples.cpp",
"lalr_error_handling_calculator_example.cpp",
"lalr_hello_world_example.cpp",

View file

@ -4,7 +4,16 @@
#include <lalr/Parser.ipp>
#include <lalr/PositionIterator.hpp>
#include <lalr/string_literal.hpp>
#include <fstream>
#include <string.h>
#include <locale>
#include <clocale>
#include <codecvt>
#ifdef __APPLE__
#include <stdint.h>
#else
#include <uchar.h>
#endif
using namespace std;
using namespace lalr;
@ -12,11 +21,13 @@ using namespace lalr;
namespace
{
typedef std::basic_string<char32_t> String;
struct Attribute;
struct Value
{
std::string value_;
String value_;
std::vector<shared_ptr<Attribute>> attributes_;
std::vector<shared_ptr<Value>> elements_;
@ -24,10 +35,10 @@ struct Value
: value_()
, attributes_()
, elements_()
{
{
}
Value( const std::string& value )
Value( const String& value )
: value_( value )
, attributes_()
, elements_()
@ -37,7 +48,7 @@ struct Value
struct Attribute
{
std::string name_;
String name_;
shared_ptr<Value> value_;
Attribute()
@ -46,7 +57,7 @@ struct Attribute
{
}
Attribute( const std::string& name, const shared_ptr<Value>& value )
Attribute( const String& name, const shared_ptr<Value>& value )
: name_( name )
, value_( value )
{
@ -55,7 +66,7 @@ struct Attribute
struct JsonUserData
{
std::string name_;
String name_;
shared_ptr<Value> value_;
JsonUserData()
@ -70,42 +81,42 @@ struct JsonUserData
{
}
JsonUserData( const std::string& name, shared_ptr<Value> value )
JsonUserData( const String& name, shared_ptr<Value> value )
: name_( name )
, value_( value )
{
}
};
static JsonUserData document( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData document( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
return start[1];
}
static JsonUserData attribute( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData attribute( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
const shared_ptr<Value>& attribute = start[2].value_;
return JsonUserData( nodes[0].lexeme(), attribute );
}
static JsonUserData null( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData null( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
shared_ptr<Value> null_value = make_shared<Value>();
return JsonUserData( null_value );
}
static JsonUserData value( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData value( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
shared_ptr<Value> value = make_shared<Value>( nodes[0].lexeme() );
return JsonUserData( value );
}
static JsonUserData object( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData object( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
return start[1];
}
static JsonUserData add_to_object( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData add_to_object( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
const shared_ptr<Value>& object = start[0].value_;
shared_ptr<Attribute> attribute = make_shared<Attribute>( start[2].name_, start[2].value_ );
@ -113,7 +124,7 @@ static JsonUserData add_to_object( const JsonUserData* start, const ParserNode<c
return JsonUserData( object );
}
static JsonUserData create_object( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData create_object( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
shared_ptr<Value> object = make_shared<Value>();
shared_ptr<Attribute> attribute = make_shared<Attribute>( start[0].name_, start[0].value_ );
@ -121,7 +132,7 @@ static JsonUserData create_object( const JsonUserData* start, const ParserNode<c
return JsonUserData( object );
}
static JsonUserData add_to_array( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData add_to_array( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
const shared_ptr<Value>& array = start[0].value_;
const shared_ptr<Value>& element = start[2].value_;
@ -129,7 +140,7 @@ static JsonUserData add_to_array( const JsonUserData* start, const ParserNode<ch
return JsonUserData( array );
}
static JsonUserData create_array( const JsonUserData* start, const ParserNode<char>* nodes, size_t length )
static JsonUserData create_array( const JsonUserData* start, const ParserNode<char32_t>* nodes, size_t length )
{
shared_ptr<Value> array = make_shared<Value>();
const shared_ptr<Value>& element = start[0].value_;
@ -147,20 +158,28 @@ static void indent( int level )
static void print( const Value& value, int level )
{
std::setlocale( LC_ALL, "en_US.UTF-8" );
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> utf8;
for ( const shared_ptr<Attribute>& attribute : value.attributes_ )
{
LALR_ASSERT( attribute );
const string& name = attribute->name_;
const String& name = attribute->name_;
const Value& value = *attribute->value_;
if ( value.attributes_.empty() && value.elements_.empty() )
{
indent( level + 1 );
printf( "%s='%s'\n", attribute->name_.c_str(), attribute->value_->value_.c_str() );
printf( "%s='%s'\n",
utf8.to_bytes(attribute->name_).c_str(),
utf8.to_bytes(attribute->value_->value_).c_str()
);
}
else
{
indent( level + 1 );
printf( "%s:\n", attribute->name_.c_str() );
printf( "%s:\n",
utf8.to_bytes(attribute->name_).c_str()
);
print( value, level + 1 );
}
}
@ -173,7 +192,10 @@ static void print( const Value& value, int level )
if ( value.attributes_.empty() && value.elements_.empty() )
{
indent( level + 1 );
printf( "%d: '%s'\n", index, value.value_.c_str() );
printf( "%d: '%s'\n",
index,
utf8.to_bytes(value.value_).c_str()
);
}
else
{
@ -190,8 +212,8 @@ static void print( const Value& value, int level )
void lalr_json_example()
{
extern const lalr::ParserStateMachine* json_parser_state_machine;
Parser<const char*, JsonUserData> parser( json_parser_state_machine );
parser.set_lexer_action_handler( "string", &string_literal<const char*> );
Parser<istreambuf_iterator<char32_t>, JsonUserData> parser( json_parser_state_machine );
parser.set_lexer_action_handler( "string", &string_literal<istreambuf_iterator<char32_t>> );
parser.parser_action_handlers()
( "document", &document )
( "add_to_object", &add_to_object )
@ -205,20 +227,16 @@ void lalr_json_example()
( "array", &object )
;
const char* input =
"{\n"
" \"model\": {\n"
" \"format\": \"Model\",\n"
" \"version\": 1,\n"
" \"address\": \"0017FAB0\",\n"
" \"items\": {\n"
" \"name\": \"Albert\"\n"
" },\n"
" \"more_items\": ['one', 2, 3]\n"
" }\n"
"}\n";
using std::locale;
using std::codecvt;
using std::basic_ifstream;
using std::istreambuf_iterator;
std::basic_ifstream<char32_t> file( LALR_EXAMPLES "lalr_json_example.json", std::ios_base::binary );
file.imbue( locale(file.getloc(), new codecvt<char32_t, char, std::mbstate_t>) );
istreambuf_iterator<char32_t> input( file );
istreambuf_iterator<char32_t> input_end;
parser.parse( input, input + strlen(input) );
parser.parse( input, input_end );
LALR_ASSERT( parser.accepted() );
LALR_ASSERT( parser.full() );
print( *parser.user_data().value_, 0 );

View file

@ -0,0 +1,11 @@
{
"model": {
"format": "Model",
"version": 1,
"address": "0017FAB0",
"items": {
"name": "Albert"
},
"more_items": ["one", 2, 3, "to prove that it's really UTF-8... 😁 😄!"]
}
}