#!perl
# Copyright 2022 Axel Zuber
# This file is part of MarpaX::G4.  MarpaX::G4 is free software: you can
# redistribute it and/or modify it under the terms of the GNU Lesser
# General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
#
# MarpaX::G4 is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser
# General Public License along with MarpaX::G4.  If not, see
# http://www.gnu.org/licenses/.

use warnings;
use strict;

use File::Temp;
use Test::More tests => 2;

my $EVAL_ERROR;

if (not eval { require MarpaX::G4; 1; })
{
    Test::More::diag($EVAL_ERROR);
    Test::More::BAIL_OUT('Could not load MarpaX::G4');
}

my $marpa_version_ok = defined $MarpaX::G4::VERSION;
my $marpa_version_desc =
    $marpa_version_ok
        ? 'MarpaX::G4 version is ' . $MarpaX::G4::VERSION
        : 'No MarpaX::G4::VERSION';
Test::More::ok( $marpa_version_ok, $marpa_version_desc );

my $grammartext =<<'INPUT';
grammar JSON;
json                   : value;
obj                    : '{' pair (',' pair)* '}'
                       | '{' '}' ;
pair                   : STRING ':' value;
arr                    : '[' value (',' value)* ']'
                       | '[' ']';
value                  : STRING
                       | NUMBER
                       | obj
                       | arr
                       | 'true'
                       | 'false'
                       | 'null';
lexer grammar JSON;
STRING                 : '"' (ESC | SAFECODEPOINT)* '"';
NUMBER                 : '-'? INT ('.' [0-9] +)? EXP?;
fragment ESC           : '\\' (["\\/bfnrt] | UNICODE);
fragment UNICODE       : 'u' HEX HEX HEX HEX;
fragment HEX           : [0-9a-fA-F];
fragment SAFECODEPOINT : ~ ["\\\u0000-\u001F];
fragment INT           : '0' | [1-9] [0-9]*;
fragment EXP           : [Ee] [+\-]? INT;
WS                     : [ \t\n\r] + -> skip;
INPUT

my $tmp = File::Temp->new();

my $translator = MarpaX::G4->new();
$translator->translatestring( $grammartext, { f => 1, k => 1, u => 1, o => $tmp->filename } );

my $actual_output = do { local $/; <$tmp> };

my $expected_output =<< 'EXPECTED_OUTPUT';
lexeme default = latm => 1

:start         ::= json

# ---
# Discard rule from redirect options :
:discard       ~   <discarded redirects>
<discarded redirects> ~   WS
# ---
json           ::= value

obj            ::= '{' pair obj_002 '}'
               |   '{' '}'
obj_001        ::= ',' pair
obj_002        ::= obj_001*

pair           ::= STRING ':' value

arr            ::= '[' value arr_002 ']'
               |   '[' ']'
arr_001        ::= ',' value
arr_002        ::= arr_001*

value          ::= STRING
               |   NUMBER
               |   obj
               |   arr
               |   'true':i
               |   'false':i
               |   'null':i

STRING         ~   '"' STRING_002 '"'
STRING_001     ~   ESC
               |   SAFECODEPOINT
STRING_002     ~   STRING_001*

NUMBER         ~   opt_NUMBER_001 INT opt_NUMBER_004 opt_NUMBER_005
opt_NUMBER_001 ~
opt_NUMBER_001 ~   '-'
NUMBER_002     ~   [0-9]+
NUMBER_003     ~   '.' NUMBER_002
opt_NUMBER_004 ~
opt_NUMBER_004 ~   NUMBER_003
opt_NUMBER_005 ~
opt_NUMBER_005 ~   EXP

ESC            ~   ESC_002
ESC_001        ~   [\\/bfnrt]:ic
               |   UNICODE
ESC_002        ~   '\\' ESC_001

UNICODE        ~   UNICODE_001
UNICODE_001    ~   'u':i HEX HEX HEX HEX

HEX            ~   [0-9a-f]:ic
SAFECODEPOINT  ~   [^"\\\u0000-\u001F]

INT            ~   INT_002
INT_001        ~   [0-9]*
INT_002        ~   '0'
               |   [1-9] INT_001

EXP            ~   EXP_002
opt_EXP_001    ~
opt_EXP_001    ~   [+\-]
EXP_002        ~   [E]:ic opt_EXP_001 INT

WS             ~   [ \t\n\r]+
EXPECTED_OUTPUT

sub canonical_text
{
    my ($string) = @_;
    $string =~ s/[\r\n]+$//g;
    $string =~ s/[\s]+/ /g;
    return $string;
}

$actual_output   = canonical_text($actual_output);
$expected_output = canonical_text($expected_output);

Test::More::ok( $actual_output eq $expected_output, "\n===\n=== expected Marpa::R2 json grammar\n===\n${expected_output}\n===\n=== does not match actual output\n===\n${actual_output}\n===\n" );

# vim: expandtab shiftwidth=4:
