#!perl
# Copyright 2014 Jeffrey Kegler
# This file is part of Marpa::R2. Marpa::R2 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.
#
# Marpa::R2 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 Marpa::R2. If not, see
# http://www.gnu.org/licenses/.
use 5.010;
use strict;
use warnings;
use English qw( -no_match_vars );
use Fatal qw(open close);
if (scalar @ARGV != 1) {
die("usage: $PROGRAM_NAME error_codes.c > marpa.h-err");
}
open my $codes_c, '>', $ARGV[0];
# In addition to be taken from the texinfo, document
# error codes are checked against this list.
# The actual numeric value is based on order in
# this list, not in the document.
# This is to allow the descriptions of the error
# codes in the list to be reordered without
# impacting the code.
#
# So that data for error codes can be kept
# memory-efficiently in an array,
# error codes are assigned numbers in sequence
# and based on their order in this list.
# For backward compatibility, new error codes
# should always be added at the end.
my @error_codes = qw(
MARPA_ERR_NONE
MARPA_ERR_AHFA_IX_NEGATIVE
MARPA_ERR_AHFA_IX_OOB
MARPA_ERR_ANDID_NEGATIVE
MARPA_ERR_ANDID_NOT_IN_OR
MARPA_ERR_ANDIX_NEGATIVE
MARPA_ERR_BAD_SEPARATOR
MARPA_ERR_BOCAGE_ITERATION_EXHAUSTED
MARPA_ERR_COUNTED_NULLABLE
MARPA_ERR_DEVELOPMENT
MARPA_ERR_DUPLICATE_AND_NODE
MARPA_ERR_DUPLICATE_RULE
MARPA_ERR_DUPLICATE_TOKEN
MARPA_ERR_YIM_COUNT
MARPA_ERR_YIM_ID_INVALID
MARPA_ERR_EVENT_IX_NEGATIVE
MARPA_ERR_EVENT_IX_OOB
MARPA_ERR_GRAMMAR_HAS_CYCLE
MARPA_ERR_INACCESSIBLE_TOKEN
MARPA_ERR_INTERNAL
MARPA_ERR_INVALID_AHFA_ID
MARPA_ERR_INVALID_AIMID
MARPA_ERR_INVALID_BOOLEAN
MARPA_ERR_INVALID_IRLID
MARPA_ERR_INVALID_NSYID
MARPA_ERR_INVALID_LOCATION
MARPA_ERR_INVALID_RULE_ID
MARPA_ERR_INVALID_START_SYMBOL
MARPA_ERR_INVALID_SYMBOL_ID
MARPA_ERR_I_AM_NOT_OK
MARPA_ERR_MAJOR_VERSION_MISMATCH
MARPA_ERR_MICRO_VERSION_MISMATCH
MARPA_ERR_MINOR_VERSION_MISMATCH
MARPA_ERR_NOOKID_NEGATIVE
MARPA_ERR_NOT_PRECOMPUTED
MARPA_ERR_NOT_TRACING_COMPLETION_LINKS
MARPA_ERR_NOT_TRACING_LEO_LINKS
MARPA_ERR_NOT_TRACING_TOKEN_LINKS
MARPA_ERR_NO_AND_NODES
MARPA_ERR_NO_EARLEY_SET_AT_LOCATION
MARPA_ERR_NO_OR_NODES
MARPA_ERR_NO_PARSE
MARPA_ERR_NO_RULES
MARPA_ERR_NO_START_SYMBOL
MARPA_ERR_NO_TOKEN_EXPECTED_HERE
MARPA_ERR_NO_TRACE_YIM
MARPA_ERR_NO_TRACE_YS
MARPA_ERR_NO_TRACE_PIM
MARPA_ERR_NO_TRACE_SRCL
MARPA_ERR_NULLING_TERMINAL
MARPA_ERR_ORDER_FROZEN
MARPA_ERR_ORID_NEGATIVE
MARPA_ERR_OR_ALREADY_ORDERED
MARPA_ERR_PARSE_EXHAUSTED
MARPA_ERR_PARSE_TOO_LONG
MARPA_ERR_PIM_IS_NOT_LIM
MARPA_ERR_POINTER_ARG_NULL
MARPA_ERR_PRECOMPUTED
MARPA_ERR_PROGRESS_REPORT_EXHAUSTED
MARPA_ERR_PROGRESS_REPORT_NOT_STARTED
MARPA_ERR_RECCE_NOT_ACCEPTING_INPUT
MARPA_ERR_RECCE_NOT_STARTED
MARPA_ERR_RECCE_STARTED
MARPA_ERR_RHS_IX_NEGATIVE
MARPA_ERR_RHS_IX_OOB
MARPA_ERR_RHS_TOO_LONG
MARPA_ERR_SEQUENCE_LHS_NOT_UNIQUE
MARPA_ERR_SOURCE_TYPE_IS_AMBIGUOUS
MARPA_ERR_SOURCE_TYPE_IS_COMPLETION
MARPA_ERR_SOURCE_TYPE_IS_LEO
MARPA_ERR_SOURCE_TYPE_IS_NONE
MARPA_ERR_SOURCE_TYPE_IS_TOKEN
MARPA_ERR_SOURCE_TYPE_IS_UNKNOWN
MARPA_ERR_START_NOT_LHS
MARPA_ERR_SYMBOL_VALUED_CONFLICT
MARPA_ERR_TERMINAL_IS_LOCKED
MARPA_ERR_TOKEN_IS_NOT_TERMINAL
MARPA_ERR_TOKEN_LENGTH_LE_ZERO
MARPA_ERR_TOKEN_TOO_LONG
MARPA_ERR_TREE_EXHAUSTED
MARPA_ERR_TREE_PAUSED
MARPA_ERR_UNEXPECTED_TOKEN_ID
MARPA_ERR_UNPRODUCTIVE_START
MARPA_ERR_VALUATOR_INACTIVE
MARPA_ERR_VALUED_IS_LOCKED
MARPA_ERR_RANK_TOO_LOW
MARPA_ERR_RANK_TOO_HIGH
MARPA_ERR_SYMBOL_IS_NULLING
MARPA_ERR_SYMBOL_IS_UNUSED
MARPA_ERR_NO_SUCH_RULE_ID
MARPA_ERR_NO_SUCH_SYMBOL_ID
MARPA_ERR_BEFORE_FIRST_TREE
MARPA_ERR_SYMBOL_IS_NOT_COMPLETION_EVENT
MARPA_ERR_SYMBOL_IS_NOT_NULLED_EVENT
MARPA_ERR_SYMBOL_IS_NOT_PREDICTION_EVENT
MARPA_ERR_RECCE_IS_INCONSISTENT
MARPA_ERR_INVALID_ASSERTION_ID
MARPA_ERR_NO_SUCH_ASSERTION_ID
MARPA_ERR_HEADERS_DO_NOT_MATCH
);
my %error_number = map { $error_codes[$_], $_ } (0 .. $#error_codes);
my @errors_seen = ();
my @error_number_matches = ();
my @errors = ();
my $current_error_number = undef;
my @error_suggested_messages = ();
LINE: while ( my $line = <STDIN> ) {
if ( defined $current_error_number ) {
my ($documented_value) =
( $line =~ /^Numeric \s* value [:] \s (\d+) [.] $/xms );
if ( defined $documented_value ) {
if ( $documented_value != $current_error_number ) {
die
"Error number mismatch $current_error_number is $documented_value in doc";
}
$error_number_matches[$current_error_number]++;
} ## end if ( defined $documented_value )
my ($message) =
( $line =~ /Suggested \s* message [:] \s " ([^"]*) " /xms );
if ($message) {
$error_suggested_messages[$current_error_number] = $message;
$current_error_number = undef;
}
} ## end if ( defined $current_error_number )
if ( $line =~ /[@]deftypevr/xms ) {
my ($error) = ($line =~ m/(MARPA_ERR_.*)\b/xms);
if ($error) {
my $error_number = $error_number{$error};
die("$error not in list in $PROGRAM_NAME") if not defined $error_number;
$current_error_number = $error_number;
$errors_seen[$error_number] = 1;
$errors[$current_error_number] = $error;
}
}
} ## end while ( my $line = <STDIN> )
my @errors_not_seen = grep { !$errors_seen[$_] } (0 .. $#error_codes);
if (@errors_not_seen) {
for my $error_not_seen (@errors_not_seen) {
say STDERR "Error not in document: ", $error_codes[$error_not_seen];
}
die 'Error(s) in list, but not in document';
}
my $error_code_issues = 0;
ERROR_CODE: for my $error_code ( 0 .. $#error_codes ) {
my $matches = $error_number_matches[$error_code] // 0;
next ERROR_CODE if $matches == 1;
say STDERR
"Problem: Error number $error_code has $matches errors associated with it";
$error_code_issues++;
} ## end ERROR_CODE: for my $error_code ( 0 .. $#error_codes )
die 'Error(s) in list, but no number in document' if $error_code_issues;
my $error_count = scalar @errors;
say "#define MARPA_ERROR_COUNT $error_count";
for ( my $error_number = 0; $error_number < $error_count; $error_number++ ) {
say '#define '
. $errors[$error_number] . q{ }
. $error_number;
}
say {$codes_c} 'const struct marpa_error_description_s marpa_error_description[] = {';
for ( my $error_number = 0; $error_number < $error_count; $error_number++ ) {
my $error_name = $errors[$error_number];
my $suggested_description = $error_suggested_messages[$error_number]
// $error_name;
say {$codes_c}
qq[ { $error_number, "$error_name", "$suggested_description" },];
} ## end for ( my $error_number = 0; $error_number < $error_count...)
say {$codes_c} '};';
# vim: expandtab shiftwidth=4: