/* #undef MARPAESLIF_NTRACE */
/* For stack manipulation debug: */
/* #define MARPAESLIF_NOTICE_ACTION */
/* For inlined qsort */
#define MARPAESLIF_INLINED_QSORT

/* Hotests of the hotests functions is the one that takes care of memory/stack: */
/* _marpaESLIFRecognizer_internalStack_i_setb()                                 */
/* When possible, we want to avoid jumps on freeing memory:                     */
/* _marpaESLIFRecognizer_valueResultFreev()                                     */
/*                                                                              */
/* We put the flatten gcc attribute on them.                                    */

#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <locale.h>
#include <limits.h>
#include <stddef.h>
#include "marpaESLIF/internal/config.h"
#include "marpaESLIF/internal/math.h"
#include "marpaESLIF/internal/structures.h"
#include "marpaESLIF/internal/logging.h"
#include "marpaESLIF/internal/bootstrap.h"
#include "marpaESLIF/internal/lua.h"
#include "marpaESLIF/internal/json.h"
#ifdef MARPAESLIF_INLINED_QSORT
#include "marpaESLIF/internal/iqsort.h"
#endif

/* For qsort we maintain two different callbacks: CMP for classic qsort(), ISLT for QSORT(), where    */
/* the version for qsort ISLT must always return a true value if the classic version CMP returns < 0. */
/* When inlined qsort is used, both ISLT and CMP can be inlined.                                      */
#ifdef MARPAESLIF_INLINED_QSORT
#include "marpaESLIF/internal/iqsort.h"
#define INLINE_QSORT inline /* Class qsort callback can be inlined */
#define MARPAESLIF_QSORT(TYPE,BASE,NELT,ISLT,CMP) QSORT(TYPE,BASE,NELT,ISLT)
#else
#define INLINE_QSORT
#define MARPAESLIF_QSORT(TYPE,BASE,NELT,ISLT,CMP) qsort(BASE,NELT,sizeof(TYPE),CMP)
#endif

#ifndef offsetof
#  define offsetof(type, member) ((size_t)((char *)&((type *)0)->member - (char *)0))
#endif

/* A hack on marpaESLIFValueResult to get the pointer. Look to union members that hold a pointer. */
/* It is NOT a hasard that they ALL start like this { p (a pointer), short shallowb, etc... }.    */
/* I.e. the offsets of p and shallowb are ALWAYS the same, for every marpaESLIFValueResult that   */
/* that is a container of another pointer.                                                        */
#define MARPAESLIFVALUERESULT_P_OFFSETOF offsetof(marpaESLIFValueResult_t, u.p.p)
#define MARPAESLIFVALUERESULT_TO_P(marpaESLIFValueResultp) (* (void **) (((char *) (marpaESLIFValueResultp)) + MARPAESLIFVALUERESULT_P_OFFSETOF))

#define MARPAESLIFVALUERESULT_SHALLOWB_OFFSETOF offsetof(marpaESLIFValueResult_t, u.p.shallowb)
#define MARPAESLIFVALUERESULT_TO_SHALLOWB(marpaESLIFValueResultp) (* (short *) (((char *) (marpaESLIFValueResultp)) + MARPAESLIFVALUERESULT_SHALLOWB_OFFSETOF))

#ifdef MARPAESLIF_HAVE_LONG_LONG
#define MARPAESLIFRECOGNIZER_MARPAESLIFVALUE_TRACE(funcs, marpaESLIFRecognizerp, whats, stacki, marpaESLIFValueResultp) do { \
    if (stacki >= 0) {                                                 \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Setting stack[%d]", stacki); \
    }                                                                   \
    switch (marpaESLIFValueResultp->type) {                             \
    case MARPAESLIF_VALUE_TYPE_UNDEF:                                   \
      MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Type: UNDEF"); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_CHAR:                                    \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: CHAR %c 0x%02x", isprint((unsigned char) marpaESLIFValueResultp->u.c) ? marpaESLIFValueResultp->u.c : ' ', (unsigned int) marpaESLIFValueResultp->u.c); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_SHORT:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: SHORT %d", (int) marpaESLIFValueResultp->u.b); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_INT:                                     \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: INT %d", marpaESLIFValueResultp->u.i); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_LONG:                                    \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: LONG %ld", marpaESLIFValueResultp->u.l); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_FLOAT:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: FLOAT %f", (double) marpaESLIFValueResultp->u.f); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_DOUBLE:                                  \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: DOUBLE %f", marpaESLIFValueResultp->u.d); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_PTR:                                     \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: PTR %p, shallowb %d", marpaESLIFValueResultp->u.p.p, (int) marpaESLIFValueResultp->u.p.shallowb); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_ARRAY:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: ARRAY {%p,%ld}, shallowb %d", marpaESLIFValueResultp->u.a.p, (unsigned long) marpaESLIFValueResultp->u.a.sizel, (int) marpaESLIFValueResultp->u.a.shallowb); \
      MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "Match dump for ", (whats != NULL) ? whats : "ARRAY", marpaESLIFValueResultp->u.a.p, marpaESLIFValueResultp->u.a.sizel, 1 /* traceb */, 0 /* noticeb */, marpaESLIFRecognizerp->marpaESLIF_streamp->linel, marpaESLIFRecognizerp->marpaESLIF_streamp->columnl); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH:			\
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: OFFSET_AND_LENGTH {%ld,%ld}", (long) marpaESLIFValueResultp->u.o.p, (unsigned long) marpaESLIFValueResultp->u.o.sizel); \
      MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "Match dump for ", (whats != NULL) ? whats : "OFFSET_AND_LENGTH", marpaESLIFRecognizerp->marpaESLIF_streamp->buffers + marpaESLIFValueResultp->u.o.p, marpaESLIFValueResultp->u.o.sizel, 1 /* traceb */, 0 /* noticeb */, marpaESLIFRecognizerp->marpaESLIF_streamp->linel, marpaESLIFRecognizerp->marpaESLIF_streamp->columnl); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_BOOL:                                    \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: BOOL %d", (int) marpaESLIFValueResultp->u.y); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_STRING:                                  \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: STRING {%p,%ld}, encoding %s, shallowb %d", marpaESLIFValueResultp->u.s.p, (unsigned long) marpaESLIFValueResultp->u.s.sizel, marpaESLIFValueResultp->u.s.encodingasciis, (int) marpaESLIFValueResultp->u.s.shallowb); \
      MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "Match dump for ", (whats != NULL) ? whats : "STRING", marpaESLIFValueResultp->u.s.p, marpaESLIFValueResultp->u.s.sizel, 1 /* traceb */, 0 /* noticeb */, marpaESLIFRecognizerp->marpaESLIF_streamp->linel, marpaESLIFRecognizerp->marpaESLIF_streamp->columnl); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_ROW:                                     \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: ROW {%p,%ld}, shallowb %d", marpaESLIFValueResultp->u.r.p, (unsigned long) marpaESLIFValueResultp->u.r.sizel, (int) marpaESLIFValueResultp->u.r.shallowb); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_TABLE:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: TABLE {%p,%ld}, shallowb %d", marpaESLIFValueResultp->u.t.p, (unsigned long) marpaESLIFValueResultp->u.t.sizel, (int) marpaESLIFValueResultp->u.t.shallowb); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:                           \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: LONG_DOUBLE %Lf", marpaESLIFValueResultp->u.ld); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_LONG_LONG:                               \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: LONG_LONG " MARPAESLIF_LONG_LONG_FMT, marpaESLIFValueResultp->u.ll); \
    default:                                                            \
      /* This is for debug - the rare case of MARPAESLIF_VALUE_TYPE_LONG_LONG is not handled */\
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: ? (type=%d)", marpaESLIFValueResultp->type); \
      break;                                                            \
    }                                                                   \
  } while (0)
#else /* MARPAESLIF_HAVE_LONG_LONG */
#define MARPAESLIFRECOGNIZER_MARPAESLIFVALUE_TRACE(funcs, marpaESLIFRecognizerp, whats, stacki, marpaESLIFValueResultp) do { \
    if (stacki >= 0) {                                                 \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Setting stack[%d]", stacki); \
    }                                                                   \
    switch (marpaESLIFValueResultp->type) {                                                \
    case MARPAESLIF_VALUE_TYPE_UNDEF:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: UNDEF"); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_CHAR:                                    \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: CHAR %c 0x%02x", isprint((unsigned char) marpaESLIFValueResultp->u.c) ? marpaESLIFValueResultp->u.c : ' ', (unsigned int) marpaESLIFValueResultp->u.c); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_SHORT:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: SHORT %d", (int) marpaESLIFValueResultp->u.b); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_INT:                                     \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: INT %d", marpaESLIFValueResultp->u.i); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_LONG:                                    \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: LONG %ld", marpaESLIFValueResultp->u.l); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_FLOAT:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: FLOAT %f", (double) marpaESLIFValueResultp->u.f); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_DOUBLE:                                  \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: DOUBLE %f", marpaESLIFValueResultp->u.d); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_PTR:                                     \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: PTR %p", marpaESLIFValueResultp->u.p.p); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_ARRAY:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: ARRAY {%p,%ld}", marpaESLIFValueResultp->u.a.p, (unsigned long) marpaESLIFValueResultp->u.a.sizel); \
      MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "Match dump for ", (whats != NULL) ? whats : "ARRAY", marpaESLIFValueResultp->u.a.p, marpaESLIFValueResultp->u.a.sizel, 1 /* traceb */, 0 /* noticeb */, marpaESLIFRecognizerp->marpaESLIF_streamp->linel, marpaESLIFRecognizerp->marpaESLIF_streamp->columnl); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH:			\
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: OFFSET_AND_LENGTH {%ld,%ld}", (long) marpaESLIFValueResultp->u.o.p, (unsigned long) marpaESLIFValueResultp->u.o.sizel); \
      MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "Match dump for ", (whats != NULL) ? whats : "OFFSET_AND_LENGTH", marpaESLIFRecognizerp->marpaESLIF_streamp->buffers + marpaESLIFValueResultp->u.o.p, marpaESLIFValueResultp->u.o.sizel, 1 /* traceb */, 0 /* noticeb */, marpaESLIFRecognizerp->marpaESLIF_streamp->linel, marpaESLIFRecognizerp->marpaESLIF_streamp->columnl); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_BOOL:                                    \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: BOOL %d", (int) marpaESLIFValueResultp->u.y); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_STRING:                                  \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: STRING {%p,%ld}, encoding %s", marpaESLIFValueResultp->u.s.p, (unsigned long) marpaESLIFValueResultp->u.s.sizel, marpaESLIFValueResultp->u.s.encodingasciis); \
      MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "Match dump for ", (whats != NULL) ? whats : "STRING", marpaESLIFValueResultp->u.s.p, marpaESLIFValueResultp->u.s.sizel, 1 /* traceb */, 0 /* noticeb */, marpaESLIFRecognizerp->marpaESLIF_streamp->linel, marpaESLIFRecognizerp->marpaESLIF_streamp->columnl); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_ROW:                                     \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: ROW {%p,%ld}", marpaESLIFValueResultp->u.r.p, (unsigned long) marpaESLIFValueResultp->u.r.sizel); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_TABLE:                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: TABLE {%p,%ld}", marpaESLIFValueResultp->u.t.p, (unsigned long) marpaESLIFValueResultp->u.t.sizel); \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:                           \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: LONG_DOUBLE %Lf", marpaESLIFValueResultp->u.ld); \
      break;                                                            \
    default:                                                            \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Type: ? (type=%d)", marpaESLIFValueResultp->type); \
      break;                                                            \
    }                                                                   \
  } while (0)
#endif /* MARPAESLIF_HAVE_LONG_LONG */

static const char *MARPAESLIF_VERSION_STATIC       = MARPAESLIF_VERSION;
static const int   MARPAESLIF_VERSION_MAJOR_STATIC = MARPAESLIF_VERSION_MAJOR;
static const int   MARPAESLIF_VERSION_MINOR_STATIC = MARPAESLIF_VERSION_MINOR;
static const int   MARPAESLIF_VERSION_PATCH_STATIC = MARPAESLIF_VERSION_PATCH;

/* For ord2utf */
static const int utf8_table1[] = { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff};
static const int utf8_table1_size = sizeof(utf8_table1) / sizeof(int);
static const int utf8_table2[] = { 0,    0xc0, 0xe0, 0xf0, 0xf8, 0xfc};
static const int utf8_table3[] = { 0xff, 0x1f, 0x0f, 0x07, 0x03, 0x01};

/* C.f. https://stackoverflow.com/questions/10536207/ansi-c-maximum-number-of-characters-printing-a-decimal-int */
#define MARPAESLIF_MAX_DECIMAL_DIGITS_TYPE(type) ((3 * sizeof(type) * CHAR_BIT / 8) + 1) /* Rounded-up approximation, without NUL */
#define MARPAESLIF_MAX_DECIMAL_DIGITS_CHAR     MARPAESLIF_MAX_DECIMAL_DIGITS_TYPE(char)
#define MARPAESLIF_MAX_DECIMAL_DIGITS_SHORT    MARPAESLIF_MAX_DECIMAL_DIGITS_TYPE(short)
#define MARPAESLIF_MAX_DECIMAL_DIGITS_INT      MARPAESLIF_MAX_DECIMAL_DIGITS_TYPE(int)
#define MARPAESLIF_MAX_DECIMAL_DIGITS_LONG     MARPAESLIF_MAX_DECIMAL_DIGITS_TYPE(long)
#ifdef MARPAESLIF_HAVE_LONG_LONG
#define MARPAESLIF_MAX_DECIMAL_DIGITS_LONGLONG MARPAESLIF_MAX_DECIMAL_DIGITS_TYPE(long long)
#endif

#ifndef C_SIGNBIT
/* Based on npymath/_signbit.c */
#  ifdef __GNUC__
#    warning Simulating missing signbit()
#  else
#    ifdef _MSC_VER
#      pragma message("Simulating missing signbit()")
#   endif
#  endif
#  define C_SIGNBIT _marpaESLIF_signbit_d
static inline int _marpaESLIF_signbit_d(double x)
{
  union
  {
    double d;
    short s[4];
    int i[2];
  } u;

  u.d = x;

#  if SIZEOF_INT == 4
#    ifdef WORDS_BIGENDIAN
  return u.i[0] < 0;
#    else
  return u.i[1] < 0;
#    endif
#  else  /* SIZEOF_INT */
#    ifdef WORDS_BIGENDIAN
  return u.s[0] < 0;
#    else
  return u.s[3] < 0;
#    endif
#  endif  /* SIZEOF_INT */
}
#endif /* C_SIGNBIT */

#define MARPAESLIF_ENCODING_IS_UTF8(encodings, encodingl)               \
  (                                                                     \
    /* UTF-8 */                                                         \
    (                                                                   \
      (encodingl == 5)                                 &&               \
      ((encodings[0] == 'U') || (encodings[0] == 'u')) &&               \
      ((encodings[1] == 'T') || (encodings[1] == 't')) &&               \
      ((encodings[2] == 'F') || (encodings[2] == 'f')) &&               \
       (encodings[3] == '-') &&                                         \
       (encodings[4] == '8')                                            \
    )                                                                   \
    ||                                                                  \
    /* UTF8 */                                                          \
    (                                                                   \
      (encodingl == 4)                                 &&               \
      ((encodings[0] == 'U') || (encodings[0] == 'u')) &&               \
      ((encodings[1] == 'T') || (encodings[1] == 't')) &&               \
      ((encodings[2] == 'F') || (encodings[2] == 'f')) &&               \
       (encodings[3] == '8')                                            \
    )                                                                   \
  )

#define MARPAESLIF_ENCODING_IS_UTF16(encodings, encodingl)              \
  (                                                                     \
    /* UTF-16 */                                                        \
    (                                                                   \
      (encodingl == 6)                                 &&               \
      ((encodings[0] == 'U') || (encodings[0] == 'u')) &&               \
      ((encodings[1] == 'T') || (encodings[1] == 't')) &&               \
      ((encodings[2] == 'F') || (encodings[2] == 'f')) &&               \
       (encodings[3] == '-')                           &&               \
       (encodings[4] == '1')                           &&               \
       (encodings[5] == '6')                                            \
    )                                                                   \
    ||                                                                  \
    /* UTF16 */                                                         \
    (                                                                   \
      (encodingl == 5)                                 &&               \
      ((encodings[0] == 'U') || (encodings[0] == 'u')) &&               \
      ((encodings[1] == 'T') || (encodings[1] == 't')) &&               \
      ((encodings[2] == 'F') || (encodings[2] == 'f')) &&               \
       (encodings[3] == '1')                           &&               \
       (encodings[4] == '6')                                            \
    )                                                                   \
  )

#define MARPAESLIF_ENCODING_IS_UTF32(encodings, encodingl)              \
  (                                                                     \
    /* UTF-32 */                                                        \
    (                                                                   \
      (encodingl == 6)                                 &&               \
      ((encodings[0] == 'U') || (encodings[0] == 'u')) &&               \
      ((encodings[1] == 'T') || (encodings[1] == 't')) &&               \
      ((encodings[2] == 'F') || (encodings[2] == 'f')) &&               \
       (encodings[3] == '-')                           &&               \
       (encodings[4] == '3')                           &&               \
       (encodings[5] == '2')                                            \
    )                                                                   \
    ||                                                                  \
    /* UTF32 */                                                         \
    (                                                                   \
      (encodingl == 5)                                 &&               \
      ((encodings[0] == 'U') || (encodings[0] == 'u')) &&               \
      ((encodings[1] == 'T') || (encodings[1] == 't')) &&               \
      ((encodings[2] == 'F') || (encodings[2] == 'f')) &&               \
       (encodings[3] == '3')                           &&               \
       (encodings[4] == '2')                                            \
    )                                                                   \
  )

#ifndef MARPAESLIF_VALUEERRORPROGRESSREPORT
#define MARPAESLIF_VALUEERRORPROGRESSREPORT 0 /* Left in the code, although not needed IMHO */
#endif

/* Internal marpaESLIFValueResult used to do lazy row transformation: we use an INVALID type */
/* that only marpaESLIF can set because its contextp is NULL.                                */
/* We distinguish containers that have UNDEF or not.                                         */
/* This is likely to generate compiler warnings.                                             */
#define MARPAESLIF_VALUE_TYPE_LAZY_NOUNDEF -1
static marpaESLIFValueResult_t marpaESLIFValueResultLazyNoUndef = {
  NULL,                      /* contextp */
  NULL,                      /* representationp */
  MARPAESLIF_VALUE_TYPE_LAZY_NOUNDEF /* type */
};

#define MARPAESLIF_VALUE_TYPE_LAZY_WITHUNDEF -2
static marpaESLIFValueResult_t marpaESLIFValueResultLazyWithUndef = {
  NULL,                      /* contextp */
  NULL,                      /* representationp */
  MARPAESLIF_VALUE_TYPE_LAZY_WITHUNDEF /* type */
};

/* -------------------------------------------------------------------------------------------- */
/* Exhaustion event name is hardcoded                                                           */
/* -------------------------------------------------------------------------------------------- */
#define MARPAESLIF_EVENTTYPE_EXHAUSTED_NAME "'exhausted'"

/* -------------------------------------------------------------------------------------------- */
/* Util macros on symbol                                                                        */
/* -------------------------------------------------------------------------------------------- */
#define MARPAESLIF_IS_META(symbolp)               ((symbolp)->type == MARPAESLIF_SYMBOL_TYPE_META)
#define MARPAESLIF_IS_LEXEME(symbolp)             (MARPAESLIF_IS_META(symbolp) && (! (symbolp)->lhsb))
#define MARPAESLIF_IS_TERMINAL(symbolp)           ((symbolp)->type == MARPAESLIF_SYMBOL_TYPE_TERMINAL)
#define MARPAESLIF_IS_LEXEME_OR_TERMINAL(symbolp) (MARPAESLIF_IS_LEXEME(symbolp) || MARPAESLIF_IS_TERMINAL(symbolp))
#define MARPAESLIF_IS_PSEUDO_TERMINAL(symbolp)    (MARPAESLIF_IS_TERMINAL(symbolp) && (symbolp)->u.terminalp->pseudob)
#define MARPAESLIF_IS_META_LOOKAHEAD(symbolp)     (MARPAESLIF_IS_META(symbolp) && (symbolp)->lookaheadb)
#define MARPAESLIF_IS_DISCARD(symbolp)            (symbolp)->discardb

/* -------------------------------------------------------------------------------------------- */
/* Util macros on recognizer                                                                    */
/* -------------------------------------------------------------------------------------------- */
#define MARPAESLIFRECOGNIZER_IS_TOP(marpaESLIFRecognizerp) ((marpaESLIFRecognizerp)->marpaESLIFRecognizerParentp == NULL)
#define MARPAESLIFRECOGNIZER_IS_CHILD(marpaESLIFRecognizerp) ((marpaESLIFRecognizerp)->marpaESLIFRecognizerParentp != NULL)
#define MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp) (MARPAESLIFRECOGNIZER_IS_TOP(marpaESLIFRecognizerp) || (! (marpaESLIFRecognizerp)->noEventb))
#define MARPAESLIFRECOGNIZER_MATCH_TRACE(funcs, marpaESLIFRecognizerp, symbolp, rci, marpaESLIFValueResultp) do { \
    if (rci == MARPAESLIF_MATCH_OK) {                                   \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Match OK for %s", symbolp->descp->asciis); \
      MARPAESLIFRECOGNIZER_MARPAESLIFVALUE_TRACE(funcs, marpaESLIFRecognizerp, symbolp->descp->asciis, -1 /* i */, marpaESLIFValueResultp); \
    } else {                                                            \
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Match KO for %s", symbolp->descp->asciis); \
    }                                                                   \
  } while (0)

/* -------------------------------------------------------------------------------------------- */
/* This macro makes sure we return a multiple of chunk of always at least 1 BYTE more than size */
/* -------------------------------------------------------------------------------------------- */
#define MARPAESLIF_CHUNKED_SIZE_UPPER(size, chunk) ((size) < (chunk)) ? (chunk) : ((1 + ((size) / (chunk))) * (chunk))

/* -------------------------------------------------------------------------------------------- */
/* Get a symbol from stack - with an extra check when not in production mode                    */
/* -------------------------------------------------------------------------------------------- */
#ifndef MARPAESLIF_NTRACE
#define MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli) do { \
    if (MARPAESLIF_UNLIKELY((symboli < 0) || (! GENERICSTACK_IS_PTR(symbolStackp, symboli)))) { \
      MARPAESLIF_ERRORF(marpaESLIFp, "Symbol no %d is unknown from symbolStackp", symboli); \
      errno = EINVAL;                                                   \
      goto err;                                                         \
    }                                                                   \
    symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_GET_PTR(symbolStackp, symboli); \
  } while (0)
#else
#define MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli) \
  symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_GET_PTR(symbolStackp, symboli)
#endif

/* -------------------------------------------------------------------------------------------- */
/* Fast access to a symbol from the grammar                                                     */
/* -------------------------------------------------------------------------------------------- */
#ifndef MARPAESLIF_NTRACE
#define MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFp, symbolp, grammarp, symboli) do { \
    if (MARPAESLIF_UNLIKELY((symboli < 0) || (! GENERICSTACK_IS_PTR(grammarp->symbolStackp, symboli)))) { \
      MARPAESLIF_ERRORF(marpaESLIFp, "Symbol no %d is unknown from symbolStackp", symboli); \
      errno = EINVAL;                                                   \
      goto err;                                                         \
    }                                                                   \
    symbolp = grammarp->allSymbolsArraypp[symboli];                     \
  } while (0)
#else
#define MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFp, symbolp, grammarp, symboli) \
  symbolp = grammarp->allSymbolsArraypp[symboli]
#endif

/* -------------------------------------------------------------------------------------------- */
/* Fast access to a rule from the grammar                                                       */
/* -------------------------------------------------------------------------------------------- */
#ifndef MARPAESLIF_NTRACE
#define MARPAESLIF_GRAMMAR_INTERNAL_GET_RULE(marpaESLIFp, rulep, grammarp, rulei) do { \
    if (MARPAESLIF_UNLIKELY((rulei < 0) || (! GENERICSTACK_IS_PTR(grammarp->ruleStackp, rulei)))) { \
      MARPAESLIF_ERRORF(marpaESLIFp, "Rule no %d is unknown from ruleStackp", rulei); \
      errno = EINVAL;                                                   \
      goto err;                                                         \
    }                                                                   \
    rulep = grammarp->allRulesArraypp[rulei];                           \
  } while (0)
#else
#define MARPAESLIF_GRAMMAR_INTERNAL_GET_RULE(marpaESLIFp, rulep, grammarp, rulei) \
  rulep = grammarp->allRulesArraypp[rulei]
#endif

/* -------------------------------------------------------------------------------------------- */
/* Get a rule from stack - with an extra check when not in production mode                      */
/* -------------------------------------------------------------------------------------------- */
#ifndef MARPAESLIF_NTRACE
#define MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei) do { \
    if (MARPAESLIF_UNLIKELY((rulei < 0) || (! GENERICSTACK_IS_PTR(ruleStackp, rulei)))) { \
      MARPAESLIF_ERRORF(marpaESLIFp, "Rule no %d is unknown from ruleStackp", rulei); \
      errno = EINVAL;                                                   \
      goto err;                                                         \
    }                                                                   \
    rulep = (marpaESLIF_rule_t *) GENERICSTACK_GET_PTR(ruleStackp, rulei); \
  } while (0)
#else
#define MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei) \
  rulep = (marpaESLIF_rule_t *) GENERICSTACK_GET_PTR(ruleStackp, rulei)
#endif

/* -------------------------------------------------------------------------------------------- */
/* Make a marpaESLIFValueResult shallow                                                         */
/* -------------------------------------------------------------------------------------------- */
#define MARPAESLIF_MAKE_MARPAESLIFVALUERESULT_SHALLOW(marpaESLIFValueResult) do { \
    switch (marpaESLIFValueResult.type) {                               \
    case MARPAESLIF_VALUE_TYPE_PTR:                                     \
      (marpaESLIFValueResult).u.p.shallowb       = 1;			\
      (marpaESLIFValueResult).u.p.freeUserDatavp = NULL;                \
      (marpaESLIFValueResult).u.p.freeCallbackp  = NULL;                \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_ARRAY:                                   \
      (marpaESLIFValueResult).u.a.shallowb       = 1;			\
      (marpaESLIFValueResult).u.a.freeUserDatavp = NULL;                \
      (marpaESLIFValueResult).u.a.freeCallbackp  = NULL;                \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_STRING:                                  \
      (marpaESLIFValueResult).u.s.shallowb       = 1;			\
      (marpaESLIFValueResult).u.s.freeUserDatavp = NULL;                \
      (marpaESLIFValueResult).u.s.freeCallbackp  = NULL;                \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_ROW:                                     \
      (marpaESLIFValueResult).u.r.shallowb       = 1;			\
      (marpaESLIFValueResult).u.r.freeUserDatavp = NULL;                \
      (marpaESLIFValueResult).u.r.freeCallbackp  = NULL;                \
      break;                                                            \
    case MARPAESLIF_VALUE_TYPE_TABLE:                                   \
      (marpaESLIFValueResult).u.t.shallowb       = 1;			\
      (marpaESLIFValueResult).u.t.freeUserDatavp = NULL;                \
      (marpaESLIFValueResult).u.t.freeCallbackp  = NULL;                \
      break;                                                            \
    default:                                                            \
      break;                                                            \
    }                                                                   \
  } while (0)

/* -------------------------------------------------------------------------------------------- */
/* Make a marpaESLIFValueResultp shallow                                                        */
/* -------------------------------------------------------------------------------------------- */
#define MARPAESLIF_MAKE_MARPAESLIFVALUERESULTP_SHALLOW(marpaESLIFValueResultp) do { \
    if (marpaESLIFValueResultp != NULL) {                               \
      switch (marpaESLIFValueResultp->type) {                           \
      case MARPAESLIF_VALUE_TYPE_PTR:                                   \
        marpaESLIFValueResultp->u.p.shallowb       = 1;			\
        marpaESLIFValueResultp->u.p.freeUserDatavp = NULL;              \
        marpaESLIFValueResultp->u.p.freeCallbackp  = NULL;              \
        break;                                                          \
      case MARPAESLIF_VALUE_TYPE_ARRAY:                                 \
        marpaESLIFValueResultp->u.a.shallowb       = 1;			\
        marpaESLIFValueResultp->u.a.freeUserDatavp = NULL;              \
        marpaESLIFValueResultp->u.a.freeCallbackp  = NULL;              \
        break;                                                          \
      case MARPAESLIF_VALUE_TYPE_STRING:                                \
        marpaESLIFValueResultp->u.s.shallowb       = 1;			\
        marpaESLIFValueResultp->u.s.freeUserDatavp = NULL;              \
        marpaESLIFValueResultp->u.s.freeCallbackp  = NULL;              \
        break;                                                          \
      case MARPAESLIF_VALUE_TYPE_ROW:                                   \
        marpaESLIFValueResultp->u.r.shallowb       = 1;			\
        marpaESLIFValueResultp->u.r.freeUserDatavp = NULL;              \
        marpaESLIFValueResultp->u.r.freeCallbackp  = NULL;              \
        break;                                                          \
      case MARPAESLIF_VALUE_TYPE_TABLE:                                 \
        marpaESLIFValueResultp->u.t.shallowb       = 1;			\
        marpaESLIFValueResultp->u.t.freeUserDatavp = NULL;              \
        marpaESLIFValueResultp->u.t.freeCallbackp  = NULL;              \
        break;                                                          \
      default:                                                          \
        break;                                                          \
      }                                                                 \
    }                                                                   \
  } while (0)

/* -------------------------------------------------------------------- */
/* _marpaESLIFRecognizer_concat_valueResultCallbackb helpers            */
/* -------------------------------------------------------------------- */
#define VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, strings) do { \
    GENERICLOGGER_TRACE(genericLoggerp, strings);                       \
    if (MARPAESLIF_UNLIKELY(! marpaESLIF_stringGeneratorp->okb)) {      \
      goto err;                                                         \
    }                                                                   \
  } while (0)

#define VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, fmts, ...) do { \
    GENERICLOGGER_TRACEF(genericLoggerp, fmts, __VA_ARGS__);            \
    if (MARPAESLIF_UNLIKELY(! marpaESLIF_stringGeneratorp->okb)) {      \
      goto err;                                                         \
    }                                                                   \
  } while (0)

#define VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, srcs, srcl) do { \
    if (MARPAESLIF_UNLIKELY(! _marpaESLIF_appendOpaqueDataToStringGenerator(marpaESLIF_stringGeneratorp, srcs, srcl))) { \
      goto err;                                                         \
    }                                                                   \
  } while (0)


#define VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, type, value, currentDecimalPointc, wantedDecimalPointc) do { \
    char *_decimalPointp;                                               \
    char *_floattos = marpaESLIF_##type##tos(marpaESLIFp, value);       \
    if (MARPAESLIF_UNLIKELY(_floattos == NULL)) {                       \
      goto err;                                                         \
    }                                                                   \
    if (currentDecimalPointc != '\0') {                                 \
      if (wantedDecimalPointc != '\0') {                                \
        if (currentDecimalPointc != wantedDecimalPointc) {              \
          _decimalPointp = strchr(_floattos, currentDecimalPointc);     \
          if (_decimalPointp != NULL) {                                 \
            *_decimalPointp = wantedDecimalPointc;                      \
          }                                                             \
        }                                                               \
      }                                                                 \
    }                                                                   \
    GENERICLOGGER_TRACEF(genericLoggerp, "%s", _floattos);              \
    free(_floattos);                                                    \
    if (MARPAESLIF_UNLIKELY(! marpaESLIF_stringGeneratorp->okb)) {      \
      goto err;                                                         \
    }                                                                   \
  } while (0)

#define VALUERESULTCALLBACK_CODEPOINT_TO_JSON(genericLoggerp, marpaESLIF_stringGeneratorp, codepoint) do { \
    /* Adapted from https://github.com/nlohmann/json/blob/develop/include/nlohmann/detail/output/serializer.hpp */ \
    marpaESLIF_uint32_t _codepoint = (marpaESLIF_uint32_t) codepoint;   \
                                                                        \
    switch (_codepoint) {                                               \
    case 0x08: /* backspace */                                          \
      VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\\b"); \
      break;                                                            \
    case 0x09: /* horizontal tab */                                     \
      VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\\t"); \
      break;                                                            \
    case 0x0A: /* newline */                                            \
      VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\\n"); \
      break;                                                            \
    case 0x0C: /* formfeed */                                           \
      VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\\f"); \
      break;                                                            \
    case 0x0D: /* carriage return */                                    \
      VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\\r"); \
      break;                                                            \
    case 0x22: /* quotation mark */                                     \
      VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\\\""); \
      break;                                                            \
    case 0x5C: /* reverse solidus */                                    \
      VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\\\\"); \
      break;                                                            \
    default:                                                            \
      /* escape control characters (0x00..0x1F) or non-ASCII characters */ \
      if ((codepoint <= (marpaESLIF_uint32_t) 0x1F) || (codepoint >= (marpaESLIF_uint32_t) 0x7F)) { \
        if (codepoint <= (marpaESLIF_uint32_t) 0xFFFF) {                 \
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\\u%04x", (int) codepoint); \
        } else {                                                        \
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\\u%04x\\u%04x", (int) (0xD7C0 + (codepoint >> 10)), (int) (0xDC00 + (codepoint & 0x3FF))); \
        }                                                               \
      } else {                                                          \
        VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%c", (char) codepoint); \
      }                                                                 \
      break;                                                            \
    }                                                                   \
  } while (0)

/* -------------------------------------------------------------------------------------------- */
/* For logging                                                                                  */
/* -------------------------------------------------------------------------------------------- */
#undef  FILENAMES
#define FILENAMES "marpaESLIF.c"

/* -------------------------------------------------------------------------------------------- */
/* For regexp callout block initialization                                                      */
/* -------------------------------------------------------------------------------------------- */
#define MARPAESLIFCALLOUTBLOCK_INIT_STRING(marpaESLIFValueResult, utf8s, utf8l) do { \
    marpaESLIFValueResult.contextp           = NULL;                    \
    marpaESLIFValueResult.representationp    = NULL;                    \
    marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_STRING; \
    marpaESLIFValueResult.u.s.p              = (unsigned char *) (utf8s); \
    marpaESLIFValueResult.u.s.shallowb       = 1;                       \
    marpaESLIFValueResult.u.s.freeUserDatavp = NULL;                    \
    marpaESLIFValueResult.u.s.freeCallbackp  = NULL;                    \
    marpaESLIFValueResult.u.s.sizel          = (size_t) (utf8l);        \
    marpaESLIFValueResult.u.s.encodingasciis = (char *) MARPAESLIF_UTF8_STRING; \
  } while (0)

#define MARPAESLIFCALLOUTBLOCK_INIT_ARRAY(marpaESLIFValueResult, q, lengthl) do { \
    marpaESLIFValueResult.contextp           = NULL;                    \
    marpaESLIFValueResult.representationp    = NULL;                    \
    marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_ARRAY; \
    marpaESLIFValueResult.u.a.p              = (char *) (q);            \
    marpaESLIFValueResult.u.a.shallowb       = 1;                       \
    marpaESLIFValueResult.u.a.freeUserDatavp = NULL;                    \
    marpaESLIFValueResult.u.a.freeCallbackp  = NULL;                    \
    marpaESLIFValueResult.u.a.sizel          = (size_t) (lengthl);        \
  } while (0)

#define MARPAESLIFCALLOUTBLOCK_INIT_ROW(marpaESLIFValueResult, q, lengthl) do { \
    marpaESLIFValueResult.contextp           = NULL;                    \
    marpaESLIFValueResult.representationp    = NULL;                    \
    marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_ROW; \
    marpaESLIFValueResult.u.r.p              = q;                       \
    marpaESLIFValueResult.u.r.shallowb       = 0;                       \
    marpaESLIFValueResult.u.r.freeUserDatavp = NULL;                    \
    marpaESLIFValueResult.u.r.freeCallbackp  = NULL;                    \
    marpaESLIFValueResult.u.r.sizel          = lengthl;                 \
  } while (0)

#define MARPAESLIFCALLOUTBLOCK_INIT_INT(marpaESLIFValueResult, value) do { \
    marpaESLIFValueResult.contextp           = NULL;                    \
    marpaESLIFValueResult.representationp    = NULL;                    \
    marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_INT; \
    marpaESLIFValueResult.u.i                = (int) (value);           \
  } while (0)

#define MARPAESLIFCALLOUTBLOCK_INIT_LONG(marpaESLIFValueResult, value) do { \
    marpaESLIFValueResult.contextp           = NULL;                    \
    marpaESLIFValueResult.representationp    = NULL;                    \
    marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_LONG; \
    marpaESLIFValueResult.u.l                = (long) (value);          \
  } while (0)

#define MARPAESLIFCALLOUTBLOCK_INIT_UNDEF(marpaESLIFValueResult) do {   \
    marpaESLIFValueResult.contextp           = NULL;                    \
    marpaESLIFValueResult.representationp    = NULL;                    \
    marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_UNDEF; \
  } while (0)

/* Util macros used in _marpaESLIFGrammar_validateb() */
#define MARPAESLIFGRAMMAR_GET_TERMINALS(marpaESLIFp, funcs, starts, grammarp, marpaWrapperGrammarp, nTerminall, symbolArraypp) do { \
    int _symboli;                                                       \
    int _symbolArraypi;                                                 \
    marpaESLIF_symbol_t *_symbolp;                                      \
    int _propertyBitSet;                                                \
                                                                        \
    if (symbolArraypp == NULL) {                                        \
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Getting grammar terminals in grammar level %d (%s)", grammarp->leveli, grammarp->descp->asciis); \
      nTerminall = 0;                                                     \
      for (_symboli = 0; _symboli < GENERICSTACK_USED(grammarp->symbolStackp); _symboli++) { \
        MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, _symbolp, grammarp->symbolStackp, _symboli); \
        if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_symbolPropertyb(marpaWrapperGrammarp, _symbolp->idi, &_propertyBitSet))) { \
          goto err;                                                     \
        }                                                               \
        if ((_propertyBitSet & MARPAWRAPPER_SYMBOL_IS_TERMINAL) != MARPAWRAPPER_SYMBOL_IS_TERMINAL) { \
          continue;                                                     \
        }                                                               \
        nTerminall++;                                                     \
      }                                                                 \
      if (nTerminall > 0) {                                               \
        symbolArraypp = (marpaESLIF_symbol_t **) malloc(sizeof(marpaESLIF_symbol_t *) * nTerminall); \
        if (MARPAESLIF_UNLIKELY(symbolArraypp == NULL)) {               \
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno)); \
          goto err;                                                     \
        }                                                               \
        _symbolArraypi = 0;                                             \
        for (_symboli = 0; _symboli < GENERICSTACK_USED(grammarp->symbolStackp); _symboli++) { \
          MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, _symbolp, grammarp->symbolStackp, _symboli); \
          if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_symbolPropertyb(marpaWrapperGrammarp, _symbolp->idi, &_propertyBitSet))) { \
            goto err;                                                   \
          }                                                             \
          if ((_propertyBitSet & MARPAWRAPPER_SYMBOL_IS_TERMINAL) != MARPAWRAPPER_SYMBOL_IS_TERMINAL) { \
            continue;                                                   \
          }                                                             \
          MARPAESLIF_TRACEF(marpaESLIFp, funcs, "... Found symbol No %d <%s>", _symbolp->idi, _symbolp->descp->asciis); \
          symbolArraypp[_symbolArraypi++] = _symbolp;                   \
        }                                                               \
        MARPAESLIF_QSORT(marpaESLIF_symbol_t *, symbolArraypp, _symbolArraypi, _marpaESLIF_symbol_priority_sort_inlinedi, _marpaESLIF_symbol_priority_sorti); \
      }                                                                 \
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Getting grammar terminals in grammar level %d (%s): %ld symbols found", grammarp->leveli, grammarp->descp->asciis, (unsigned long) nTerminall); \
    }                                                                   \
  } while (0)

#define MARPAESLIFRECOGNIZER_DUMP_NOTICE_BEFORE(funcs, marpaESLIFRecognizerp, nbytel) do { \
  char   *_dumps;                                                       \
  size_t _dumpl;                                                        \
                                                                        \
  /* If there is some information before, show it */                    \
  if ((marpaESLIFRecognizerp->marpaESLIF_streamp->inputs != NULL) && (marpaESLIFRecognizerp->marpaESLIF_streamp->buffers != NULL) && (marpaESLIFRecognizerp->marpaESLIF_streamp->inputs > marpaESLIFRecognizerp->marpaESLIF_streamp->buffers)) { \
    if ((marpaESLIFRecognizerp->marpaESLIF_streamp->inputs - marpaESLIFRecognizerp->marpaESLIF_streamp->buffers) > nbytel) { \
      _dumps = marpaESLIFRecognizerp->marpaESLIF_streamp->inputs - nbytel; \
      _dumpl = nbytel;                                                     \
    } else {                                                            \
      _dumps = marpaESLIFRecognizerp->marpaESLIF_streamp->buffers;      \
      _dumpl = marpaESLIFRecognizerp->marpaESLIF_streamp->inputs - marpaESLIFRecognizerp->marpaESLIF_streamp->buffers; \
    }                                                                   \
    MARPAESLIFRECOGNIZER_HEXDUMPV(funcs,                                \
                                  marpaESLIFRecognizerp,                \
                                  "",                                   \
                                  marpaESLIFRecognizerp->marpaESLIF_streamp->utfb ? "UTF-8 converted data before" : "Raw data before", \
                                  _dumps,                               \
                                  _dumpl,                               \
                                  0, /* traceb */                       \
                                  1, /* noticeb */                      \
                                  marpaESLIFRecognizerp->marpaESLIF_streamp->linel, \
                                  marpaESLIFRecognizerp->marpaESLIF_streamp->columnl); \
    }                                                                   \
  } while (0)

#define MARPAESLIFRECOGNIZER_DUMP_NOTICE_AFTER(funcs, marpaESLIFRecognizerp, nbytel) do { \
  char   *_dumps;                                                       \
  size_t _dumpl;                                                        \
                                                                        \
  /* If there is some information after, show it */                     \
  if ((marpaESLIFRecognizerp->marpaESLIF_streamp->inputs != NULL) && (marpaESLIFRecognizerp->marpaESLIF_streamp->inputl > 0)) { \
    _dumps = marpaESLIFRecognizerp->marpaESLIF_streamp->inputs;         \
    _dumpl = marpaESLIFRecognizerp->marpaESLIF_streamp->inputl > nbytel ? nbytel : marpaESLIFRecognizerp->marpaESLIF_streamp->inputl; \
    MARPAESLIFRECOGNIZER_HEXDUMPV(funcs,                                \
                                  marpaESLIFRecognizerp,                \
                                  "",                                   \
                                  marpaESLIFRecognizerp->marpaESLIF_streamp->utfb ? "UTF-8 current converted data" : "Raw current data", \
                                  _dumps,                               \
                                  _dumpl,                               \
                                  0, /* traceb */                       \
                                  1, /* noticeb */                      \
                                  marpaESLIFRecognizerp->marpaESLIF_streamp->linel, \
                                  marpaESLIFRecognizerp->marpaESLIF_streamp->columnl); \
    }                                                                   \
  } while (0)

#define MARPAESLIF_PATTERN_CREATESHOW(_marpaESLIFp, patterns, patternl) do { \
    marpaESLIF_stringGenerator_t  _marpaESLIF_stringGenerator;          \
    genericLogger_t              *_genericLoggerp;                      \
                                                                        \
    _marpaESLIF_stringGenerator.marpaESLIFp = _marpaESLIFp;             \
    _marpaESLIF_stringGenerator.s           = NULL;                     \
    _marpaESLIF_stringGenerator.l           = 0;                        \
    _marpaESLIF_stringGenerator.okb         = 0;                        \
    _marpaESLIF_stringGenerator.allocl      = 0;                        \
                                                                        \
    _genericLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIF_generateStringWithLoggerCallback, (void *) &_marpaESLIF_stringGenerator, GENERICLOGGER_LOGLEVEL_TRACE); \
    if (_genericLoggerp != NULL) {                                      \
      size_t i;                                                         \
      size_t j;                                                         \
      size_t lengthl = patternl;                                        \
      char  *p = patterns;                                              \
                                                                        \
      for (i = 0; i < lengthl + ((lengthl % MARPAESLIF_HEXDUMP_COLS) ? (MARPAESLIF_HEXDUMP_COLS - lengthl % MARPAESLIF_HEXDUMP_COLS) : 0); i++) { \
        /* print offset */                                              \
        if (i % MARPAESLIF_HEXDUMP_COLS == 0) {                         \
          GENERICLOGGER_TRACEF(_genericLoggerp, "#     0x%06x: ", i);   \
        }                                                               \
        /* print hex data */                                            \
        if (i < lengthl) {                                              \
          GENERICLOGGER_TRACEF(_genericLoggerp, "%02x ", 0xFF & p[i]);  \
        } else { /* end of block, just aligning for ASCII dump */       \
          GENERICLOGGER_TRACE(_genericLoggerp, "   ");                  \
        }                                                               \
        /* print ASCII dump */                                          \
        if (i % MARPAESLIF_HEXDUMP_COLS == (MARPAESLIF_HEXDUMP_COLS - 1)) { \
          for (j = i - (MARPAESLIF_HEXDUMP_COLS - 1); j <= i; j++) {    \
            if (j >= lengthl) { /* end of block, not really printing */ \
              GENERICLOGGER_TRACE(_genericLoggerp, " ");                \
            }                                                           \
            else if (isprint(0xFF & p[j])) { /* printable char */       \
              GENERICLOGGER_TRACEF(_genericLoggerp, "%c", 0xFF & p[j]); \
            }                                                           \
            else { /* other char */                                     \
              GENERICLOGGER_TRACE(_genericLoggerp, ".");                \
            }                                                           \
          }                                                             \
          if (_marpaESLIF_stringGenerator.okb) {                        \
            MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, _marpaESLIF_stringGenerator.s); \
            MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n"); \
          }                                                             \
          if (_marpaESLIF_stringGenerator.s != NULL) {                  \
            free(_marpaESLIF_stringGenerator.s);                        \
          }                                                             \
          _marpaESLIF_stringGenerator.s = NULL;                         \
          _marpaESLIF_stringGenerator.okb = 0;                          \
        }                                                               \
      }                                                                 \
      GENERICLOGGER_FREE(_genericLoggerp);                              \
  }                                                                     \
} while (0)

#define MARPAESLIF_PCRE2_FLAGS_CREATESHOW(_marpaESLIFp, whats, pcre2Optioni, substituteb) do { \
    marpaESLIF_stringGenerator_t  _marpaESLIF_stringGenerator;          \
    genericLogger_t              *_genericLoggerp;                      \
                                                                        \
    _marpaESLIF_stringGenerator.marpaESLIFp = _marpaESLIFp;             \
    _marpaESLIF_stringGenerator.s           = NULL;                     \
    _marpaESLIF_stringGenerator.l           = 0;                        \
    _marpaESLIF_stringGenerator.okb         = 0;                        \
    _marpaESLIF_stringGenerator.allocl      = 0;                        \
                                                                        \
    _genericLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIF_generateSeparatedStringWithLoggerCallback, (void *) &_marpaESLIF_stringGenerator, GENERICLOGGER_LOGLEVEL_TRACE); \
    if (_genericLoggerp != NULL) {                                      \
      if (substituteb) {                                                \
        if ((pcre2Optioni & PCRE2_SUBSTITUTE_EXTENDED)         == PCRE2_SUBSTITUTE_EXTENDED)         { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_SUBSTITUTE_EXTENDED"); } \
        if ((pcre2Optioni & PCRE2_SUBSTITUTE_GLOBAL)           == PCRE2_SUBSTITUTE_GLOBAL)           { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_SUBSTITUTE_GLOBAL"); } \
        if ((pcre2Optioni & PCRE2_SUBSTITUTE_LITERAL)          == PCRE2_SUBSTITUTE_LITERAL)          { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_SUBSTITUTE_LITERAL"); } \
        if ((pcre2Optioni & PCRE2_SUBSTITUTE_MATCHED)          == PCRE2_SUBSTITUTE_MATCHED)          { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_SUBSTITUTE_MATCHED"); } \
        if ((pcre2Optioni & PCRE2_SUBSTITUTE_OVERFLOW_LENGTH)  == PCRE2_SUBSTITUTE_OVERFLOW_LENGTH)  { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_SUBSTITUTE_OVERFLOW_LENGTH"); } \
        if ((pcre2Optioni & PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) == PCRE2_SUBSTITUTE_REPLACEMENT_ONLY) { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_SUBSTITUTE_REPLACEMENT_ONLY"); } \
        if ((pcre2Optioni & PCRE2_SUBSTITUTE_UNKNOWN_UNSET)    == PCRE2_SUBSTITUTE_UNKNOWN_UNSET)    { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_SUBSTITUTE_UNKNOWN_UNSET"); } \
        if ((pcre2Optioni & PCRE2_SUBSTITUTE_UNSET_EMPTY)      == PCRE2_SUBSTITUTE_UNSET_EMPTY)      { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_SUBSTITUTE_UNSET_EMPTY"); } \
      } else {                                                          \
        if ((pcre2Optioni & PCRE2_ANCHORED)            == PCRE2_ANCHORED)            { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_ANCHORED"); } \
        if ((pcre2Optioni & PCRE2_ALLOW_EMPTY_CLASS)   == PCRE2_ALLOW_EMPTY_CLASS)   { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_ALLOW_EMPTY_CLASS"); } \
        if ((pcre2Optioni & PCRE2_ALT_BSUX)            == PCRE2_ALT_BSUX)            { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_ALT_BSUX"); } \
        if ((pcre2Optioni & PCRE2_ALT_CIRCUMFLEX)      == PCRE2_ALT_CIRCUMFLEX)      { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_ALT_CIRCUMFLEX"); } \
        if ((pcre2Optioni & PCRE2_ALT_VERBNAMES)       == PCRE2_ALT_VERBNAMES)       { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_ALT_VERBNAMES"); } \
        if ((pcre2Optioni & PCRE2_AUTO_CALLOUT)        == PCRE2_AUTO_CALLOUT)        { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_AUTO_CALLOUT"); } \
        if ((pcre2Optioni & PCRE2_CASELESS)            == PCRE2_CASELESS)            { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_CASELESS"); } \
        if ((pcre2Optioni & PCRE2_DOLLAR_ENDONLY)      == PCRE2_DOLLAR_ENDONLY)      { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_DOLLAR_ENDONLY"); } \
        if ((pcre2Optioni & PCRE2_DOTALL)              == PCRE2_DOTALL)              { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_DOTALL"); } \
        if ((pcre2Optioni & PCRE2_DUPNAMES)            == PCRE2_DUPNAMES)            { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_DUPNAMES"); } \
        if ((pcre2Optioni & PCRE2_EXTENDED)            == PCRE2_EXTENDED)            { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_EXTENDED"); } \
        if ((pcre2Optioni & PCRE2_FIRSTLINE)           == PCRE2_FIRSTLINE)           { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_FIRSTLINE"); } \
        if ((pcre2Optioni & PCRE2_MATCH_UNSET_BACKREF) == PCRE2_MATCH_UNSET_BACKREF) { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_MATCH_UNSET_BACKREF"); } \
        if ((pcre2Optioni & PCRE2_MULTILINE)           == PCRE2_MULTILINE)           { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_MULTILINE"); } \
        if ((pcre2Optioni & PCRE2_NEVER_BACKSLASH_C)   == PCRE2_NEVER_BACKSLASH_C)   { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_NEVER_BACKSLASH_C"); } \
        if ((pcre2Optioni & PCRE2_NEVER_UCP)           == PCRE2_NEVER_UCP)           { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_NEVER_UCP"); } \
        if ((pcre2Optioni & PCRE2_NEVER_UTF)           == PCRE2_NEVER_UTF)           { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_NEVER_UTF"); } \
        if ((pcre2Optioni & PCRE2_NO_AUTO_CAPTURE)     == PCRE2_NO_AUTO_CAPTURE)     { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_NO_AUTO_CAPTURE"); } \
        if ((pcre2Optioni & PCRE2_NO_AUTO_POSSESS)     == PCRE2_NO_AUTO_POSSESS)     { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_NO_AUTO_POSSESS"); } \
        if ((pcre2Optioni & PCRE2_NO_DOTSTAR_ANCHOR)   == PCRE2_NO_DOTSTAR_ANCHOR)   { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_NO_DOTSTAR_ANCHOR"); } \
        if ((pcre2Optioni & PCRE2_NO_START_OPTIMIZE)   == PCRE2_NO_START_OPTIMIZE)   { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_NO_START_OPTIMIZE"); } \
        if ((pcre2Optioni & PCRE2_NO_UTF_CHECK)        == PCRE2_NO_UTF_CHECK)        { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_NO_UTF_CHECK"); } \
        if ((pcre2Optioni & PCRE2_UCP)                 == PCRE2_UCP)                 { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_UCP"); } \
        if ((pcre2Optioni & PCRE2_UNGREEDY)            == PCRE2_UNGREEDY)            { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_UNGREEDY"); } \
        if ((pcre2Optioni & PCRE2_USE_OFFSET_LIMIT)    == PCRE2_USE_OFFSET_LIMIT)    { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_USE_OFFSET_LIMIT"); } \
        if ((pcre2Optioni & PCRE2_UTF)                 == PCRE2_UTF)                 { GENERICLOGGER_TRACE(_genericLoggerp, "PCRE2_UTF"); } \
      }                                                                 \
      if (_marpaESLIF_stringGenerator.okb) {                            \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, whats);    \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, _marpaESLIF_stringGenerator.s); \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");     \
      }                                                                 \
      if (_marpaESLIF_stringGenerator.s != NULL) {                      \
        free(_marpaESLIF_stringGenerator.s);                            \
      }                                                                 \
      GENERICLOGGER_FREE(_genericLoggerp);                              \
    }                                                                   \
  } while (0);

/* This can look overkill but marpaESLIFValueResult free is configured    */
/* via a generic callback function pointer freeCallbackp, that compiler   */
/* will access using a jump. We can avoid this jump in the case of        */
/* marpaESLIFValueResult that have set our internal free function,        */
/* provided it has been inlined, which is very likely because it is small */
#define MARPAESLIFVALUERESULT_FREE(marpaESLIFValueResultp, freeCallbackp, freeUserDatavp) (freeCallbackp == _marpaESLIF_generic_freeCallbackv) ? _marpaESLIF_generic_freeCallback_inlinev(freeUserDatavp, marpaESLIFValueResultp) : freeCallbackp(freeUserDatavp, marpaESLIFValueResultp)

typedef short (*_marpaESLIFRecognizer_valueResultCallback_t)(void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp);
typedef struct marpaESLIF_concat_valueResultContext {
  void                         *userDatavp;
  marpaESLIFValue_t            *marpaESLIFValuep;
  short                         stringb;
  short                         jsonb;
  short                         jsonfb;
} marpaESLIF_concat_valueResultContext_t;

static const char *GENERICSTACKITEMTYPE_NA_STRING                = "NA";
static const char *GENERICSTACKITEMTYPE_CHAR_STRING              = "CHAR";
static const char *GENERICSTACKITEMTYPE_SHORT_STRING             = "SHORT";
static const char *GENERICSTACKITEMTYPE_INT_STRING               = "INT";
static const char *GENERICSTACKITEMTYPE_LONG_STRING              = "LONG";
static const char *GENERICSTACKITEMTYPE_FLOAT_STRING             = "FLOAT";
static const char *GENERICSTACKITEMTYPE_DOUBLE_STRING            = "DOUBLE";
static const char *GENERICSTACKITEMTYPE_PTR_STRING               = "PTR";
static const char *GENERICSTACKITEMTYPE_ARRAY_STRING             = "ARRAY";
static const char *GENERICSTACKITEMTYPE_CUSTOM_STRING            = "CUSTOM";
static const char *GENERICSTACKITEMTYPE_LONG_DOUBLE_STRING       = "LONG_DOUBLE";
static const char *GENERICSTACKITEMTYPE_UNKNOWN_STRING           = "UNKNOWN";

static const char *MARPAESLIF_VALUE_TYPE_UNDEF_STRING             = "UNDEF";
static const char *MARPAESLIF_VALUE_TYPE_CHAR_STRING              = "CHAR";
static const char *MARPAESLIF_VALUE_TYPE_SHORT_STRING             = "SHORT";
static const char *MARPAESLIF_VALUE_TYPE_INT_STRING               = "INT";
static const char *MARPAESLIF_VALUE_TYPE_LONG_STRING              = "LONG";
static const char *MARPAESLIF_VALUE_TYPE_FLOAT_STRING             = "FLOAT";
static const char *MARPAESLIF_VALUE_TYPE_DOUBLE_STRING            = "DOUBLE";
static const char *MARPAESLIF_VALUE_TYPE_PTR_STRING               = "PTR";
static const char *MARPAESLIF_VALUE_TYPE_ARRAY_STRING             = "ARRAY";
static const char *MARPAESLIF_VALUE_TYPE_BOOL_STRING              = "BOOL";
static const char *MARPAESLIF_VALUE_TYPE_STRING_STRING            = "STRING";
static const char *MARPAESLIF_VALUE_TYPE_ROW_STRING               = "ROW";
static const char *MARPAESLIF_VALUE_TYPE_TABLE_STRING             = "TABLE";
static const char *MARPAESLIF_VALUE_TYPE_LONG_DOUBLE_STRING       = "LONG_DOUBLE";
#ifdef MARPAESLIF_HAVE_LONG_LONG
static const char *MARPAESLIF_VALUE_TYPE_LONG_LONG_STRING         = "LONG_LONG";
#endif
static const char *MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH_STRING = "OFFSET_AND_LENGTH";
static const char *MARPAESLIF_VALUE_TYPE_UNKNOWN_STRING           = "UNKNOWN";

static const size_t copyl    = 6; /* strlen("::copy"); */
static const size_t convertl = 9; /* strlen("::convert"); */

static const char *MARPAESLIF_TERMINAL__EOF   = ":eof";
static const char *MARPAESLIF_TERMINAL__EOL   = ":eol";
static const char *MARPAESLIF_TERMINAL__SOL   = ":sol";
static const char *MARPAESLIF_TERMINAL__EMPTY = ":empty";

static marpaESLIFRecognizer_t invalidFakeMarpaESLIFRecognizer;

/* For reset of values in the stack, it is okay to not care about the union -; */
static const marpaESLIFValueResult_t marpaESLIFValueResultUndef = {
  NULL,                       /* contextp */
  NULL,                       /* representationp */
  MARPAESLIF_VALUE_TYPE_UNDEF /* type */
  /* Here is the union */
};

/* In C89 only the first member of a union can be initialized, this is what we need */
static const marpaESLIFValueResult_t marpaESLIFValueResultLeftBracket = {
  NULL,                       /* contextp */
  NULL,                       /* representationp */
  MARPAESLIF_VALUE_TYPE_CHAR, /* type */
  {
   '{'                        /* u.c */
  }
};
static const marpaESLIFValueResult_t marpaESLIFValueResultRightBracket = {
  NULL,                       /* contextp */
  NULL,                       /* representationp */
  MARPAESLIF_VALUE_TYPE_CHAR, /* type */
  {
   '}'                        /* u.c */
  }
};
static const marpaESLIFValueResult_t marpaESLIFValueResultLeftSquare = {
  NULL,                       /* contextp */
  NULL,                       /* representationp */
  MARPAESLIF_VALUE_TYPE_CHAR, /* type */
  {
   '['                        /* u.c */
  }
};

/* In C89 only the first member of a union can be initialized, this is what we need */
static const marpaESLIFValueResult_t marpaESLIFValueResultRightSquare = {
  NULL,                       /* contextp */
  NULL,                       /* representationp */
  MARPAESLIF_VALUE_TYPE_CHAR, /* type */
  {
   ']'                        /* u.c */
  }
};
/* In C89 only the first member of a union can be initialized, this is what we need */
static const marpaESLIFValueResult_t marpaESLIFValueResultComma = {
  NULL,                       /* contextp */
  NULL,                       /* representationp */
  MARPAESLIF_VALUE_TYPE_CHAR, /* type */
  {
   ','                        /* u.c */
  }
};
/* In C89 only the first member of a union can be initialized, this is what we need */
static const marpaESLIFValueResult_t marpaESLIFValueResultColon = {
  NULL,                       /* contextp */
  NULL,                       /* representationp */
  MARPAESLIF_VALUE_TYPE_CHAR, /* type */
  {
   ':'                        /* u.c */
  }
};

/* Internal marker for _marpaESLIFRecognizer_concat_valueResultCallbackb */
static char _marpaESLIFValueResultNextValueResultMustDisplayAsJsonString = '\0';
static const marpaESLIFValueResult_t marpaESLIFValueResultNextValueResultMustDisplayAsJsonString = {
   (void *) &_marpaESLIFValueResultNextValueResultMustDisplayAsJsonString,                        /* contextp */
   NULL,                        /* representationp */
   MARPAESLIF_VALUE_TYPE_UNDEF, /* type */
};

/* Prefilled string generator, to gain also few instructions that are always the same */
static const marpaESLIF_stringGenerator_t  marpaESLIF_stringGeneratorTemplate = {
  NULL, /* marpaESLIFp */
  NULL, /* s */
  0,    /* l */
  0,    /* okb */
  0     /* allocl */
};

typedef struct marpaESLIF_pcre2_callout_enumerate_context {
  marpaESLIF_t         *marpaESLIFp;
  char                 *asciishows;
  size_t                asciishowl;
  short                 calloutb;
} marpaESLIF_pcre2_callout_enumerate_context_t;

/* Generic importer signature */
typedef short (*marpaESLIFGenericImport_t)(void *namespacep, void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short haveUndefb);

/* Precomputed representation and length of the first 256 UTF-8 characters */
typedef struct marpaESLIF_utf8_2_bytes_max {
  size_t lengthl;
  char   s[2];   /* At most 2 bytes for the 256 characters */
} marpaESLIF_utf8_2_bytes_max_t;

marpaESLIF_utf8_2_bytes_max_t utf8_2_bytes_max_arrayp[256] = {
  { 1, "\x00" },
  { 1, "\x01" },
  { 1, "\x02" },
  { 1, "\x03" },
  { 1, "\x04" },
  { 1, "\x05" },
  { 1, "\x06" },
  { 1, "\x07" },
  { 1, "\x08" },
  { 1, "\x09" },
  { 1, "\x0A" },
  { 1, "\x0B" },
  { 1, "\x0C" },
  { 1, "\x0D" },
  { 1, "\x0E" },
  { 1, "\x0F" },

  { 1, "\x10" },
  { 1, "\x11" },
  { 1, "\x12" },
  { 1, "\x13" },
  { 1, "\x14" },
  { 1, "\x15" },
  { 1, "\x16" },
  { 1, "\x17" },
  { 1, "\x18" },
  { 1, "\x19" },
  { 1, "\x1A" },
  { 1, "\x1B" },
  { 1, "\x1C" },
  { 1, "\x1D" },
  { 1, "\x1E" },
  { 1, "\x1F" },

  { 1, "\x20" },
  { 1, "\x21" },
  { 1, "\x22" },
  { 1, "\x23" },
  { 1, "\x24" },
  { 1, "\x25" },
  { 1, "\x26" },
  { 1, "\x27" },
  { 1, "\x28" },
  { 1, "\x29" },
  { 1, "\x2A" },
  { 1, "\x2B" },
  { 1, "\x2C" },
  { 1, "\x2D" },
  { 1, "\x2E" },
  { 1, "\x2F" },

  { 1, "\x30" },
  { 1, "\x31" },
  { 1, "\x32" },
  { 1, "\x33" },
  { 1, "\x34" },
  { 1, "\x35" },
  { 1, "\x36" },
  { 1, "\x37" },
  { 1, "\x38" },
  { 1, "\x39" },
  { 1, "\x3A" },
  { 1, "\x3B" },
  { 1, "\x3C" },
  { 1, "\x3D" },
  { 1, "\x3E" },
  { 1, "\x3F" },

  { 1, "\x40" },
  { 1, "\x41" },
  { 1, "\x42" },
  { 1, "\x43" },
  { 1, "\x44" },
  { 1, "\x45" },
  { 1, "\x46" },
  { 1, "\x47" },
  { 1, "\x48" },
  { 1, "\x49" },
  { 1, "\x4A" },
  { 1, "\x4B" },
  { 1, "\x4C" },
  { 1, "\x4D" },
  { 1, "\x4E" },
  { 1, "\x4F" },

  { 1, "\x50" },
  { 1, "\x51" },
  { 1, "\x52" },
  { 1, "\x53" },
  { 1, "\x54" },
  { 1, "\x55" },
  { 1, "\x56" },
  { 1, "\x57" },
  { 1, "\x58" },
  { 1, "\x59" },
  { 1, "\x5A" },
  { 1, "\x5B" },
  { 1, "\x5C" },
  { 1, "\x5D" },
  { 1, "\x5E" },
  { 1, "\x5F" },

  { 1, "\x60" },
  { 1, "\x61" },
  { 1, "\x62" },
  { 1, "\x63" },
  { 1, "\x64" },
  { 1, "\x65" },
  { 1, "\x66" },
  { 1, "\x67" },
  { 1, "\x68" },
  { 1, "\x69" },
  { 1, "\x6A" },
  { 1, "\x6B" },
  { 1, "\x6C" },
  { 1, "\x6D" },
  { 1, "\x6E" },
  { 1, "\x6F" },

  { 1, "\x70" },
  { 1, "\x71" },
  { 1, "\x72" },
  { 1, "\x73" },
  { 1, "\x74" },
  { 1, "\x75" },
  { 1, "\x76" },
  { 1, "\x77" },
  { 1, "\x78" },
  { 1, "\x79" },
  { 1, "\x7A" },
  { 1, "\x7B" },
  { 1, "\x7C" },
  { 1, "\x7D" },
  { 1, "\x7E" },
  { 1, "\x7F" },

  { 2, "\xC2\x80" },
  { 2, "\xC2\x81" },
  { 2, "\xC2\x82" },
  { 2, "\xC2\x83" },
  { 2, "\xC2\x84" },
  { 2, "\xC2\x85" },
  { 2, "\xC2\x86" },
  { 2, "\xC2\x87" },
  { 2, "\xC2\x88" },
  { 2, "\xC2\x89" },
  { 2, "\xC2\x8A" },
  { 2, "\xC2\x8B" },
  { 2, "\xC2\x8C" },
  { 2, "\xC2\x8D" },
  { 2, "\xC2\x8E" },
  { 2, "\xC2\x8F" },

  { 2, "\xC2\x90" },
  { 2, "\xC2\x91" },
  { 2, "\xC2\x92" },
  { 2, "\xC2\x93" },
  { 2, "\xC2\x94" },
  { 2, "\xC2\x95" },
  { 2, "\xC2\x96" },
  { 2, "\xC2\x97" },
  { 2, "\xC2\x98" },
  { 2, "\xC2\x99" },
  { 2, "\xC2\x9A" },
  { 2, "\xC2\x9B" },
  { 2, "\xC2\x9C" },
  { 2, "\xC2\x9D" },
  { 2, "\xC2\x9E" },
  { 2, "\xC2\x9F" },

  { 2, "\xC2\xA0" },
  { 2, "\xC2\xA1" },
  { 2, "\xC2\xA2" },
  { 2, "\xC2\xA3" },
  { 2, "\xC2\xA4" },
  { 2, "\xC2\xA5" },
  { 2, "\xC2\xA6" },
  { 2, "\xC2\xA7" },
  { 2, "\xC2\xA8" },
  { 2, "\xC2\xA9" },
  { 2, "\xC2\xAA" },
  { 2, "\xC2\xAB" },
  { 2, "\xC2\xAC" },
  { 2, "\xC2\xAD" },
  { 2, "\xC2\xAE" },
  { 2, "\xC2\xAF" },

  { 2, "\xC2\xB0" },
  { 2, "\xC2\xB1" },
  { 2, "\xC2\xB2" },
  { 2, "\xC2\xB3" },
  { 2, "\xC2\xB4" },
  { 2, "\xC2\xB5" },
  { 2, "\xC2\xB6" },
  { 2, "\xC2\xB7" },
  { 2, "\xC2\xB8" },
  { 2, "\xC2\xB9" },
  { 2, "\xC2\xBA" },
  { 2, "\xC2\xBB" },
  { 2, "\xC2\xBC" },
  { 2, "\xC2\xBD" },
  { 2, "\xC2\xBE" },
  { 2, "\xC2\xBF" },

  { 2, "\xC3\x80" },
  { 2, "\xC3\x81" },
  { 2, "\xC3\x82" },
  { 2, "\xC3\x83" },
  { 2, "\xC3\x84" },
  { 2, "\xC3\x85" },
  { 2, "\xC3\x86" },
  { 2, "\xC3\x87" },
  { 2, "\xC3\x88" },
  { 2, "\xC3\x89" },
  { 2, "\xC3\x8A" },
  { 2, "\xC3\x8B" },
  { 2, "\xC3\x8C" },
  { 2, "\xC3\x8D" },
  { 2, "\xC3\x8E" },
  { 2, "\xC3\x8F" },

  { 2, "\xC3\x90" },
  { 2, "\xC3\x91" },
  { 2, "\xC3\x92" },
  { 2, "\xC3\x93" },
  { 2, "\xC3\x94" },
  { 2, "\xC3\x95" },
  { 2, "\xC3\x96" },
  { 2, "\xC3\x97" },
  { 2, "\xC3\x98" },
  { 2, "\xC3\x99" },
  { 2, "\xC3\x9A" },
  { 2, "\xC3\x9B" },
  { 2, "\xC3\x9C" },
  { 2, "\xC3\x9D" },
  { 2, "\xC3\x9E" },
  { 2, "\xC3\x9F" },

  { 2, "\xC3\xA0" },
  { 2, "\xC3\xA1" },
  { 2, "\xC3\xA2" },
  { 2, "\xC3\xA3" },
  { 2, "\xC3\xA4" },
  { 2, "\xC3\xA5" },
  { 2, "\xC3\xA6" },
  { 2, "\xC3\xA7" },
  { 2, "\xC3\xA8" },
  { 2, "\xC3\xA9" },
  { 2, "\xC3\xAA" },
  { 2, "\xC3\xAB" },
  { 2, "\xC3\xAC" },
  { 2, "\xC3\xAD" },
  { 2, "\xC3\xAE" },
  { 2, "\xC3\xAF" },

  { 2, "\xC3\xB0" },
  { 2, "\xC3\xB1" },
  { 2, "\xC3\xB2" },
  { 2, "\xC3\xB3" },
  { 2, "\xC3\xB4" },
  { 2, "\xC3\xB5" },
  { 2, "\xC3\xB6" },
  { 2, "\xC3\xB7" },
  { 2, "\xC3\xB8" },
  { 2, "\xC3\xB9" },
  { 2, "\xC3\xBA" },
  { 2, "\xC3\xBB" },
  { 2, "\xC3\xBC" },
  { 2, "\xC3\xBD" },
  { 2, "\xC3\xBE" },
  { 2, "\xC3\xBF" }
};

static const char *MARPAESLIF_EMPTY_STRING = "";
static const char *MARPAESLIF_UTF8_STRING = "UTF-8";
static const char *MARPAESLIF_UNKNOWN_STRING = "???";
static const char *MARPAESLIF__START = ":start";

/* Please note that EVERY _marpaESLIFRecognizer_xxx() method is logging at start and at return */

static inline marpaESLIF_t          *_marpaESLIF_newp(marpaESLIFOption_t *marpaESLIFOptionp);
static inline marpaESLIF_string_t   *_marpaESLIF_string_newp(marpaESLIF_t *marpaESLIFp, char *encodingasciis, char *bytep, size_t bytel);
static inline marpaESLIF_string_t   *_marpaESLIF_string_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIF_string_t *stringp);
static inline void                   _marpaESLIF_string_freev(marpaESLIF_string_t *stringp, short onStstackb);
static inline short                  _marpaESLIF_string_utf8_eqb(marpaESLIF_string_t *string1p, marpaESLIF_string_t *string2p);
static inline short                  _marpaESLIF_string_eqb(marpaESLIF_string_t *string1p, marpaESLIF_string_t *string2p);
static inline marpaESLIF_string_t   *_marpaESLIF_string2utf8p(marpaESLIF_t *marpaESLIFp, marpaESLIF_string_t *stringp, short tconvsilentb);
static inline marpaESLIF_terminal_t *_marpaESLIF_terminal_newp(marpaESLIF_t *marpaESLIFp, marpaWrapperGrammar_t *marpaWrapperGrammarp, int eventSeti, char *descEncodings, char *descs, size_t descl, marpaESLIF_terminal_type_t type, char *modifiers, char *utf8s, size_t utf8l, char *testFullMatchs, char *testPartialMatchs, short pseudob, short characterClassb, marpaESLIF_terminal_type_t wantType, short substitutionb);
static inline void                   _marpaESLIF_terminal_freev(marpaESLIF_terminal_t *terminalp);
static marpaESLIF_string_t          *_marpaESLIF_terminal_add_substitution_desc_to_terminal_descp(marpaESLIF_t *marpaESLIFp, marpaESLIF_terminal_t *terminalp, marpaESLIF_terminal_t *substitutionTerminalp);

static inline marpaESLIF_meta_t     *_marpaESLIF_meta_newp(marpaESLIF_t *marpaESLIFp, marpaWrapperGrammar_t *marpaWrapperGrammarp, int eventSeti, char *asciinames, char *descEncodings, char *descs, size_t descl, short lazyb);
static inline void                   _marpaESLIF_meta_freev(marpaESLIF_meta_t *metap);

static inline marpaESLIF_grammar_bootstrap_t *_marpaESLIF_grammar_bootstrap_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammarBootstrapp, marpaESLIF_grammar_bootstrap_t *grammarOrigp);
static inline marpaESLIF_grammar_bootstrap_t *_marpaESLIF_grammar_bootstrap_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammarBootstrapp, marpaWrapperGrammarOption_t *marpaWrapperGrammarOptionp, int leveli, int symbolStackSizei, int ruleStackSizei, marpaESLIF_string_t *descp);
static inline short                  _marpaESLIF_grammar_initb(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, int leveli, marpaESLIFGrammar_t *marpaESLIFGrammarp);
static inline marpaESLIF_grammar_t  *_marpaESLIF_grammar_newp(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaWrapperGrammarOption_t *marpaWrapperGrammarOptionp, int leveli, char *descEncodings, char *descs, size_t descl, marpaESLIF_action_t *defaultSymbolActionp, marpaESLIF_action_t *defaultRuleActionp, marpaESLIF_action_t *defaultEventActionp, marpaESLIF_action_t *defaultRegexActionp, char *defaultEncodings, char *fallbackEncodings);
static inline void                   _marpaESLIF_grammar_bootstrap_freev(marpaESLIF_grammar_bootstrap_t *grammarp);
static inline void                   _marpaESLIF_grammar_freev(marpaESLIF_grammar_t *grammarp);

static inline void                   _marpaESLIF_ruleStack_freev(genericStack_t *ruleStackp);
static inline void                   _marpaESLIFRecognizer_lexemeStack_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline void                   _marpaESLIFRecognizer_lexemeStack_resetv(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_lexemeStack_i_p_and_sizeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, int i, char **pp, size_t *sizelp);
static inline short                  _marpaESLIFRecognizer_lexemeStack_i_setb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, int i, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline short                  _marpaESLIFRecognizer_internalStack_i_setb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, genericStack_t *valueResultStackp, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp, short forgetb, marpaESLIFValueResult_t *marpaESLIFValueResultOrigp) MARPAESLIF_FUNC_ATTRIBUTE_FLATTEN;
static inline marpaESLIFValueResult_t *_marpaESLIFRecognizer_lexemeStack_i_getp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, int i);
static inline const char            *_marpaESLIF_genericStack_i_types(genericStack_t *stackp, int i);
static inline const char            *_marpaESLIF_value_types(int typei);

static inline marpaESLIF_rule_t     *_marpaESLIF_rule_newp(marpaESLIF_t *marpaESLIFp, genericStack_t *symbolStackp, int leveli, marpaWrapperGrammar_t *marpaWrapperGrammarStartp, char *descEncodings, char *descs, size_t descl, int lhsi, size_t nrhsl, int *rhsip, int exceptioni, int ranki, short nullRanksHighb, short sequenceb, int minimumi, int separatori, short properb, marpaESLIF_action_t *actionp, short hideseparatorb, short *skipbp, marpaESLIF_lua_functiondecl_t *declp, marpaESLIF_lua_functioncall_t **callpp, marpaESLIF_lua_functioncall_t *separatorcallp);
static inline void                   _marpaESLIF_rule_freev(marpaESLIF_rule_t *rulep);

static inline marpaESLIF_symbol_t   *_marpaESLIF_symbol_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp);
static inline void                   _marpaESLIF_symbol_freev(marpaESLIF_symbol_t *symbolp);

static inline void                   _marpaESLIF_symbolStack_freev(genericStack_t *symbolStackp);

static inline marpaESLIF_grammar_t  *_marpaESLIF_bootstrap_grammar_L0p(marpaESLIFGrammar_t *marpaESLIFGrammarp, short withLazyb);
static inline marpaESLIF_grammar_t  *_marpaESLIF_bootstrap_grammar_G1p(marpaESLIFGrammar_t *marpaESLIFGrammarp, short withLazyb);
static inline marpaESLIF_grammar_t  *_marpaESLIF_bootstrap_grammarp(marpaESLIFGrammar_t *marpaESLIFGrammarp,
                                                                    int leveli,
                                                                    char *descEndocings,
                                                                    char  *descs,
                                                                    size_t descl,
                                                                    short warningIsErrorb,
                                                                    short warningIsIgnoredb,
                                                                    short autorankb,
                                                                    int bootstrap_grammar_terminali, bootstrap_grammar_terminal_t *bootstrap_grammar_terminalp,
                                                                    int bootstrap_grammar_metai, bootstrap_grammar_meta_t *bootstrap_grammar_metap,
                                                                    int bootstrap_grammar_rulei, bootstrap_grammar_rule_t *bootstrap_grammar_rulep,
                                                                    int bootstrap_grammar_lazy_rulei, bootstrap_grammar_rule_t *bootstrap_grammar_lazy_rulep,
                                                                    marpaESLIF_action_t *defaultSymbolActionp,
                                                                    marpaESLIF_action_t *defaultRuleActionp,
                                                                    marpaESLIF_action_t *defaultEventActionp,
                                                                    marpaESLIF_action_t *defaultRegexActionp,
                                                                    char *defaultEncodings,
                                                                    char *fallbackEncodings);
static inline short                  _marpaESLIF_numberb(marpaESLIF_t *marpaESLIFp, char *s, size_t sizel, marpaESLIFValueResult_t *marpaESLIFValueResultp, short *confidencebp);
static inline short                  _marpaESLIFGrammar_validateb(marpaESLIFGrammar_t *marpaESLIFGrammarp, short ignoreLazyb, char *forcedStartSymbols, int forcedStartSymbolLeveli);
static inline marpaESLIF_internal_event_action_t _eventActionsToActione(char *actions);
static inline marpaESLIF_internal_rule_action_t _ruleActionpToActione(marpaESLIFAction_t *actionp);
static inline marpaESLIF_internal_symbol_action_t _symbolActionpToActione(marpaESLIFAction_t *actionp);
static inline short                  _marpaESLIFGrammar_haveLexemeb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int grammari, marpaWrapperGrammar_t *marpaWrapperGrammarp, short *haveLexemebp);
static inline short                  _marpaESLIFGrammar_bootstrap_transferb(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp);
static inline marpaESLIFGrammar_bootstrap_t   *_marpaESLIFGrammar_bootstrap_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammarOrigp);
static inline marpaESLIFGrammar_bootstrap_t   *_marpaESLIFGrammar_bootstrap_newp(marpaESLIF_t *marpaESLIFp);
static inline marpaESLIFGrammar_t   *_marpaESLIFGrammar_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammarOption_t *marpaESLIFGrammarOptionp, marpaESLIFGrammar_Lshare_t *Lsharep, short bootstrapb, short rememberGrammarUtf8b, char *forcedStartSymbols, int forcedStartSymbolLeveli, marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammar_bootstrapOrigp);

static inline short                  _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_stream_t *marpaESLIF_streamp, marpaESLIF_terminal_t *terminalp, char *inputs, size_t inputl, short eofb, marpaESLIF_matcher_value_t *rcip, marpaESLIFValueResult_t *marpaESLIFValueResultp, size_t *matchedLengthlp);
static inline short                  _marpaESLIFRecognizer_terminal_matcher_setb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_stream_t *marpaESLIF_streamp, short allocb, marpaESLIF_matcher_value_t rci, marpaESLIF_matcher_value_t *rcip, marpaESLIFValueResult_t *marpaESLIFValueResultp, char *matchedp, size_t matchedLengthl, size_t *matchedLengthlp, short substitutionb, PCRE2_UCHAR **outputbufferpp, PCRE2_SIZE outputbufferl);
static inline short                  _marpaESLIFRecognizer_meta_matcherb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_symbol_t *symbolp, marpaESLIF_matcher_value_t *rcip, marpaESLIFValueResult_t *marpaESLIFValueResultp, short *isExhaustedbp, int maxStartCompletionsi, size_t *lastSizeBeforeCompletionlp, int *numberOfStartCompletionsip, size_t *matchedLengthlp);
static inline marpaESLIF_grammar_t  *_marpaESLIFRecognizer_meta_subGrammarp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_symbol_t *symbolp);
static inline short                  _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_stream_t *marpaESLIF_streamp, marpaESLIF_symbol_t *symbolp, marpaESLIF_matcher_value_t *rcip, marpaESLIFValueResult_t *marpaESLIFValueResultp, int maxStartCompletionsi, size_t *lastSizeBeforeCompletionlp, int *numberOfStartCompletionsip, size_t *matchedLengthlp);

static const  char                  *_marpaESLIF_utf82printableascii_defaultp = "<!NOT TRANSLATED!>";
#ifndef MARPAESLIF_NTRACE
static        void                   _marpaESLIF_tconvTraceCallback(void *userDatavp, const char *msgs);
#endif

static inline char                  *_marpaESLIF_charconvb(marpaESLIF_t *marpaESLIFp, char *toEncodings, char *fromEncodings, char *srcs, size_t srcl, size_t *dstlp, char **fromEncodingsp, tconv_t *tconvpp, short eofb, char **byteleftsp, size_t *byteleftlp, size_t *byteleftalloclp, short tconvsilentb, char *defaultEncodings, char *fallbackEncodings);

static inline char                  *_marpaESLIF_utf82printableascii_newp(marpaESLIF_t *marpaESLIFp, char *descs, size_t descl);
static inline void                   _marpaESLIF_utf82printableascii_freev(char *utf82printableasciip);
static        short                  _marpaESLIFReader_grammarReader(void *userDatavp, char **inputsp, size_t *inputlp, short *eofbp, short *characterStreambp, char **encodingsp, size_t *encodinglp, marpaESLIFReaderDispose_t *disposeCallbackpp);
static inline short                  _marpaESLIFRecognizer_isZeroLengthLexemeExpectedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isZeroLengthLexemeExpectedbp);
static inline short                  _marpaESLIFRecognizer_isDiscardExpectedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isDiscardExpectedbp, size_t *fastDiscardlp, marpaESLIF_symbol_t **fastDiscardSymbolpp, marpaESLIFValueResult_t *marpaESLIFValueResultArrayp);
static inline size_t                _marpaESLIFRecognizer_expectedSymbols_yieldb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short pristineb, size_t *iteratorlp, size_t nTerminall, marpaESLIF_symbol_t **symbolArraypp, marpaESLIF_symbol_t **symbolpp);
static inline short                  _marpaESLIFRecognizer_resume_oneb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, genericStack_t *alternativeStackSymbolp, marpaESLIF_stream_t *marpaESLIF_streamp, short initialEventsb, short *canContinuebp, short *isExhaustedbp);
static inline short                  _marpaESLIFRecognizer_checkStartCompletionb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t lengthl);
static inline short                  _marpaESLIFRecognizer_isStartCompleteb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isStartCompletebp);
static inline short                  _marpaESLIFRecognizer_resumeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t deltaLengthl, short *continuebp, short *exhaustedbp);
static inline short                  __marpaESLIFRecognizer_resumeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t deltaLengthl, short initialEventsb, short *continuebp, short *isExhaustedbp);
static inline marpaESLIF_grammar_bootstrap_t  *_marpaESLIF_grammar_bootstrap_findp(marpaESLIF_t *marpaESLIFp, genericStack_t *grammarStackp, int leveli, marpaESLIF_string_t *descp);
static inline marpaESLIF_grammar_t  *_marpaESLIF_grammar_findp(marpaESLIF_t *marpaESLIFp, genericStack_t *grammarStackp, int leveli, marpaESLIF_string_t *descp);
static inline marpaESLIF_grammar_t  *_marpaESLIFGrammar_grammar_findp(marpaESLIFGrammar_t *marpaESLIFGrammarp, int leveli, marpaESLIF_string_t *descp);
static inline marpaESLIF_rule_t     *_marpaESLIF_rule_findp(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, int rulei);
static inline marpaESLIF_symbol_t   *_marpaESLIF_symbol_findp(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, char *asciis, int symboli, int *symbolip, short silentb, short onlyLhsb, short onlyRhsb, marpaESLIF_symbol_type_t type);
static inline short                  _marpaESLIFRecognizer_fast_alternativeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_alternative_t *alternativep);
static inline short                  _marpaESLIFRecognizer_alternative_completeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t lengthl);
static inline short                  __marpaESLIFRecognizer_name_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, short *matchbp);
static inline short                  _marpaESLIFRecognizer_name_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, short *matchbp);
static inline short                  _marpaESLIFRecognizer_name_last_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, char **trysp, size_t *trylp);
static inline short                  _marpaESLIFRecognizer_discard_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, short *matchbp);

static inline void                   _marpaESLIFRecognizer_alternativeStack_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, genericStack_t *alternativeStackSymbolp);
static inline marpaESLIF_alternative_t *_marpaESLIFRecognizer_alternativeStack_getp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, genericStack_t *alternativeStackSymbolp, int indicei);
static inline short                  _marpaESLIFRecognizer_alternative_and_valueb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_alternative_t *alternativep, int valuei);
static inline short                  _marpaESLIFRecognizer_push_eventb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFEventType_t type, marpaESLIF_symbol_t *symbolp, char *events, char *discardp, size_t discardl, marpaESLIF_internal_event_action_t event_actione);
static inline short                  _marpaESLIFRecognizer_last_symbolDatab(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *lexemes, char **bytesp, size_t *bytelp, marpaESLIF_symbol_data_t **symbolDatapp, short forPauseb, marpaESLIF_symbol_type_t type, short onlyLhsb, short onlyRhsb);
static inline short                  _marpaESLIFRecognizer_discard_lastb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **bytesp, size_t *bytelp);
static inline short                  _marpaESLIFRecognizer_set_symbolDatab(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, char *xsbytes, size_t bytel, marpaESLIF_symbol_data_t **symbolDatapp);
static inline short                  _marpaESLIFRecognizer_set_pauseb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, char *bytes, size_t bytel);
static inline short                  _marpaESLIFRecognizer_set_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, char *bytes, size_t bytel);
static inline short                  _marpaESLIFRecognizer_push_grammar_eventsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline void                   _marpaESLIFRecognizer_clear_grammar_eventsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline void                   _marpaESLIFRecognizer_clear_all_eventsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_value_validb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, void *userDatavp, _marpaESLIFRecognizer_valueResultCallback_t callbackp);
static inline short                  __marpaESLIFRecognizer_value_validb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static        short                  _marpaESLIFRecognizer_concat_valueResultCallbackb(void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp);

static inline void                   _marpaESLIFRecognizer_sort_eventsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline void                   _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp) MARPAESLIF_FUNC_ATTRIBUTE_FLATTEN;
static inline short                  _marpaESLIFRecognizer_stream_initb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t bufsizl, int buftriggerperci, short eofb, short utfb);
static inline void                   _marpaESLIF_stream_disposev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline marpaESLIFRecognizer_t *_marpaESLIFRecognizer_newp(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp, short discardb, short noEventb, short silentb);
static inline marpaESLIFRecognizer_t *__marpaESLIFRecognizer_newp(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp, short discardb, short noEventb, short silentb, marpaESLIFRecognizer_t *marpaESLIFRecognizerParentp, short fakeb, int maxStartCompletionsi, short utfb, short isLexemeb);
static inline short                  _marpaESLIFRecognizer_shareb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFRecognizer_t *marpaESLIFRecognizerSharedp);
static inline short                  __marpaESLIFRecognizer_shareb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFRecognizer_t *marpaESLIFRecognizerSharedp);
static inline short                  _marpaESLIFRecognizer_peekb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFRecognizer_t *marpaESLIFRecognizerPeekedp);
static inline short                  _marpaESLIFRecognizer_discardb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *discardlp);
static inline short                  __marpaESLIFRecognizer_discardb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t minl, size_t *discardlp, short appendEventb);
static inline short                  _marpaESLIFGrammar_parseb(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp, marpaESLIFValueOption_t *marpaESLIFValueOptionp, short discardb, short noEventb, short silentb, marpaESLIFRecognizer_t *marpaESLIFRecognizerParentp, short *isExhaustedbp, marpaESLIFValueResult_t *marpaESLIFValueResultp, int maxStartCompletionsi, size_t *lastSizeBeforeCompletionlp, int *numberOfStartCompletionsip, short verboseb, size_t *matchedLengthlp, short isLexemeb);
static        void                   _marpaESLIF_generateStringWithLoggerCallback(void *userDatavp, genericLoggerLevel_t logLeveli, const char *msgs);
static        void                   _marpaESLIF_generateSeparatedStringWithLoggerCallback(void *userDatavp, genericLoggerLevel_t logLeveli, const char *msgs);
static        void                   _marpaESLIF_traceLoggerCallbackv(void *userDatavp, genericLoggerLevel_t logLeveli, const char *msgs);
static        void                   _marpaESLIFRecognizer_loggerCallbackv(void *userDatavp, genericLoggerLevel_t logLeveli, const char *msgs);
static inline void                   _marpaESLIF_stringGeneratorInitv(marpaESLIF_t *marpaESLIFp, marpaESLIF_stringGenerator_t *marpaESLIF_stringGeneratorp);
static inline void                   _marpaESLIF_stringGeneratorResetv(marpaESLIF_stringGenerator_t *marpaESLIF_stringGeneratorp);
static inline void                   _marpaESLIF_stringGeneratorFreev(marpaESLIF_stringGenerator_t *marpaESLIF_stringGeneratorp, short onStackb);
static inline short                  _marpaESLIF_appendOpaqueDataToStringGenerator(marpaESLIF_stringGenerator_t *marpaESLIF_stringGeneratorp, char *p, size_t sizel);
static inline short                  _marpaESLIFRecognizer_readb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **inputsp, size_t *inputlp);
static inline short                  __marpaESLIFRecognizer_readb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_flush_charconvb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_start_charconvb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *encodings, size_t encodingl, char *srcs, size_t srcl, short eofb, char *defaultEncodings, char *fallbackEncodings);

/* All wrappers, even the Lexeme and Grammar wrappers go through these routines */
static        short                  _marpaESLIFValue_ruleCallbackWrapperb(void *userDatavp, int rulei, int arg0i, int argni, int resulti);
static inline short                  _marpaESLIFValue_ruleActionCallbackb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueRuleCallback_t *ruleCallbackpp, char *asciishows, marpaESLIF_action_t *actionp, marpaESLIF_internal_rule_action_t rule_actione);
static        short                  _marpaESLIFValue_symbolCallbackWrapperb(void *userDatavp, int symboli, int argi, int resulti);
static        short                  _marpaESLIFValue_nullingCallbackWrapperb(void *userDatavp, int symboli, int resulti);
static inline short                  _marpaESLIFValue_anySymbolCallbackWrapperb(void *userDatavp, int symboli, int argi, int resulti, short nullableb);
static inline short                  _marpaESLIFValue_symbolActionCallbackb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueSymbolCallback_t *symbolCallbackpp, short nullableb, marpaESLIFValueRuleCallback_t *ruleCallbackpp, marpaESLIF_symbol_t *symbolp);
static inline short                  _marpaESLIFRecognizer_recognizerIfActionCallbackb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *asciishows, marpaESLIF_action_t *ifActionp, marpaESLIFRecognizerIfCallback_t *ifCallbackpp);
static inline short                  _marpaESLIFRecognizer_recognizerEventActionCallbackb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_action_t *eventActionp, marpaESLIFRecognizerEventCallback_t *eventCallbackpp);
static inline short                  _marpaESLIFRecognizer_recognizerRegexActionCallbackb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *asciishows, marpaESLIF_action_t *regexActionp, marpaESLIFRecognizerRegexCallback_t *regexCallbackpp);
static inline short                  _marpaESLIFRecognizer_recognizerGeneratorActionCallbackb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *asciishows, marpaESLIF_action_t *generatorActionp, marpaESLIFRecognizerGeneratorCallback_t *generatorCallbackpp);
static inline short                  _marpaESLIFValue_eslif2hostb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, void *forcedUserDatavp, marpaESLIFValueImport_t forcedImporterp);
static inline short                  _marpaESLIFRecognizer_eslif2hostb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, void *forcedUserDatavp, marpaESLIFRecognizerImport_t forcedImporterp);
static inline short                  _marpaESLIFRecognizer_expectedTerminalsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *nTerminallp, int **symbolIdArraypp, marpaESLIF_symbol_t ***symbolArrayppp);
static inline short                  _marpaESLIF_eslif2hostb(marpaESLIF_t *marpaESLIFp, void *namespacep, marpaESLIFValueResult_t *marpaESLIFValueResultp, void *userDatavp, marpaESLIFGenericImport_t importerp, marpaESLIF_stream_t *marpaESLIF_streamp);

static inline short                  _marpaESLIFValue_valueb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline short                  __marpaESLIFValue_valueb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp);

static inline void                   _marpaESLIFGrammar_bootstrap_freev(marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammarp);
static inline void                   _marpaESLIF_grammarBootstrapStack_freev(genericStack_t *grammarStackp);
static inline void                   _marpaESLIF_grammarStack_freev(genericStack_t *grammarStackp);
static inline void                   _marpaESLIFGrammar_freev(marpaESLIFGrammar_t *marpaESLIFGrammarp, short onStackb);
static        char                  *_marpaESLIFGrammar_symbolDescriptionCallbacks(void *userDatavp, int symboli);
static        short                  _marpaESLIFGrammar_symbolOptionSetterInitb(void *userDatavp, int symboli, marpaWrapperGrammarSymbolOption_t *marpaWrapperGrammarSymbolOptionp);
static        short                  _marpaESLIFGrammar_symbolOptionSetterDiscardb(void *userDatavp, int symboli, marpaWrapperGrammarSymbolOption_t *marpaWrapperGrammarSymbolOptionp);
static        short                  _marpaESLIFGrammar_symbolOptionSetterInternalb(void *userDatavp, int symboli, marpaWrapperGrammarSymbolOption_t *marpaWrapperGrammarSymbolOptionp);
static        short                  _marpaESLIFGrammar_symbolOptionSetterInternalNoeventb(void *userDatavp, int symboli, marpaWrapperGrammarSymbolOption_t *marpaWrapperGrammarSymbolOptionp);
static        short                  _marpaESLIFGrammar_grammarOptionSetterNoLoggerb(void *userDatavp, marpaWrapperGrammarOption_t *marpaWrapperGrammarOptionp);
static inline void                   _marpaESLIF_rule_createshowv(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, marpaESLIF_rule_t *rulep, char *asciishows, size_t *asciishowlp);
static inline void                   _marpaESLIF_grammar_createshowv(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIF_grammar_t *grammarp, char *asciishows, size_t *asciishowlp);
static inline int                    _marpaESLIF_utf82ordi(PCRE2_SPTR8 utf8bytes, marpaESLIF_uint32_t *uint32p, PCRE2_SPTR8 utf8maxexcludedp);
static inline short                  _marpaESLIFRecognizer_matchPostProcessingb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t matchl);
static inline short                  _marpaESLIFRecognizer_getNextLineAndColumnb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t matchl);
static inline short                  _marpaESLIFRecognizer_appendDatab(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *datas, size_t datal, short eofb);
static inline short                  _marpaESLIFRecognizer_createDiscardStateb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_createBeforeStateb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_createAfterStateb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_createSymbolDatab(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_symbol_data_t ***symbolDatappp, short forPauseb);
static inline void                   _marpaESLIFRecognizer_symbolData_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_symbol_data_t **symbolDatapp);
static inline short                  _marpaESLIFRecognizer_createLastPauseb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline void                   _marpaESLIFRecognizer_lastPause_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_createLastTryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline void                   _marpaESLIFRecognizer_lastTry_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                  _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isExhaustedbp);
static inline marpaESLIFRecognizer_t *_marpaESLIFRecognizer_newFromp(marpaESLIF_grammar_t *grammarp, marpaESLIFRecognizer_t *marpaESLIFRecognizerSharedp, short discardb, short noEventb, short silentb);
static inline short                  _marpaESLIFRecognizer_isCanContinueb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isCanContinuebp, short *eofbp, short *isExhaustedbp);
static inline short                  _marpaESLIFRecognizer_isEofb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *eofbp);
static inline short                  _marpaESLIFRecognizer_inputb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **inputsp, size_t *inputlp);
static inline short                  _marpaESLIFRecognizer_scanb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short initialEventsb, short *continuebp, short *isExhaustedbp);
static inline short                  _marpaESLIFRecognizer_hook_discardb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short discardOnOffb);
static inline short                  _marpaESLIFRecognizer_hook_discard_switchb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
#if MARPAESLIF_VALUEERRORPROGRESSREPORT
static inline void                   _marpaESLIFValueErrorProgressReportv(marpaESLIFValue_t *marpaESLIFValuep);
#endif
static inline marpaESLIF_symbol_t   *_marpaESLIF_resolveLhsp(marpaESLIF_t *marpaESLIFp, genericStack_t *grammarStackp, marpaESLIF_grammar_t *current_grammarp, char *asciis, int parami, int lookupLevelDeltai, marpaESLIF_string_t *lookupGrammarStringp, marpaESLIF_grammar_t **grammarpp, short silentb);

static inline char                  *_marpaESLIF_ascii2ids(marpaESLIF_t *marpaESLIFp, char *asciis);
static inline short                  _marpaESLIF_generic_literal_transferb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIF_string_t *stringp, int resulti);
static        short                  _marpaESLIF_symbol_literal_transferb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultNotUsedp, int resulti);
static        short                  _marpaESLIF_rule_literal_transferb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        void                   _marpaESLIF_generic_freeCallbackv(void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline void                   _marpaESLIF_generic_freeCallback_inlinev(void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline marpaESLIFValue_t     *_marpaESLIFValue_newp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueOption_t *marpaESLIFValueOptionp, short silentb, short fakeb, short isLexemeb);
static inline short                  _marpaESLIFValue_stack_newb(marpaESLIFValue_t *marpaESLIFValuep);
static inline short                  _marpaESLIFValue_stack_freeb(marpaESLIFValue_t *marpaESLIFValuep);
static inline marpaESLIFValueResult_t *_marpaESLIFRecognizer_context_getp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *contextp);
static inline short                  _marpaESLIFValue_stack_setb(marpaESLIFValue_t *marpaESLIFValuep, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline short                  _marpaESLIFValue_stack_switchb(marpaESLIFValue_t *marpaESLIFValuep, int i, int j);
static inline short                  _marpaESLIFValue_stack_getb(marpaESLIFValue_t *marpaESLIFValuep, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline short                  _marpaESLIFValue_stack_getAndForgetb(marpaESLIFValue_t *marpaESLIFValuep, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline short                  _marpaESLIFValue_marpaESLIFValueResult_freeb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, short deepb);
static inline short                  _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short deepb);

static inline marpaESLIFValueResult_t *_marpaESLIFValue_stack_getp(marpaESLIFValue_t *marpaESLIFValuep, int indicei);
static inline short                  _marpaESLIFValue_stack_forgetb(marpaESLIFValue_t *marpaESLIFValuep, int indicei);
static inline short                  _marpaESLIF_generic_action___concatb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultLexemep, int arg0i, int argni, int resulti, short nullableb, char *toEncodings, short jsonb, short jsonfb);
static        short                  _marpaESLIF_generic_action_copyb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int argi, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___shiftb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___undefb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___asciib(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___convertb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___concatb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___copyb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___trueb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___falseb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___jsonb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___jsonfb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___rowb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___tableb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_rule_action___astb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb);
static        short                  _marpaESLIF_symbol_action___transferb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static        short                  _marpaESLIF_symbol_action___undefb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static        short                  _marpaESLIF_symbol_action___asciib(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static        short                  _marpaESLIF_symbol_action___convertb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static        short                  _marpaESLIF_symbol_action___concatb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static        short                  _marpaESLIF_symbol_action___trueb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static        short                  _marpaESLIF_symbol_action___falseb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static        short                  _marpaESLIF_symbol_action___jsonb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static        short                  _marpaESLIF_symbol_action___jsonfb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti);
static INLINE_QSORT int              _marpaESLIF_event_sorti(const void *p1, const void *p2);
static inline int                    _marpaESLIF_event_sort_inlinedi(marpaESLIFEvent_t *p1, marpaESLIFEvent_t *p2);
static INLINE_QSORT int              _marpaESLIF_symbol_priority_sorti(const void *p1, const void *p2);
static inline int                    _marpaESLIF_symbol_priority_sort_inlinedi(marpaESLIF_symbol_t **p1, marpaESLIF_symbol_t **p2);
static INLINE_QSORT int              _marpaESLIF_cleanup_sorti(const void *p1, const void *p2);
static inline int                    _marpaESLIF_cleanup_sort_inlinedi(genericStackItem_t *p1, genericStackItem_t *p2);
static inline unsigned long          _marpaESLIF_djb2_s(unsigned char *str, size_t lengthl);
static inline int                    _marpaESLIF_inlined_ptrhashi(void *p);
int                                  _marpaESLIF_ptrhashi(void *userDatavp, genericStackItemType_t itemType, void **pp);
int                                  _marpaESLIF_string_hash_callbacki(void *userDatavp, genericStackItemType_t itemType, void **pp);
short                                _marpaESLIF_string_cmp_callbackb(void *userDatavp, void **pp1, void **pp2);
void                                *_marpaESLIF_string_copy_callbackp(void *userDatavp, void **pp);
void                                 _marpaESLIF_string_free_callbackv(void *userDatavp, void **pp);
static        void                   _marpaESLIFRecognizerHash_free_callbackv(void *userDatavp, void **pp);
static        void                   _lexemeGrammarHash_free_callbackv(void *userDatavp, void **pp);
static inline void                   _marpaESLIFRecognizer_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short forceb);
static inline short                  _marpaESLIFRecognizer_getPristineFromCachep(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, short discardb, short noEventb, short silentb, marpaESLIFRecognizer_t *marpaESLIFRecognizerParentp, short fakeb, marpaESLIFRecognizer_t **marpaESLIFRecognizerpp, short isLexemeb);
static inline short                   _marpaESLIFRecognizer_getLexemeGrammarFromCachep(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIF_string_t *utf8p, marpaESLIFGrammar_t **marpaESLIFGrammarCachedpp);
static inline short                   _marpaESLIFRecognizer_putPristineToCacheb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline short                   _marpaESLIFRecognizer_putLexemeGrammarToCacheb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIF_string_t *utf8p, marpaESLIFGrammar_t *marpaESLIFGrammarCachedp);
static inline char                   *_marpaESLIF_action2asciis(marpaESLIF_action_t *actionp);
static inline short                   _marpaESLIF_action_validb(marpaESLIF_t *marpaESLIFp, marpaESLIF_action_t *actionp);
static inline short                   _marpaESLIF_action_eqb(marpaESLIF_action_t *action1p, marpaESLIF_action_t *action2p);
static inline marpaESLIF_action_t    *_marpaESLIF_action_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIF_action_t *actionp);
static inline void                    _marpaESLIF_action_freev(marpaESLIF_action_t *actionp);
static inline short                   _marpaESLIF_string_removebomb(marpaESLIF_t *marpaESLIFp, char *bytep, size_t *bytelp, char *encodingasciis, size_t *bomsizelp);
static inline short                   _marpaESLIFRecognizer_pointers_cleanupb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultOrigp, marpaESLIFValueResult_t *marpaESLIFValueResultNewp);
static inline int                     _marpaESLIFRecognizer_pointers_tracki(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, genericStack_t *marpaESLIFValueResultStackp);
static inline marpaESLIFGrammar_t    *_marpaESLIFJSON_decode_newp(marpaESLIF_t *marpaESLIFp, short strictb);
static inline marpaESLIFGrammar_t    *_marpaESLIFJSON_encode_newp(marpaESLIF_t *marpaESLIFp, short strictb);
static inline short                   _marpaESLIFValueResult_is_signed_nanb(marpaESLIF_t *marpaESLIFp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short negativeb, short *confidencebp);
static int                           _marpaESLIF_pcre2_callouti(pcre2_callout_block *blockp, void *userDatavp);
static int                           _marpaESLIF_pcre2_callout_enumeratei(pcre2_callout_enumerate_block *blockp, void *userDatavp);
static inline void                   _marpaESLIFCalloutBlock_initb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline void                   _marpaESLIFCalloutBlock_disposev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
static inline marpaESLIFSymbol_t    *_marpaESLIFSymbol_terminal_newp(marpaESLIF_t *marpaESLIFp, marpaESLIF_terminal_type_t terminalType, marpaESLIFString_t *stringp, char *modifiers, marpaESLIFString_t *substitutionStringp, char *substitutionModifiers, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp);
static inline marpaESLIF_symbol_t   *_marpaESLIFSymbol_meta_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp, char *symbols, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp);
static inline marpaESLIF_symbol_t   *_marpaESLIFSymbol_meta_new_by_levelp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp, char *symbols, int leveli, marpaESLIFString_t *descp, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp);
static inline marpaESLIFSymbol_t    *__marpaESLIFSymbol_meta_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp, char *symbols, int leveli, marpaESLIFString_t *descp, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp);
static inline unsigned int           _marpaESLIF_charset_toupperi(marpaESLIF_t *marpaESLIFp, const char c);
static inline short                  _marpaESLIF_charset_eqb(marpaESLIF_t *marpaESLIFp, const char *s, const char *p, size_t sizel);
static inline char                  *_marpaESLIF_charset_canonicals(marpaESLIF_t *marpaESLIFp, const char *s, const size_t sizel);
#ifdef MARPAESLIF_NAN
static inline void                   _marpaESLIF_guessNanv(marpaESLIF_t *marpaESLIFp);
#endif
static inline short                  _marpaESLIF_transfer_grammarb(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *dstp, int dsti, marpaESLIFGrammar_t *srcp, int srci);
static inline void                   _marpaESLIFRecognizer_errorv(marpaESLIFRecognizer_t *marpaESLIFRecognizerp);
#ifndef MARPAESLIF_NTRACE
static inline void                   _marpaESLIF_dump(marpaESLIF_t *marpaESLIFp);
#endif
static inline marpaESLIF_lua_functiondecl_t *_marpaESLIF_lua_functiondecl_newp(marpaESLIF_t *marpaESLIFp);
static inline marpaESLIF_lua_functioncall_t *_marpaESLIF_lua_functioncall_newp(marpaESLIF_t *marpaESLIFp);
static inline marpaESLIF_lua_functiondecl_t *_marpaESLIF_lua_functiondecl_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIF_lua_functiondecl_t *declp);
static inline marpaESLIF_lua_functioncall_t *_marpaESLIF_lua_functioncall_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIF_lua_functioncall_t *callp);
static inline marpaESLIF_lua_functioncall_t *_marpaESLIF_lua_functiondecl2callp(marpaESLIF_t *marpaESLIFp, marpaESLIF_lua_functiondecl_t *declp);
static inline void                   _marpaESLIF_lua_functiondecl_freev(marpaESLIF_lua_functiondecl_t *declp);
static inline void                   _marpaESLIF_lua_functioncall_freev(marpaESLIF_lua_functioncall_t *callp);
static inline short                  _marpaESLIFRecognizer_eventb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *eventArraylp, marpaESLIFEvent_t **eventArraypp);
static inline short                  _marpaESLIFRecognizer_name_last_pauseb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *lexemes, char **pausesp, size_t *pauselp);
static inline short                  _marpaESLIFRecognizer_alternative_readb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFAlternative_t *marpaESLIFAlternativep, size_t lengthl);
static inline size_t                 _marpaESLIF_next_power_of_twob(marpaESLIF_t *marpaESLIFp, size_t wantedl);
static inline short                  _marpaESLIFValue_importb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline short                  _marpaESLIFRecognizer_importb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp);
static inline short                  _marpaESLIFRecognizer_name_expectedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *nNamelp, char ***namesArraypp);
static inline short                  _marpaESLIFRecognizer_discard_last_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **trysp, size_t *trylp);
static inline short                  _marpaESLIFRecognizer_alternativeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFAlternative_t *marpaESLIFAlternativep);
static inline marpaESLIF_symbol_t   *_marpaESLIFSymbol_string_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFString_t *stringp, char *modifiers, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp);
static inline marpaESLIF_symbol_t   *_marpaESLIFSymbol_regex_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFString_t *stringp, char *modifiers, marpaESLIFString_t *substitutionStringp, char *substitutionModifiers, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp);
static inline short                  _marpaESLIFSymbol_tryb(marpaESLIFSymbol_t *marpaESLIFSymbolp, char *inputs, size_t inputl, short *matchbp);
static inline short                  _marpaESLIFRecognizer_symbol_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFSymbol_t *marpaESLIFSymbolp, short *matchbp);
static inline short                 __marpaESLIFRecognizer_symbol_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFSymbol_t *marpaESLIFSymbolp, short *matchbp);
static        short                  _marpaESLIFRecognizerSymbolProxyImportb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short haveUndefb);

/*****************************************************************************/
static inline marpaESLIF_string_t *_marpaESLIF_string_newp(marpaESLIF_t *marpaESLIFp, char *encodingasciis, char *bytep, size_t bytel)
/*****************************************************************************/
/* Caller is responsible to set coherent values of bytes and bytel.          */
/* In particular an empty string must be set with bytep = NULL and bytel = 0 */
/*****************************************************************************/
{
  static const char   *funcs = "_marpaESLIF_string_newp";
  marpaESLIF_string_t *stringp = NULL;
  char                *dstbytep;

  stringp = (marpaESLIF_string_t *) malloc(sizeof(marpaESLIF_string_t));
  if (MARPAESLIF_UNLIKELY(stringp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  stringp->encodingasciis = NULL;
  stringp->asciis         = NULL;

  if (bytel > 0) {
    /* bytel + 1 for the hiden NUL byte */
    if (MARPAESLIF_UNLIKELY((stringp->bytep = dstbytep = (char *) calloc(1, bytel + 1)) == NULL)) {
      /* We always add a NUL byte for convenience */
      MARPAESLIF_ERRORF(marpaESLIFp, "calloc failure, %s", strerror(errno));
      goto err;
    }
    memcpy(dstbytep, bytep, bytel);
    stringp->bytel = bytel;
  } else {
    stringp->bytep = (char *) MARPAESLIF_EMPTY_STRING;
    stringp->bytel = 0;
  }

  if (bytel > 0) {
    /* This will fill stringp->encodingasciis if not already set */
    if (MARPAESLIF_UNLIKELY((stringp->asciis = _marpaESLIF_charconvb(marpaESLIFp, "ASCII//TRANSLIT//IGNORE", encodingasciis, bytep, bytel, NULL, &(stringp->encodingasciis), NULL /* tconvpp */, 1 /* eofb */, NULL /* byteleftsp */, NULL /* byteleftlp */, NULL /* byteleftalloclp */, 0 /* tconvsilentb */, NULL /* defaultEncodings */, NULL /* fallbackEncodings */)) == NULL)) {
      goto err;
    }
  } else {
    /* ASCII version is an empty string */
    stringp->asciis = (char *) MARPAESLIF_EMPTY_STRING;
    /* Copy encodingasciis if any */
    if (encodingasciis != NULL) {
      if (encodingasciis == MARPAESLIF_UTF8_STRING) {
        /* Internal variable used to avoid unnecessary strdup() call */
        stringp->encodingasciis = (char *) MARPAESLIF_UTF8_STRING;
      } else {
        if (MARPAESLIF_UNLIKELY((stringp->encodingasciis = strdup(encodingasciis)) == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
          goto err;
        }
      }
    }
  }

  goto done;

 err:
  _marpaESLIF_string_freev(stringp, 0 /* onStackb */);
  stringp = NULL;

 done:
  return stringp;
}

/*****************************************************************************/
static inline marpaESLIF_string_t *_marpaESLIF_string_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIF_string_t *stringp)
/*****************************************************************************/
{
  marpaESLIF_string_t *rcp = NULL;
  char                *bytep;
  size_t               bytel;
  
  if (MARPAESLIF_UNLIKELY(stringp == NULL)) {
    goto err;
  }

  rcp = (marpaESLIF_string_t *) malloc(sizeof(marpaESLIF_string_t));
  if (MARPAESLIF_UNLIKELY(rcp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  rcp->encodingasciis = NULL;
  rcp->asciis         = NULL;

  if ((rcp->bytel = stringp->bytel) > 0) {
    bytep = rcp->bytep = (char *) calloc(1, (bytel = stringp->bytel) + 1); /* We always add a NUL byte for convenience */
    if (MARPAESLIF_UNLIKELY(bytep == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "calloc failure, %s", strerror(errno));
      goto err;
    }
    memcpy(bytep, stringp->bytep, bytel);
  } else {
    rcp->bytep = (char *) MARPAESLIF_EMPTY_STRING;
  }

  if (stringp->asciis != NULL) {
    if (stringp->asciis == MARPAESLIF_EMPTY_STRING) {
      rcp->asciis = (char *) MARPAESLIF_EMPTY_STRING;
    } else {
      if (MARPAESLIF_UNLIKELY((rcp->asciis = strdup(stringp->asciis)) == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
  }

  if (stringp->encodingasciis != NULL) {
    if (stringp->encodingasciis == MARPAESLIF_UTF8_STRING) {
      /* Internal variable used to avoid unnecesary strdup() call */
      rcp->encodingasciis = (char *) MARPAESLIF_UTF8_STRING;
    } else {
      if (MARPAESLIF_UNLIKELY((rcp->encodingasciis = strdup(stringp->encodingasciis)) == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
  }

  goto done;

 err:
  _marpaESLIF_string_freev(rcp, 0 /* onStackb */);
  rcp = NULL;

 done:
  return rcp;
}

/*****************************************************************************/
static inline void _marpaESLIF_string_freev(marpaESLIF_string_t *stringp, short onStackb)
/*****************************************************************************/
{
  if (stringp != NULL) {
    if ((stringp->bytep != NULL) && (stringp->bytep != MARPAESLIF_EMPTY_STRING)) {
      free(stringp->bytep);
    }
    if ((stringp->encodingasciis != NULL) && (stringp->encodingasciis != MARPAESLIF_UTF8_STRING)) {
      free(stringp->encodingasciis);
    }
    if ((stringp->asciis != NULL) && (stringp->asciis != MARPAESLIF_EMPTY_STRING)) {
      free(stringp->asciis);
    }
    if (! onStackb) {
      free(stringp);
    }
  }
}

/*****************************************************************************/
static inline short _marpaESLIF_string_utf8_eqb(marpaESLIF_string_t *string1p, marpaESLIF_string_t *string2p)
/*****************************************************************************/
{
  /* It is assumed the caller compare strings with the same encoding - UTF-8 in our case */
  char  *byte1p;
  char  *byte2p;
  size_t bytel;

  if ((string1p == NULL) || (string2p == NULL)) {
    return 0;
  }
  if (((byte1p = string1p->bytep) == NULL) || ((byte2p = string2p->bytep) == NULL)) {
    return 0;
  }
  if ((bytel = string1p->bytel) != string2p->bytel) {
    return 0;
  }
  return (memcmp(byte1p, byte2p, bytel) == 0) ? 1 : 0;
}

/*****************************************************************************/
static inline short _marpaESLIF_string_eqb(marpaESLIF_string_t *string1p, marpaESLIF_string_t *string2p)
/*****************************************************************************/
{
  /* It is assumed the caller compare strings with the same encoding - UTF-8 in our case */
  char  *byte1p;
  char  *byte2p;
  size_t bytel;

  if ((string1p == NULL) || (string2p == NULL)) {
    return 0;
  }
  if (((byte1p = string1p->bytep) == NULL) || ((byte2p = string2p->bytep) == NULL)) {
    return 0;
  }
  if ((bytel = string1p->bytel) != string2p->bytel) {
    return 0;
  }
  return (memcmp(byte1p, byte2p, bytel) == 0) ? 1 : 0;
}

/*****************************************************************************/
static inline marpaESLIF_terminal_t *_marpaESLIF_terminal_newp(marpaESLIF_t *marpaESLIFp, marpaWrapperGrammar_t *marpaWrapperGrammarp, int eventSeti, char *descEncodings, char *descs, size_t descl, marpaESLIF_terminal_type_t type, char *modifiers, char *utf8s, size_t utf8l, char *testFullMatchs, char *testPartialMatchs, short pseudob, short characterClassb, marpaESLIF_terminal_type_t wantType, short substitutionb)
/*****************************************************************************/
/* This method is bootstraped at marpaESLIFp creation itself to have the internal regexps, with grammarp being NULL... */
/* characterClassb can always be set to 0 if unsure, but it caller set it to a true value it really has to be a character class i.e. [] and only that */
/* If substitutionb is set, we do almost no processing but recuperate the inner utf8 string. */
/*****************************************************************************/
{
  static const char                *funcs                     = "_marpaESLIF_terminal_newp";
  char                             *strings                   = NULL;
  marpaESLIFRecognizer_t           *marpaESLIFRecognizerp     = NULL;
#ifndef MARPAESLIF_NTRACE
  marpaESLIFRecognizer_t           *marpaESLIFRecognizerTestp = NULL;
#endif
  marpaESLIF_string_t              *content2descp             = NULL;
  char                             *generatedasciis           = NULL;
  short                             memcmpb                   = 0;
  marpaESLIF_terminal_t            *terminalp                 = NULL;
  size_t                            pcre2JitOptionl           = 0;
  marpaESLIF_uint32_t               pcre2Optioni              = PCRE2_ANCHORED;
  marpaESLIF_uint32_t               pcre2SubstitutionOptioni  = 0;
  int                               pcre2Errornumberi;
  PCRE2_SIZE                        pcre2ErrorOffsetl;
  PCRE2_UCHAR                       pcre2ErrorBuffer[256];
  marpaWrapperGrammarSymbolOption_t marpaWrapperGrammarSymbolOption;
  int                               i;
  char                             *inputs;
  size_t                            inputl;
  marpaESLIF_matcher_value_t        rci;
  marpaESLIF_uint32_t               codepointi;
  marpaESLIF_uint32_t               firstcodepointi;
  marpaESLIF_uint32_t               lastcodepointi;
  short                             backslashb;
  short                             utfflagb;
  size_t                            stringl;
  char                             *tmps;
  size_t                            hexdigitl;
  int                               utf82ordi;
  marpaESLIFValueResult_t           marpaESLIFValueResult;
  char                             *matchedp;
  size_t                            matchedl;
  char                             *modifiersp;
  char                              modifierc;
  short                             asciisafeb;
  char                             *bytes;
  size_t                            bytel;
  marpaESLIF_stream_t              *marpaESLIF_streamp;
  marpaESLIF_pcre2_callout_enumerate_context_t enumerate_context;
  short                             modifierFoundb;
  size_t                            slashl;
  char                             *p;
  char                             *q;
  size_t                            matchedLengthl;
  unsigned char                     uc;
  marpaESLIF_utf8_2_bytes_max_t    *utf8_2_bytes_maxp;

  /* Check some required parameters */
  if (pseudob) {
    if ((wantType != MARPAESLIF_TERMINAL_TYPE_NA) && (wantType != type)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "Invalid terminal type %d instead of %d", type, wantType);
      errno = EINVAL;
      goto err;
    }
    if (MARPAESLIF_UNLIKELY((utf8s != NULL) || (utf8l > 0))) {
      MARPAESLIF_ERROR(marpaESLIFp, "Invalid builtin terminal origin");
      errno = EINVAL;
      goto err;
    }
    /* We hardcode the description */
    switch (type) {
    case MARPAESLIF_TERMINAL_TYPE__EOF:
      utf8s = (char *) MARPAESLIF_TERMINAL__EOF;
      utf8l = strlen(MARPAESLIF_TERMINAL__EOF);
      break;
    case MARPAESLIF_TERMINAL_TYPE__EOL:
      utf8s = (char *) MARPAESLIF_TERMINAL__EOL;
      utf8l = strlen(MARPAESLIF_TERMINAL__EOL);
      break;
    case MARPAESLIF_TERMINAL_TYPE__SOL:
      utf8s = (char *) MARPAESLIF_TERMINAL__SOL;
      utf8l = strlen(MARPAESLIF_TERMINAL__SOL);
      break;
    case MARPAESLIF_TERMINAL_TYPE__EMPTY:
      utf8s = (char *) MARPAESLIF_TERMINAL__EMPTY;
      utf8l = strlen(MARPAESLIF_TERMINAL__EMPTY);
      break;
    default:
      MARPAESLIF_ERRORF(marpaESLIFp, "Invalid builtin terminal type %d", type);
      errno = EINVAL;
      goto err;
    }
  } else {
    if (MARPAESLIF_UNLIKELY((utf8s == NULL) || (utf8l <= 0))) {
      MARPAESLIF_ERROR(marpaESLIFp, "Invalid terminal origin");
      errno = EINVAL;
      goto err;
    }
  }

  /* Please note the "fakeb" parameter below */
  terminalp = (marpaESLIF_terminal_t *) malloc(sizeof(marpaESLIF_terminal_t));
  if (MARPAESLIF_UNLIKELY(terminalp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  terminalp->utf8s                                       = NULL;
  terminalp->utf8l                                       = 0;
  terminalp->idi                                         = -1;
  terminalp->descp                                       = NULL;
  terminalp->modifiers                                   = NULL;
  terminalp->patterns                                    = NULL;
  terminalp->patternl                                    = 0;
  terminalp->patterni                                    = 0;
  terminalp->substitutionUtf8s                           = NULL;
  terminalp->substitutionUtf8l                           = 0;
  terminalp->substitutionModifiers                       = NULL;
  terminalp->substitutionPatterns                        = NULL;
  terminalp->substitutionPatternl                        = 0;
  terminalp->substitutionPatterni                        = 0;
  terminalp->regex.patternp                              = NULL;
  terminalp->regex.match_datap                           = NULL;
#ifdef PCRE2_CONFIG_JIT
  terminalp->regex.jitb                                  = 0;
#endif
  terminalp->regex.isAnchoredb                           = 0;
  terminalp->regex.utfb                                  = 0;
  terminalp->regex.compile_contextp                      = NULL;
  terminalp->regex.calloutb                              = 0;
  terminalp->regex.match_contextp                        = NULL;
  terminalp->regex.callout_context.marpaESLIFRecognizerp = NULL; /* Changed at every call, c.f. _marpaESLIFRecognizer_terminal_matcherb */
  terminalp->regex.callout_context.terminalp             = NULL;
  terminalp->regex.characterClassb                       = characterClassb;
  terminalp->memcmpb                                     = 0;
  terminalp->bytes                                       = NULL;
  terminalp->bytel                                       = 0;
  terminalp->pseudob                                     = pseudob;
  terminalp->eventSeti                                   = eventSeti;

  /* Original input */
  if ((utf8s != NULL) && (utf8l > 0)) {
    terminalp->utf8l = utf8l;
    terminalp->utf8s = (char *) malloc(utf8l + 1);
    if (terminalp->utf8s == NULL) {
      MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    memcpy(terminalp->utf8s, utf8s, utf8l);
    terminalp->utf8s[utf8l] = '\0';
  }

  /* ----------- Modifiers ------------ */
  if (modifiers != NULL) {
    terminalp->modifiers = strdup(modifiers);
    if (MARPAESLIF_UNLIKELY(terminalp->modifiers == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
  }

  /* ----------- Terminal Identifier ------------ */
  if ((! substitutionb) && (marpaWrapperGrammarp != NULL)) { /* Here is the bootstrap dependency with marpaWrapperGrammarp == NULL */
    marpaWrapperGrammarSymbolOption.terminalb = 1;
    marpaWrapperGrammarSymbolOption.startb    = 0;
    marpaWrapperGrammarSymbolOption.eventSeti = eventSeti;
    terminalp->idi = marpaWrapperGrammar_newSymboli(marpaWrapperGrammarp, &marpaWrapperGrammarSymbolOption);
    if (MARPAESLIF_UNLIKELY(terminalp->idi < 0)) {
      goto err;
    }
  }

  /* ----------- Terminal Description ------------ */
  if (descs == NULL) {
    /* Get an ASCII version of the content */
    content2descp = _marpaESLIF_string_newp(marpaESLIFp, (char *) MARPAESLIF_UTF8_STRING, utf8s, utf8l);
    if (MARPAESLIF_UNLIKELY(content2descp == NULL)) {
      goto err;
    }
    if (type == MARPAESLIF_TERMINAL_TYPE_STRING) {
      /* Use already escaped version -; */
      if (modifiers != NULL) {
        /* ":xxxx */
        generatedasciis = (char *) malloc(strlen(content2descp->asciis) + 1 + strlen(modifiers) + 1);
        if (MARPAESLIF_UNLIKELY(generatedasciis == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        strcpy(generatedasciis, content2descp->asciis);
        strcat(generatedasciis, ":");
        strcat(generatedasciis, modifiers);
      } else {
        generatedasciis = strdup(content2descp->asciis);
        if (MARPAESLIF_UNLIKELY(generatedasciis == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
          goto err;
        }
      }
    } else if (type == MARPAESLIF_TERMINAL_TYPE__EOF) {
      generatedasciis = strdup(content2descp->asciis);
      if (MARPAESLIF_UNLIKELY(generatedasciis == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    } else if (type == MARPAESLIF_TERMINAL_TYPE__EOL) {
      generatedasciis = strdup(content2descp->asciis);
      if (MARPAESLIF_UNLIKELY(generatedasciis == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    } else if (type == MARPAESLIF_TERMINAL_TYPE__SOL) {
      generatedasciis = strdup(content2descp->asciis);
      if (MARPAESLIF_UNLIKELY(generatedasciis == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    } else if (type == MARPAESLIF_TERMINAL_TYPE__EMPTY) {
      generatedasciis = strdup(content2descp->asciis);
      if (MARPAESLIF_UNLIKELY(generatedasciis == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    } else {
      /* "/" + XXX + "/" (escaping slashes - this is not perfect, it assumes that regexp was writen only in ASCII) */
      p = content2descp->asciis;
      slashl = 0;
      while (*p != '\0') {
        if (*p++ == '/') {
          ++slashl;
        }
      }
      if (modifiers != NULL) {
        /* xxxx */
        generatedasciis = (char *) malloc(1 + slashl + strlen(content2descp->asciis) + 1 + strlen(modifiers) + 1);
      } else {
        generatedasciis = (char *) malloc(1 + slashl + strlen(content2descp->asciis) + 1 + 1);
      }
      if (MARPAESLIF_UNLIKELY(generatedasciis == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }

      q = generatedasciis;
      *q++ = '/';

      p = content2descp->asciis;
      while (*p != '\0') {
        if (*p == '/') {
          *q++ = '\\';
        }
        *q++ = *p++;
      }

      *q++ = '/';

      if (modifiers != NULL) {
        p = modifiers;
        while (*p != '\0') {
          *q++ = *p++;
        }
      }

      *q = '\0';
    }
    terminalp->descp = _marpaESLIF_string_newp(marpaESLIFp, "ASCII", generatedasciis, strlen(generatedasciis));
  } else {
    terminalp->descp = _marpaESLIF_string_newp(marpaESLIFp, descEncodings, descs, descl);
  }
  if (MARPAESLIF_UNLIKELY(terminalp->descp == NULL)) {
    goto err;
  }

  /* ----------- Terminal Implementation ------------ */
  switch (type) {

  case MARPAESLIF_TERMINAL_TYPE__EOF:
    /* No op */
    break;

  case MARPAESLIF_TERMINAL_TYPE__EOL:
    /* No op */
    break;

  case MARPAESLIF_TERMINAL_TYPE__SOL:
    /* No op */
    break;

  case MARPAESLIF_TERMINAL_TYPE__EMPTY:
    /* No op */
    break;

  case MARPAESLIF_TERMINAL_TYPE_STRING:

    /* If there are no modifiers, then the terminals as taken as-is */
    /* The only string modifier allowed is case-insensitive, that WILL */
    /* require regex. */
    if (modifiers == NULL) {
      /* Per definition the real string cannot be longer than bytel. At most */
      /* it is exactly this size. Everytime there is a backslashed character */
      /* the backslash itself is skipped. This mean that allocating bytel+1 */
      /* bytes is always guaranteed to get the raw string entirely. We overestimate */
      /* this in another way: the {bytesl,bytel} array must contain the delimiters, that */
      /* are also skipped when parsing it. */
      bytes = (char *) malloc(utf8l+1);
      if (MARPAESLIF_UNLIKELY(bytes == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      memcmpb = terminalp->memcmpb = 1;
      terminalp->bytes = bytes;  /* bytes will move everytime we append to the buffer */
      bytel   = 0;               /* bytel will increase everytime we append to the buffer */

      /* If there is a failure, _marpaESLIF_terminal_freev() will take care of bytes */
    }
    

    /* We convert a string terminal into a regexp */
    /* By construction we are coming from the parsing of a grammar, that previously translated the whole */
    /* grammar into an UTF-8 string. We use PCRE2 to extract all code points, and create a new string that */
    /* is a concatenation of \x{} thingies. By doing so, btw, we are able to know if we need PCRE2_UTF flag. */
    /* We are also able to reconstruct the raw string, because we recognizer the escape characters. */
    inputs = utf8s;
    inputl = utf8l;

    /* Fake a recognizer. EOF flag will be set automatically in fake mode */
    marpaESLIFRecognizerp = __marpaESLIFRecognizer_newp(marpaESLIFp,
                                                        NULL, /* grammarp */
                                                        NULL, /* marpaESLIFRecognizerOptionp */
                                                        0, /* discardb - not used anyway because we are in fake mode */
                                                        1, /* noEventb - not used anyway because we are in fake mode */
                                                        0, /* silentb */
                                                        NULL, /* marpaESLIFRecognizerParentp */
                                                        1, /* fakeb */
                                                        0, /* maxStartCompletionsi */
                                                        1, /* Here, we know input is UTF-8 valid */
                                                        0 /* isLexemeb */);
    if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
      goto err;
    }
#ifndef MARPAESLIF_NTRACE
    MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "String conversion to regexp for ", terminalp->descp->asciis, utf8s, utf8l, 1 /* traceb */, 0 /* noticeb */, 0 /* linel */, 0 /* columnl */);
#endif

    /* Please note that at the very very early startup, when we create marpaESLIFp, there is NO marpaESLIFp->anycharp yet! */
    /* But we will never crash because marpaESLIFp never create its internal terminals using the STRING type -; */
    marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
    while (inputl > 0) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizerp, marpaESLIF_streamp, marpaESLIFp->anycharp, inputs, inputl, 1 /* eofb */, &rci, &marpaESLIFValueResult, &matchedLengthl))) {
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(rci != MARPAESLIF_MATCH_OK)) {
        MARPAESLIF_ERROR(marpaESLIFp, "Failed to detect all characters of terminal string");
        errno = EINVAL;
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_lexemeStack_i_setb(marpaESLIFRecognizerp, GENERICSTACK_USED(marpaESLIFRecognizerp->lexemeStackp), &marpaESLIFValueResult))) {
	_marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, &marpaESLIFValueResult);
        goto err;
      }
      inputs += marpaESLIFValueResult.u.a.sizel;
      inputl -= marpaESLIFValueResult.u.a.sizel;
    }
    /* All matches are in the recognizer's lexeme input stack, in order. Take all unicode code points to generate a regex out of this string. */
    utfflagb = 0;
    stringl = 0;
    backslashb = 0;
    /* Remember that lexeme input stack is putting a fake value at indice 0, because marpa does not like it */
    for (i = 1; i < GENERICSTACK_USED(marpaESLIFRecognizerp->lexemeStackp); i++) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_lexemeStack_i_p_and_sizeb(marpaESLIFRecognizerp, i, &matchedp, &matchedl))) {
        goto err;
      }
      /* Get the code point from the UTF-8 representation */
      utf82ordi = _marpaESLIF_utf82ordi((PCRE2_SPTR8) matchedp, &codepointi, (PCRE2_SPTR8) (matchedp + matchedl));
      if (MARPAESLIF_UNLIKELY(utf82ordi <= 0)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Malformed UTF-8 character at offset %d", -utf82ordi);
        errno = EINVAL;
        goto err;
      } else if (MARPAESLIF_UNLIKELY(utf82ordi != (int) matchedl)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Not all bytes consumed: %d instead of %ld", utf82ordi, (unsigned long) matchedl);
        errno = EINVAL;
        goto err;
      }
      if (i == 1) {
        /* We want to skip first and last characters, and we will use that to detect the backslash... Note that it cannot be backslash per def as per the regexps */
        firstcodepointi = codepointi;
        /* First codepoints are known in advance */
        switch (firstcodepointi) {
        case '\'':
          lastcodepointi = '\'';
          break;
        case '"':
          lastcodepointi = '"';
          break;
        case 0x201c:
          lastcodepointi = 0x201d;
          break;
        default:
          {
            if (isprint((unsigned char) codepointi)) {
              MARPAESLIF_ERRORF(marpaESLIFp, "Impossible first codepoint %c (0x%02lx), should be 0x201c, \"'\" or '\"'", (unsigned char) codepointi, (unsigned long) codepointi);
            } else {
              MARPAESLIF_ERRORF(marpaESLIFp, "Impossible first codepoint 0x%02lx, should be 0x201c, \"'\" or '\"'", (unsigned long) codepointi);
            }
            MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "Dump", "", matchedp, matchedl, 0 /* traceb */, 0 /* noticeb */, 0 /* linel */, 0 /* columnl */);
            errno = EINVAL;
            goto err;
          }
        }
        continue;
      } else if (i == (GENERICSTACK_USED(marpaESLIFRecognizerp->lexemeStackp) - 1)) {
        /* Trailing backslash ? */
        if (MARPAESLIF_UNLIKELY(backslashb)) {
          MARPAESLIF_ERROR(marpaESLIFp, "Trailing backslash in string is not allowed");
          errno = EINVAL;
          goto err;
        }
        /* Non-sense to not have the same value */
        if (MARPAESLIF_UNLIKELY(lastcodepointi != codepointi)) {
          /* Note that we know that our regexp start and end with printable characters */
          if (isprint((unsigned char) codepointi)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "First and last characters do not correspond: %c (0x%02lx) v.s. %c (0x%02lx) (wanted %c (0x%lx))",
                              (unsigned char) firstcodepointi, (unsigned long) firstcodepointi,
                              (unsigned char) codepointi, (unsigned long) codepointi,
                              (unsigned char) lastcodepointi, (unsigned long) lastcodepointi);
          } else {
            MARPAESLIF_ERRORF(marpaESLIFp, "First and last characters do not correspond: %c (0x%02lx) v.s. 0x%02lx (wanted %c (0x%lx))",
                              (unsigned char) firstcodepointi, (unsigned long) firstcodepointi,
                              (unsigned long) codepointi,
                              (unsigned char) lastcodepointi, (unsigned long) lastcodepointi);
          }
          errno = EINVAL;
          goto err;
        }
        break;
      } else {
        /* Backslash stuff */
        if (codepointi == '\\') {
          if (! backslashb) {
            /* Next character MAY BE escaped. Only backslash itself or the first character is considered as per the regexp. */
            MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Backslash character remembered");
            backslashb = 1;
            continue;
          } else {
            /* This is escaped backslash */
            MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Escaped backslash character accepted");
            backslashb = 0;
          }
        } else if (codepointi == lastcodepointi) {
          if (MARPAESLIF_UNLIKELY(! backslashb)) {
            /* This is a priori impossible to not have the first or backslash character if it is not preceeded by backslash */
            if (codepointi == lastcodepointi) {
              MARPAESLIF_ERRORF(marpaESLIFp, "First character %c found but no preceeding backslash", (unsigned char) codepointi);
            } else {
              MARPAESLIF_ERROR(marpaESLIFp, "Backslash character found but no preceeding backslash");
            }
            errno = EINVAL;
            goto err;
          }
          /* This is escaped first character */
          MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Escaped quote character accepted");
          backslashb = 0;
        } else {
          if (MARPAESLIF_UNLIKELY(backslashb)) {
            /* Here the backslash flag must not be true */
            if (isprint((unsigned char) codepointi)) {
              MARPAESLIF_ERRORF(marpaESLIFp, "Got character %c (0x%02lx) preceeded by backslash: in your string only backslash character (\\) or the string delimitor (%c) can be escaped", (unsigned char) codepointi, (unsigned long) codepointi, (unsigned char) firstcodepointi);
            } else {
              MARPAESLIF_ERRORF(marpaESLIFp, "Got character 0x%02lx (non printable) preceeded by backslash: in your string only backslash character (\\) or the string delimitor (%c) can be escaped", (unsigned long) codepointi, (unsigned char) firstcodepointi);
            }
            errno = EINVAL;
            goto err;
          }
          /* All is well */
#ifndef MARPAESLIF_NTRACE
          if (isprint((unsigned char) codepointi)) {
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Got character %c (0x%02lx)", (unsigned char) codepointi, (unsigned long) codepointi);
          } else {
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Got character 0x%02lx (non printable)", (unsigned long) codepointi);
          }
#endif
        }
      }

      /* The recognizerd UTF-8 character start at matchedp and is of size matchedl */
      if (memcmpb) {
        /* bytes is guaranteed to have enough room for the matched character. */
        memcpy(bytes, matchedp, matchedl);
        bytes += matchedl;
        bytel += matchedl;
      }
      
      /* Determine the number of hex digits to fully represent the code point, remembering if we need PCRE2_UTF flag */
      if ((codepointi >= 0x20) && (codepointi <= 0x7E)) {
        /* Characters [0x20-0x7E] are considered safe */
        /* Since we are not doing a character-class thingy, we escape all PCRE2 metacharacters */
        /* that are recognized outside of a character class */
        switch ((unsigned char) codepointi) {
        case '\\':
        case '^':
        case '$':
        case '.':
        case '[':
        case '|':
        case '(':
        case ')':
        case '?':
        case '*':
        case '+':
        case '{':
          asciisafeb = 2;
          break;
        default:
          asciisafeb = 1;
          break;
        }
      } else {
        asciisafeb = 0;
        hexdigitl = 4; /* \x{} */
        if ((codepointi & 0xFF000000) != 0x00000000) {
          hexdigitl += 8;
          utfflagb = 1;
        } else if ((codepointi & 0x00FF0000) != 0x00000000) {
          hexdigitl += 6;
          utfflagb = 1;
        } else if ((codepointi & 0x0000FF00) != 0x00000000) {
          hexdigitl += 4;
          utfflagb = 1;
        } else {
          hexdigitl += 2;
        }
      }

      if (substitutionb) {
        /* Raw copy */
        if (strings == NULL) {
          strings = (char *) malloc(matchedl + 1);
          if (MARPAESLIF_UNLIKELY(strings == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
            goto err;
          }
          memcpy(strings, matchedp, matchedl);
        } else {
          tmps = (char *) realloc(strings, stringl + matchedl + 1);
          if (MARPAESLIF_UNLIKELY(tmps == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "realloc failure, %s", strerror(errno));
            goto err;
          }
          strings = tmps;
          memcpy(strings + stringl, matchedp, matchedl);
        }
        stringl += matchedl;
        strings[stringl] = '\0'; /* Makes sure the string always end with NUL */
      } else {
        /* Append the ASCII representation */
        stringl += (asciisafeb > 0) ? asciisafeb : hexdigitl;
        if (strings == NULL) {
          strings = (char *) malloc(stringl + 1);
          if (MARPAESLIF_UNLIKELY(strings == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
            goto err;
          }
          strings[0] = '\0'; /* Start with an empty string */
        } else {
          tmps = (char *) realloc(strings, stringl + 1);
          if (MARPAESLIF_UNLIKELY(tmps == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "realloc failure, %s", strerror(errno));
            goto err;
          }
          strings = tmps;
        }
        strings[stringl] = '\0'; /* Makes sure the string always end with NUL */
        if (asciisafeb > 0) {
          if (asciisafeb > 1) {
            sprintf(strings + strlen(strings), "\\%c", (unsigned char) codepointi);
          } else {
            sprintf(strings + strlen(strings), "%c", (unsigned char) codepointi);
          }
        } else {
          hexdigitl -= 4; /* \x{} */
          sprintf(strings + strlen(strings), "\\x{%0*lx}", (int) hexdigitl, (unsigned long) codepointi);
        }
      }
    }

#ifndef MARPAESLIF_NTRACE
    if (substitutionb) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: substitution string analysed (UTF=%d)", terminalp->descp->asciis, utfflagb);
    } else {
      /* Done - now we can generate a regexp out of that UTF-8 compatible string */
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: content string converted to regex %s (UTF=%d)", terminalp->descp->asciis, strings, utfflagb);
    }
#endif

    utf8s = strings;
    utf8l = stringl;
    /* opti for string is compatible with opti for regex - just that the lexer accept less options - in particular the UTF flag */
    if (utfflagb) {
      pcre2Optioni |= PCRE2_UTF;
    }

    /* ********************************************************************************************************** */
    /*                                   THERE IS NO BREAK INTENTIONALY HERE                                      */
    /* ********************************************************************************************************** */
    /* break; */

    /* Please note that we do not unescape: in character class, if "]" was escaped it has to be left as is. In */
    /* a regular expression, if "/" is escaped, this is has no impact. */

  case MARPAESLIF_TERMINAL_TYPE_REGEX:

    if ((type != MARPAESLIF_TERMINAL_TYPE_STRING) && (marpaESLIFp->anycharp != NULL)) {
      /* Coming directly there, try to determine the need of PCRE2_UTF. This will not work with */
      /* character classes containing codepoints in the form \x{}, but then PCRE2 will yell on its own. */
      /* This does not work when we build internal marpaESLIF regex itself -; */
      marpaESLIFRecognizer_freev(marpaESLIFRecognizerp); /* NULL protected */
      marpaESLIFRecognizerp = NULL;

      inputs = utf8s;
      inputl = utf8l;

      /* Fake a recognizer. EOF flag will be set automatically in fake mode */
      marpaESLIFRecognizerp = __marpaESLIFRecognizer_newp(marpaESLIFp,
                                                          NULL, /* grammarp */
                                                          NULL, /* marpaESLIFRecognizerOptionp */
                                                          0, /* discardb - not used anyway because we are in fake mode */
                                                          1, /* noEventb - not used anyway because we are in fake mode */
                                                          0, /* silentb */
                                                          NULL, /* marpaESLIFRecognizerParentp */
                                                          1, /* fakeb */
                                                          0, /* maxStartCompletionsi */
                                                          1, /* Here we know input is UTF-8 valid */
                                                          0 /* isLexemeb */);
      if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
        goto err;
      }

      marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
      while (inputl > 0) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizerp, marpaESLIF_streamp, marpaESLIFp->anycharp, inputs, inputl, 1 /* eofb */, &rci, &marpaESLIFValueResult, &matchedLengthl))) {
          errno = EINVAL;
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(rci != MARPAESLIF_MATCH_OK)) {
          MARPAESLIF_ERROR(marpaESLIFp, "Failed to detect all characters of terminal string");
          errno = EINVAL;
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_lexemeStack_i_setb(marpaESLIFRecognizerp, GENERICSTACK_USED(marpaESLIFRecognizerp->lexemeStackp), &marpaESLIFValueResult))) {
	  _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, &marpaESLIFValueResult);
          goto err;
        }
        inputs += marpaESLIFValueResult.u.a.sizel;
        inputl -= marpaESLIFValueResult.u.a.sizel;
      }
      /* All matches are in the recognizer's lexeme input stack, in order. Take all unicode code points. */
      utfflagb = 0;
      /* Remember that marpa input stack is starting at indice 1 - 0 is for the context */
      for (i = 1; i < GENERICSTACK_USED(marpaESLIFRecognizerp->lexemeStackp); i++) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_lexemeStack_i_p_and_sizeb(marpaESLIFRecognizerp, i, &matchedp, &matchedl))) {
          goto err;
        }
        /* Get the code point from the UTF-8 representation */
        utf82ordi = _marpaESLIF_utf82ordi((PCRE2_SPTR8) matchedp, &codepointi, (PCRE2_SPTR8) (matchedp + matchedl));
        if (MARPAESLIF_UNLIKELY(utf82ordi <= 0)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Malformed UTF-8 character at offset %d", -utf82ordi);
          errno = EINVAL;
          goto err;
        } else if (MARPAESLIF_UNLIKELY(utf82ordi != (int) matchedl)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Not all bytes consumed: %d instead of %ld", utf82ordi, (unsigned long) matchedl);
          errno = EINVAL;
          goto err;
        }
        /* Determine the number of hex digits to fully represent the code point, remembering if we need PCRE2_UTF flag */
        if (codepointi > 0xFF) {
          utfflagb = 1;
          break;
        }
      }
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: regex content scanned and give UTF=%d", terminalp->descp->asciis, strings, utfflagb);
      /* Detected the need of UTF flag in the regex ? */
      if (utfflagb) {
        pcre2Optioni |= PCRE2_UTF;
      }
    }

    /* Apply user options */
    switch (type) {
    case MARPAESLIF_TERMINAL_TYPE_STRING:
    case MARPAESLIF_TERMINAL_TYPE_REGEX:
      if (modifiers != NULL) {
        modifiersp = modifiers;
        while ((modifierc = *modifiersp++) != '\0') {
          modifierFoundb = 0;
          if (substitutionb) {
            /* Special case of substitution - it is restricted to strings */
            if (type == MARPAESLIF_TERMINAL_TYPE_STRING) {
              /* Checks all possible substitution modifiers and will naturelly bail if it is unknown. */
              for (i = 0; i < (sizeof(marpaESLIF_substitution_option_map) / sizeof(marpaESLIF_substitution_option_map[0])); i++) {
                if (modifierc == marpaESLIF_substitution_option_map[i].modifierc) {
                  /* It is important to process pcre2OptionNoti first */
                  if (marpaESLIF_substitution_option_map[i].pcre2OptionNoti != 0) {
                    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s: substitution modifier %c: removing %s", terminalp->descp->asciis, marpaESLIF_substitution_option_map[i].modifierc, marpaESLIF_substitution_option_map[i].pcre2OptionNots);
                    pcre2Optioni &= ~marpaESLIF_substitution_option_map[i].pcre2OptionNoti;
                  }
                  if (marpaESLIF_substitution_option_map[i].pcre2Optioni != 0) {
                    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s: substitution modifier %c: adding %s", terminalp->descp->asciis, marpaESLIF_substitution_option_map[i].modifierc, marpaESLIF_substitution_option_map[i].pcre2Options);
                    pcre2Optioni |= marpaESLIF_substitution_option_map[i].pcre2Optioni;
                  }
                  modifierFoundb = 1;
                  break;
                }
              }
            }
          } else {
            /* String modifiers are a subset of regex modifiers. We have to filter ourself to detect */
            /* if the modifier is allowed. */
            /* Regex mode checks all possible regexp modifiers and will naturelly bail if it is unknown. */
            if (((type == MARPAESLIF_TERMINAL_TYPE_STRING) && ((modifierc == 'i') || (modifierc == 'c'))) ||
                (type == MARPAESLIF_TERMINAL_TYPE_REGEX)) {
              for (i = 0; i < (sizeof(marpaESLIF_regex_option_map) / sizeof(marpaESLIF_regex_option_map[0])); i++) {
                if (modifierc == marpaESLIF_regex_option_map[i].modifierc) {
                  /* It is important to process pcre2OptionNoti first */
                  if (marpaESLIF_regex_option_map[i].pcre2OptionNoti != 0) {
                    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s: regex modifier %c: removing %s", terminalp->descp->asciis, marpaESLIF_regex_option_map[i].modifierc, marpaESLIF_regex_option_map[i].pcre2OptionNots);
                    pcre2Optioni &= ~marpaESLIF_regex_option_map[i].pcre2OptionNoti;
                  }
                  if (marpaESLIF_regex_option_map[i].pcre2Optioni != 0) {
                    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s: regex modifier %c: adding %s", terminalp->descp->asciis, marpaESLIF_regex_option_map[i].modifierc, marpaESLIF_regex_option_map[i].pcre2Options);
                    pcre2Optioni |= marpaESLIF_regex_option_map[i].pcre2Optioni;
                  }
                  modifierFoundb = 1;
                  break;
                }
              }
            }
          }
          if (MARPAESLIF_UNLIKELY(! modifierFoundb)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "Unsupported modifier '%c'", modifierc);
            errno = EINVAL;
            goto err;
          }
        }
      }
      break;
    default:
      MARPAESLIF_ERRORF(marpaESLIFp, "Unsupported terminal type %d", type);
      errno = EINVAL;
      goto err;
    }

    if (! substitutionb) {
      /* We want to support callouts, that requires a compile context */
      terminalp->regex.compile_contextp = pcre2_compile_context_create(NULL);
      if (MARPAESLIF_UNLIKELY(terminalp->regex.compile_contextp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "pcre2_compile_context_create, %s", strerror(errno));
        goto err;
      }

      /* Documentation says that the result of this function is always 0 ;) */
      pcre2_set_character_tables(terminalp->regex.compile_contextp, marpaESLIFp->tablesp);

      if (utf8s == NULL) {
        /* Case of the empty string => empty pattern */
        /* Note that this is different from // in the grammar: // is NOT recognized as a valid regex */
        terminalp->regex.patternp = pcre2_compile(
                                                  (PCRE2_SPTR) "",
                                                  (PCRE2_SIZE) 0,
                                                  pcre2Optioni,
                                                  &pcre2Errornumberi, /* for error number */
                                                  &pcre2ErrorOffsetl, /* for error offset */
                                                  terminalp->regex.compile_contextp);
      } else {
        terminalp->regex.patternp = pcre2_compile(
                                                  (PCRE2_SPTR) utf8s,      /* An UTF-8 pattern */
                                                  (PCRE2_SIZE) utf8l,      /* In code units (!= code points) - in UTF-8 a code unit is a byte */
                                                  pcre2Optioni,
                                                  &pcre2Errornumberi, /* for error number */
                                                  &pcre2ErrorOffsetl, /* for error offset */
                                                  terminalp->regex.compile_contextp);
      }
      if (MARPAESLIF_UNLIKELY(terminalp->regex.patternp == NULL)) {
        pcre2_get_error_message(pcre2Errornumberi, pcre2ErrorBuffer, sizeof(pcre2ErrorBuffer));
        MARPAESLIF_ERRORF(marpaESLIFp, "%s: pcre2_compile failure at offset %ld: %s", terminalp->descp->asciis, (unsigned long) pcre2ErrorOffsetl, pcre2ErrorBuffer);
        if (marpaESLIFRecognizerp != NULL) {
          MARPAESLIFRECOGNIZER_HEXDUMPV(funcs, marpaESLIFRecognizerp, "Dump of PCRE2 pattern", " as an UTF-8 sequence of bytes", utf8s, utf8l, 0 /* traceb */, 0 /* noticeb */, 0 /* linel */, 0 /* columnl */);
        }
        goto err;
      }

      /* Set the calloutb flag */
      enumerate_context.marpaESLIFp = NULL; /* Setting NULL here is a hack just to have the calloutb set and nothing else */
      enumerate_context.asciishows  = NULL;
      enumerate_context.asciishowl  = 0;
      enumerate_context.calloutb    = 0;
      pcre2_callout_enumerate(terminalp->regex.patternp, _marpaESLIF_pcre2_callout_enumeratei, &enumerate_context);
      terminalp->regex.calloutb = enumerate_context.calloutb;

      /* Set match context in any case */
      terminalp->regex.match_contextp = pcre2_match_context_create(NULL);
      if (MARPAESLIF_UNLIKELY(terminalp->regex.match_contextp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "pcre2_match_context_create failure, %s", strerror(errno));
        goto err;
      }

      /* Prepare the callout context. This is almost static, only marpaESLIFRecognizerp will change at every call */
      /* Note that this is ok because ESLIF is always sequential in the recognizer phase.                         */
      terminalp->regex.callout_context.terminalp = terminalp;
      pcre2_set_callout(terminalp->regex.match_contextp, _marpaESLIF_pcre2_callouti, &(terminalp->regex.callout_context));

      /* Set match data */
      terminalp->regex.match_datap = pcre2_match_data_create_from_pattern(terminalp->regex.patternp, NULL /* Default memory allocation */);
      if (MARPAESLIF_UNLIKELY(terminalp->regex.match_datap == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "%s: pcre2_match_data_create_from_pattern failure, %s", terminalp->descp->asciis, strerror(errno));
        goto err;
      }

      /* Determine if we can do JIT */
#ifdef PCRE2_CONFIG_JIT
      if ((pcre2_config(PCRE2_CONFIG_JIT, &pcre2Optioni) >= 0) && (pcre2Optioni == 1)) {
        terminalp->regex.jitb = (pcre2_jit_compile(terminalp->regex.patternp, PCRE2_JIT_COMPLETE|PCRE2_JIT_PARTIAL_HARD) == 0) ? 1 : 0;
      }
#endif /*  PCRE2_CONFIG_JIT */

      /* Even if JIT compiles ok, the pattern may have said (*NO_JIT) and the only way to know about that */
      /* is to check PCRE2_INFO_JITSIZE */
      if (terminalp->regex.jitb) {
        pcre2Errornumberi = pcre2_pattern_info(terminalp->regex.patternp, PCRE2_INFO_JITSIZE, &pcre2JitOptionl);
        if (MARPAESLIF_UNLIKELY(pcre2Errornumberi != 0)) {
          pcre2_get_error_message(pcre2Errornumberi, pcre2ErrorBuffer, sizeof(pcre2ErrorBuffer));
          MARPAESLIF_ERRORF(marpaESLIFp, "%s: pcre2_pattern_info failure: %s", terminalp->descp->asciis, pcre2ErrorBuffer);
          goto err;
        }
        if (pcre2JitOptionl == 0) {
          MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s: JIT size empty in regex - disabling JIT match", terminalp->descp->asciis);
          terminalp->regex.jitb = 0;
        }
      }

      /* And some modes after the pattern was allocated */
      pcre2Errornumberi = pcre2_pattern_info(terminalp->regex.patternp, PCRE2_INFO_ALLOPTIONS, &pcre2Optioni);
      if (MARPAESLIF_UNLIKELY(pcre2Errornumberi != 0)) {
        pcre2_get_error_message(pcre2Errornumberi, pcre2ErrorBuffer, sizeof(pcre2ErrorBuffer));
        MARPAESLIF_ERRORF(marpaESLIFp, "%s: pcre2_pattern_info failure: %s", terminalp->descp->asciis, pcre2ErrorBuffer);
        goto err;
      }
      terminalp->regex.utfb        = ((pcre2Optioni & PCRE2_UTF) == PCRE2_UTF);
      terminalp->regex.isAnchoredb = ((pcre2Optioni & PCRE2_ANCHORED) == PCRE2_ANCHORED);
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s: UTF mode is %s, Anchored mode is %s",
                        terminalp->descp->asciis,
                        terminalp->regex.utfb ? "on" : "off",
                        terminalp->regex.isAnchoredb ? "on" : "off"
                        );
    }
    break;

  default:
    MARPAESLIF_ERRORF(marpaESLIFp, "%s: Unsupported terminal type %d", terminalp->descp->asciis, type);
    errno = EINVAL;
    goto err;
    break;
  }

  if (memcmpb) {
    /* Commit bytel and put a NUL byte for convenience */
    /* We guaranteed that this buffer is large enough at the beginning */
    terminalp->bytel = bytel;
    terminalp->bytes[bytel] = '\0';
  }

#ifndef MARPAESLIF_NTRACE
  if (! substitutionb) {
    /* Fake a recognizer. EOF flag will be set automatically in fake mode */
    marpaESLIFRecognizerTestp = __marpaESLIFRecognizer_newp(marpaESLIFp,
                                                            NULL, /* grammarp */
                                                            NULL, /* marpaESLIFRecognizerOptionp */
                                                            0, /* discardb - not used anyway because we are in fake mode */
                                                            1, /* noEventb - not used anyway because we are in fake mode */
                                                            0, /* silentb */
                                                            NULL, /* marpaESLIFRecognizerParentp */
                                                            1, /* fakeb */
                                                            0, /* maxStartCompletionsi */
                                                            1, /* Internal tests are always done on UTF-8 valid strings */
                                                            0 /* isLexemeb */);
    if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerTestp == NULL)) {
      goto err;
    }

    /* Look to the implementations of terminal matchers: they NEVER use leveli, nor marpaWrapperGrammarp, nor grammarStackp -; */
    /* Also, note that we always end up with a regex. */
    
    if (testFullMatchs != NULL) {

      marpaESLIF_streamp = marpaESLIFRecognizerTestp->marpaESLIF_streamp;
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizerTestp, marpaESLIF_streamp, terminalp, testFullMatchs, strlen(testFullMatchs), 1, &rci, NULL /* marpaESLIFValueResultp */, &matchedLengthl))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "%s: testing full match: matcher general failure", terminalp->descp->asciis);
        errno = EINVAL;
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(rci != MARPAESLIF_MATCH_OK)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "%s: testing full match: matcher returned rci = %d", terminalp->descp->asciis, rci);
        errno = EINVAL;
        goto err;
      }
      /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s: testing full match is successful on %s", terminalp->descp->asciis, testFullMatchs); */
    }

    if (testPartialMatchs != NULL) {

      marpaESLIF_streamp = marpaESLIFRecognizerTestp->marpaESLIF_streamp;
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizerTestp, marpaESLIF_streamp, terminalp, testPartialMatchs, strlen(testPartialMatchs), 0, &rci, NULL /* marpaESLIFValueResultp */, &matchedLengthl))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "%s: testing partial match: matcher general failure", terminalp->descp->asciis);
        errno = EINVAL;
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(rci != MARPAESLIF_MATCH_AGAIN)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "%s: testing partial match: matcher returned rci = %d", terminalp->descp->asciis, rci);
        errno = EINVAL;
        goto err;
      }
      /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s: testing partial match is successful on %s when not at EOF", terminalp->descp->asciis, testPartialMatchs); */
    }
  }

#endif

  /* Creation of PCRE2 pattern is ok - keep it for bootstrap comparison when creating grammars */
  terminalp->patterns = (char *) malloc(utf8l + 1); /* We always add a NUL byte for convenience */
  if (MARPAESLIF_UNLIKELY(terminalp->patterns == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }
  memcpy(terminalp->patterns, utf8s, utf8l);
  terminalp->patterns[utf8l] = '\0';
  terminalp->patternl = utf8l;
  terminalp->patterni = pseudob ? 0 : pcre2Optioni;
  terminalp->type     = type;

  /* For strings and characters classes, lookup the first 256 ASCII or UTF-8 characters for predicted failures */
  if ((! substitutionb) && terminalp->regex.isAnchoredb && ((terminalp->type == MARPAESLIF_TERMINAL_TYPE_STRING) || characterClassb)) {

    /* Fake a recognizer. EOF flag will be set automatically in fake mode */
    marpaESLIFRecognizer_freev(marpaESLIFRecognizerp); /* NULL protected */
    marpaESLIFRecognizerp = __marpaESLIFRecognizer_newp(marpaESLIFp,
                                                        NULL, /* grammarp */
                                                        NULL, /* marpaESLIFRecognizerOptionp */
                                                        0, /* discardb - not used anyway because we are in fake mode */
                                                        1, /* noEventb - not used anyway because we are in fake mode */
                                                        0, /* silentb */
                                                        NULL, /* marpaESLIFRecognizerParentp */
                                                        1, /* fakeb */
                                                        0, /* maxStartCompletionsi */
                                                        1, /* Here we know input is UTF-8 valid */
                                                        0 /* isLexemeb */);
    if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
      goto err;
    }
    marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;

    for (i = 0, utf8_2_bytes_maxp = utf8_2_bytes_max_arrayp; i < 256; i++, utf8_2_bytes_maxp++) {
      if (terminalp->regex.utfb) {
        /* Take care, we voluntarily set eofb to false */
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizerp, marpaESLIF_streamp, terminalp, utf8_2_bytes_maxp->s, utf8_2_bytes_maxp->lengthl /* inputl */, 0 /* eofb */, &rci, &marpaESLIFValueResult, &matchedLengthl))) {
          goto err;
        }

        terminalp->byte2failureb = 0;
        terminalp->utf2failureb = 1;
        switch (rci) {
        case MARPAESLIF_MATCH_OK:
          terminalp->willfailutfb[i] = 0;
          _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, &marpaESLIFValueResult);
          break;
        case MARPAESLIF_MATCH_AGAIN:
          terminalp->willfailutfb[i] = 0;
          break;
        default:
          terminalp->willfailutfb[i] = 1;
          break;
        }
      } else {
        uc = (unsigned char) i;

        /* Take care, we voluntarily set eofb to false */
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizerp, marpaESLIF_streamp, terminalp, (char *) &uc /* inputs */, 1 /* inputl */, 0 /* eofb */, &rci, &marpaESLIFValueResult, &matchedLengthl))) {
          goto err;
        }

        terminalp->byte2failureb = 1;
        terminalp->utf2failureb = 0;
        switch (rci) {
        case MARPAESLIF_MATCH_OK:
          terminalp->willfailasciib[i] = 0;
          _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, &marpaESLIFValueResult);
          break;
        case MARPAESLIF_MATCH_AGAIN:
          terminalp->willfailasciib[i] = 0;
          break;
        default:
          terminalp->willfailasciib[i] = 1;
          break;
        }
      }
    }
    marpaESLIFRecognizer_freev(marpaESLIFRecognizerp);
    marpaESLIFRecognizerp = NULL;
  } else {
    terminalp->byte2failureb = 0;
    terminalp->utf2failureb = 0;
  }

  goto done;
  
 err:
  _marpaESLIF_terminal_freev(terminalp);
  terminalp = NULL;

 done:
  if (strings != NULL) {
    free(strings);
  }
  if (generatedasciis != NULL) {
    free(generatedasciis);
  }
  _marpaESLIF_string_freev(content2descp, 0 /* onStackb */);
#ifndef MARPAESLIF_NTRACE
  marpaESLIFRecognizer_freev(marpaESLIFRecognizerTestp); /* NULL protected */
#endif
  marpaESLIFRecognizer_freev(marpaESLIFRecognizerp); /* NULL protected */
  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", terminalp); */
  return terminalp;
}

/*****************************************************************************/
static inline marpaESLIF_meta_t *_marpaESLIF_meta_newp(marpaESLIF_t *marpaESLIFp, marpaWrapperGrammar_t *marpaWrapperGrammarp, int eventSeti, char *asciinames, char *descEncodings, char *descs, size_t descl, short lazyb)
/*****************************************************************************/
{
  static const char                *funcs = "_marpaESLIF_meta_newp";
  marpaESLIF_meta_t                *metap = NULL;
  marpaWrapperGrammarSymbolOption_t marpaWrapperGrammarSymbolOption;

  /* MARPAESLIF_TRACE(marpaESLIFp, funcs, "Building meta"); */

  if (MARPAESLIF_UNLIKELY(asciinames == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "No name for meta symbol");
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(strlen(asciinames) <= 0)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Meta symbol name is empty");
    goto err;
  }

  metap = (marpaESLIF_meta_t *) malloc(sizeof(marpaESLIF_meta_t));
  if (MARPAESLIF_UNLIKELY(metap == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  metap->idi                              = -1;
  metap->asciinames                       = NULL;
  metap->descp                            = NULL;
  metap->marpaWrapperGrammarStartp        = NULL; /* Changed when validating the grammar */
  metap->marpaWrapperGrammarStartNoEventp = NULL; /* Changed when validating the grammar */
  metap->lexemeIdi                        = -1;   /* Ditto */
  metap->prioritizedb                     = 0;    /* Internal flag to prevent a prioritized symbol to appear more than once as an LHS */
  metap->marpaESLIFGrammarLexemeClonep    = NULL; /* Changed when validating the grammar */
  metap->nTerminalPristinel               = 0;    /* Number of terminals at the very beginning of marpaWrapperGrammarStartp */
  metap->terminalIdArrayPristinep         = NULL; /* Grammar terminals at the very beginning of marpaWrapperGrammarStartp (Ids) */
  metap->terminalArrayPristinepp          = NULL; /* Grammar terminals at the very beginning of marpaWrapperGrammarStartp (Symbols ordered by priority) */
  metap->nTerminall                       = 0;    /* Number of grammar terminals of marpaWrapperGrammarStartp */
  metap->symbolArraypp                    = NULL; /* Grammar terminals of marpaWrapperGrammarp (Symbols ordered by priority) */
  metap->lazyb                            = lazyb;
  metap->eventSeti                        = eventSeti;

  marpaWrapperGrammarSymbolOption.terminalb = 0;
  marpaWrapperGrammarSymbolOption.startb    = 0;
  marpaWrapperGrammarSymbolOption.eventSeti = eventSeti;

  /* -------- Meta name -------- */
  metap->asciinames = strdup(asciinames);
  if (MARPAESLIF_UNLIKELY(metap->asciinames == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
    goto err;
  }

  /* -------- Meta Description - default to meta name -------- */
  if ((descs == NULL) || (descl <= 0)) {
    metap->descp = _marpaESLIF_string_newp(marpaESLIFp, "ASCII", asciinames, strlen(asciinames));
  } else {
    metap->descp = _marpaESLIF_string_newp(marpaESLIFp, descEncodings, descs, descl);
  }
  if (MARPAESLIF_UNLIKELY(metap->descp == NULL)) {
    goto err;
  }

  /* ----------- Meta Identifier ------------ */
  metap->idi = marpaWrapperGrammar_newSymboli(marpaWrapperGrammarp, &marpaWrapperGrammarSymbolOption);
  if (MARPAESLIF_UNLIKELY(metap->idi < 0)) {
    goto err;
  }

  goto done;

 err:
  _marpaESLIF_meta_freev(metap);
  metap = NULL;

 done:
  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", metap); */
  return metap;
}

/*****************************************************************************/
static inline void _marpaESLIF_meta_freev(marpaESLIF_meta_t *metap)
/*****************************************************************************/
{
  if (metap != NULL) {
    if (metap->asciinames != NULL) {
      free(metap->asciinames);
    }
    _marpaESLIF_string_freev(metap->descp, 0 /* onStackb */);
    if (metap->marpaWrapperGrammarStartp != NULL) {
      marpaWrapperGrammar_freev(metap->marpaWrapperGrammarStartp);
    }
    if (metap->marpaWrapperGrammarStartNoEventp != NULL) {
      marpaWrapperGrammar_freev(metap->marpaWrapperGrammarStartNoEventp);
    }
    if (metap->terminalIdArrayPristinep != NULL) {
      free(metap->terminalIdArrayPristinep);
    }
    if (metap->terminalArrayPristinepp != NULL) {
      free(metap->terminalArrayPristinepp);
    }
    if (metap->symbolArraypp != NULL) {
      free(metap->symbolArraypp);
    }

    /* All the rest are shallow pointers - in particular marpaESLIFGrammarLexemeClonep is a hack for performance reasons */
    free(metap);
  }
}

/*****************************************************************************/
static inline marpaESLIF_grammar_t *_marpaESLIF_bootstrap_grammar_L0p(marpaESLIFGrammar_t *marpaESLIFGrammarp, short withLazyb)
/*****************************************************************************/
{
  return _marpaESLIF_bootstrap_grammarp(marpaESLIFGrammarp,
					1, /* L0 in Marpa::R2 terminology is level No 1 for us */
                                        "ASCII", /* "L0" is an ASCII thingy */
                                        "L0",
                                        strlen("L0"),
					0, /* warningIsErrorb */
					1, /* warningIsIgnoredb */
					0, /* autorankb */
					sizeof(bootstrap_grammar_L0_terminals) / sizeof(bootstrap_grammar_L0_terminals[0]),
					bootstrap_grammar_L0_terminals,
					sizeof(bootstrap_grammar_L0_metas) / sizeof(bootstrap_grammar_L0_metas[0]),
					bootstrap_grammar_L0_metas,
					sizeof(bootstrap_grammar_L0_rules) / sizeof(bootstrap_grammar_L0_rules[0]),
					bootstrap_grammar_L0_rules,
					0, /* No L0 lazy rule: withLazyb ? sizeof(bootstrap_grammar_L0_lazy_rules) / sizeof(bootstrap_grammar_L0_lazy_rules[0]) : 0, */
					NULL, /* No L0 lazy rule: withLazyb ? bootstrap_grammar_L0_lazy_rules : NULL, */
                                        NULL, /* defaultSymbolActionp */
                                        NULL, /* defaultRuleActionp */
                                        NULL, /* defaultEventActionp */
                                        NULL, /* defaultRegexActionp */
                                        "ASCII", /* defaultEncodings" */
                                        NULL /* fallbackEncodings */ );
}

/*****************************************************************************/
static inline marpaESLIF_grammar_t *_marpaESLIF_bootstrap_grammar_G1p(marpaESLIFGrammar_t *marpaESLIFGrammarp, short withLazyb)
/*****************************************************************************/
{
  return _marpaESLIF_bootstrap_grammarp(marpaESLIFGrammarp,
					0, /* G1 in Marpa::R2 terminology is level No 0 for us */
                                        "ASCII", /* "G1" is an ASCII thingy */
                                        "G1",
                                        strlen("G1"),
					0, /* warningIsErrorb */
					1, /* warningIsIgnoredb */
					0, /* autorankb */
					sizeof(bootstrap_grammar_G1_terminals) / sizeof(bootstrap_grammar_G1_terminals[0]),
					bootstrap_grammar_G1_terminals,
					sizeof(bootstrap_grammar_G1_metas) / sizeof(bootstrap_grammar_G1_metas[0]),
					bootstrap_grammar_G1_metas,
					sizeof(bootstrap_grammar_G1_rules) / sizeof(bootstrap_grammar_G1_rules[0]),
					bootstrap_grammar_G1_rules,
					withLazyb ? sizeof(bootstrap_grammar_G1_lazy_rules) / sizeof(bootstrap_grammar_G1_lazy_rules[0]) : 0,
					withLazyb ? bootstrap_grammar_G1_lazy_rules : NULL,
                                        NULL, /* defaultSymbolActionp */
                                        NULL, /* defaultRuleActionp */
                                        NULL, /* defaultEventActionp */
                                        NULL, /* defaultRegexActionp */
                                        "ASCII", /* defaultEncodings" */
                                        NULL /* fallbackEncodings */ );
}

/*****************************************************************************/
static inline marpaESLIF_grammar_t *_marpaESLIF_bootstrap_grammarp(marpaESLIFGrammar_t *marpaESLIFGrammarp,
								   int leveli,
                                                                   char *descEncodings,
                                                                   char *descs,
                                                                   size_t descl,
								   short warningIsErrorb,
								   short warningIsIgnoredb,
								   short autorankb,
								   int bootstrap_grammar_terminali, bootstrap_grammar_terminal_t *bootstrap_grammar_terminalp,
								   int bootstrap_grammar_metai, bootstrap_grammar_meta_t *bootstrap_grammar_metap,
								   int bootstrap_grammar_rulei, bootstrap_grammar_rule_t *bootstrap_grammar_rulep,
                                                                   int bootstrap_grammar_lazy_rulei, bootstrap_grammar_rule_t *bootstrap_grammar_lazy_rulep,
                                                                   marpaESLIF_action_t *defaultSymbolActionp,
                                                                   marpaESLIF_action_t *defaultRuleActionp,
                                                                   marpaESLIF_action_t *defaultEventActionp,
                                                                   marpaESLIF_action_t *defaultRegexActionp,
                                                                   char *defaultEncodings,
                                                                   char *fallbackEncodings)
/*****************************************************************************/
{
  static const char          *funcs        = "_marpaESLIF_bootstrap_grammarp";
  marpaESLIF_t               *marpaESLIFp  = marpaESLIFGrammarp->marpaESLIFp;
  marpaESLIF_symbol_t        *symbolp      = NULL;
  marpaESLIF_rule_t          *rulep        = NULL;
  marpaESLIF_terminal_t      *terminalp    = NULL;
  marpaESLIF_meta_t          *metap        = NULL;
  marpaESLIF_grammar_t       *grammarp;
  marpaWrapperGrammarOption_t marpaWrapperGrammarOption;
  int                         i;
  marpaESLIF_action_t         ruleAction;

  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Bootstrapping grammar at level %d", (int) leveli);

  marpaWrapperGrammarOption.genericLoggerp    = marpaESLIFp->marpaESLIFOption.genericLoggerp;
  marpaWrapperGrammarOption.warningIsErrorb   = warningIsErrorb;
  marpaWrapperGrammarOption.warningIsIgnoredb = warningIsIgnoredb;
  marpaWrapperGrammarOption.autorankb         = autorankb;

  /* Default type of rule action, value itself is filled in the loop */
  ruleAction.type = MARPAESLIF_ACTION_TYPE_NAME;
  
  grammarp = _marpaESLIF_grammar_newp(marpaESLIFGrammarp, &marpaWrapperGrammarOption, leveli, descEncodings, descs, descl, defaultSymbolActionp, defaultRuleActionp, defaultEventActionp, defaultRegexActionp, defaultEncodings, fallbackEncodings);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    goto err;
  }

  /* We hardcode discardIsFallback for the bootstrap grammar */
  grammarp->discardIsFallbackb = 1;

  /* First the terminals */
  for (i = 0; i < bootstrap_grammar_terminali; i++) {
    symbolp = _marpaESLIF_symbol_newp(marpaESLIFp, NULL /* marpaESLIFSymbolOptionp */);
    if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
      goto err;
    }
    if (bootstrap_grammar_terminalp[i].eventBefores != NULL) {
      symbolp->eventBefores = strdup(bootstrap_grammar_terminalp[i].eventBefores);
      if (MARPAESLIF_UNLIKELY(symbolp->eventBefores == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
    if (bootstrap_grammar_terminalp[i].eventAfters != NULL) {
      symbolp->eventAfters = strdup(bootstrap_grammar_terminalp[i].eventAfters);
      if (MARPAESLIF_UNLIKELY(symbolp->eventAfters == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }

    terminalp = _marpaESLIF_terminal_newp(marpaESLIFp,
					  grammarp->marpaWrapperGrammarStartp,
					  MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE,
                                          NULL, /* descEncodings */
					  NULL, /* descs */
                                          0, /* descl */
					  bootstrap_grammar_terminalp[i].terminalType,
					  bootstrap_grammar_terminalp[i].modifiers,
					  bootstrap_grammar_terminalp[i].utf8s,
					  (bootstrap_grammar_terminalp[i].utf8s != NULL) ? strlen(bootstrap_grammar_terminalp[i].utf8s) : 0,
					  bootstrap_grammar_terminalp[i].testFullMatchs,
					  bootstrap_grammar_terminalp[i].testPartialMatchs,
                                          0, /* pseudob */
                                          bootstrap_grammar_terminalp[i].characterClassb,
                                          MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                          0 /* substitutionb */);
    if (MARPAESLIF_UNLIKELY(terminalp == NULL)) {
      goto err;
    }
    /* When bootstrapping the grammar, we expect terminal IDs to be exactly the value of the enum */
    if (MARPAESLIF_UNLIKELY(terminalp->idi != bootstrap_grammar_terminalp[i].idi)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "Got symbol ID %d from Marpa while we were expecting %d", terminalp->idi, bootstrap_grammar_terminalp[i].idi);
      goto err;
    }

    symbolp->type        = MARPAESLIF_SYMBOL_TYPE_TERMINAL;
    symbolp->u.terminalp = terminalp;
    symbolp->idi         = terminalp->idi;
    symbolp->descp       = terminalp->descp;
    /* Terminal is now in symbol */
    terminalp = NULL;

    GENERICSTACK_SET_PTR(grammarp->symbolStackp, symbolp, symbolp->idi);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarp->symbolStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "symbolStackp push failure, %s", strerror(errno));
      goto err;
    }
    /* Push is ok: symbolp is in grammarp->symbolStackp */
    symbolp = NULL;
  }

  /* Then the non-terminals */
  for (i = 0; i < bootstrap_grammar_metai; i++) {
    symbolp = _marpaESLIF_symbol_newp(marpaESLIFp, NULL /* marpaESLIFSymbolOptionp */);
    if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
      goto err;
    }
    if (bootstrap_grammar_metap[i].lookupLevelDeltai >= 0) {
      symbolp->lookupLevelDeltai = bootstrap_grammar_metap[i].lookupLevelDeltai;
    }
    symbolp->verboseb = bootstrap_grammar_metap[i].verboseb;
    if (bootstrap_grammar_metap[i].eventBefores != NULL) {
      symbolp->eventBefores = strdup(bootstrap_grammar_metap[i].eventBefores);
      if (MARPAESLIF_UNLIKELY(symbolp->eventBefores == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
    if (bootstrap_grammar_metap[i].eventAfters != NULL) {
      symbolp->eventAfters = strdup(bootstrap_grammar_metap[i].eventAfters);
      if (MARPAESLIF_UNLIKELY(symbolp->eventAfters == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }

    metap = _marpaESLIF_meta_newp(marpaESLIFp,
				  grammarp->marpaWrapperGrammarStartp,
				  MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE,
                                  bootstrap_grammar_metap[i].descs,
                                  NULL, /* descEncodings */
				  NULL, /* descs */
				  0, /* descl */
                                  bootstrap_grammar_metap[i].lazyb);
    if (MARPAESLIF_UNLIKELY(metap == NULL)) {
      goto err;
    }
    /* When bootstrapping the grammar, we expect meta IDs to be exactly the value of the enum */
    if (MARPAESLIF_UNLIKELY(metap->idi != bootstrap_grammar_metap[i].idi)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "Got symbol ID %d from Marpa while we were expecting %d", metap->idi, bootstrap_grammar_metap[i].idi);
      goto err;
    }

    symbolp->type       = MARPAESLIF_SYMBOL_TYPE_META;
    symbolp->startb     = bootstrap_grammar_metap[i].startb;
    symbolp->discardb   = bootstrap_grammar_metap[i].discardb;
    symbolp->u.metap    = metap;
    symbolp->idi        = metap->idi;
    symbolp->descp      = metap->descp;
    /* Meta is now in symbol */
    metap = NULL;

    /* Symbol :discard event ? We use only the nulled event for that btw */
    if (bootstrap_grammar_metap[i].discardonb) {
      symbolp->eventNulleds = strdup(":discard[on]");
      if (MARPAESLIF_UNLIKELY(symbolp->eventNulleds == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
      symbolp->eventNulledb = 1;
    }
    if (bootstrap_grammar_metap[i].discardoffb) {
      symbolp->eventNulleds = strdup(":discard[off]");
      if (MARPAESLIF_UNLIKELY(symbolp->eventNulleds == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
      symbolp->eventNulledb = 1;
    }

    GENERICSTACK_SET_PTR(grammarp->symbolStackp, symbolp, symbolp->idi);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarp->symbolStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "symbolStackp set failure, %s", strerror(errno));
      goto err;
    }
    /* Push is ok: symbolp is in grammarp->symbolStackp */
    symbolp = NULL;

  }

  /* Then the rules - bootstrap action are all external */
  for (i = 0; i < bootstrap_grammar_rulei; i++) {
    ruleAction.u.names = bootstrap_grammar_rulep[i].actions;
    rulep = _marpaESLIF_rule_newp(marpaESLIFp,
                                  grammarp->symbolStackp,
                                  grammarp->leveli,
                                  grammarp->marpaWrapperGrammarStartp,
                                  NULL, /* descEncodings */
                                  bootstrap_grammar_rulep[i].descs,
                                  strlen(bootstrap_grammar_rulep[i].descs),
				  bootstrap_grammar_rulep[i].lhsi,
				  bootstrap_grammar_rulep[i].nrhsl,
				  bootstrap_grammar_rulep[i].rhsip,
				  -1, /* exceptioni */
				  0, /* ranki */
				  0, /* nullRanksHighb */
				  (bootstrap_grammar_rulep[i].type == MARPAESLIF_RULE_TYPE_ALTERNATIVE) ? 0 : 1, /* sequenceb */
				  bootstrap_grammar_rulep[i].minimumi,
				  bootstrap_grammar_rulep[i].separatori,
				  bootstrap_grammar_rulep[i].properb,
                                  (ruleAction.u.names != NULL) ? &ruleAction : NULL,
                                  bootstrap_grammar_rulep[i].hideseparatorb,
                                  NULL, /* skipbp */
                                  NULL, /* declp */
                                  NULL, /* callpp */
                                  NULL /* separatorcallp */);
    if (MARPAESLIF_UNLIKELY(rulep == NULL)) {
      goto err;
    }
    GENERICSTACK_SET_PTR(grammarp->ruleStackp, rulep, rulep->idi);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarp->ruleStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "ruleStackp set failure, %s", strerror(errno));
      goto err;
    }
    /* Push is ok: rulep is in grammarp->ruleStackp */
    rulep = NULL;
  }

  /* Then the lazy rules */
  for (i = 0; i < bootstrap_grammar_lazy_rulei; i++) {
    ruleAction.u.names = bootstrap_grammar_lazy_rulep[i].actions;
    rulep = _marpaESLIF_rule_newp(marpaESLIFp,
                                  grammarp->symbolStackp,
                                  grammarp->leveli,
                                  grammarp->marpaWrapperGrammarStartp,
                                  NULL, /* descEncodings */
                                  bootstrap_grammar_lazy_rulep[i].descs,
                                  strlen(bootstrap_grammar_lazy_rulep[i].descs),
				  bootstrap_grammar_lazy_rulep[i].lhsi,
				  bootstrap_grammar_lazy_rulep[i].nrhsl,
				  bootstrap_grammar_lazy_rulep[i].rhsip,
				  -1, /* exceptioni */
				  0, /* ranki */
				  0, /* nullRanksHighb */
				  (bootstrap_grammar_lazy_rulep[i].type == MARPAESLIF_RULE_TYPE_ALTERNATIVE) ? 0 : 1, /* sequenceb */
				  bootstrap_grammar_lazy_rulep[i].minimumi,
				  bootstrap_grammar_lazy_rulep[i].separatori,
				  bootstrap_grammar_lazy_rulep[i].properb,
                                  (ruleAction.u.names != NULL) ? &ruleAction : NULL,
                                  bootstrap_grammar_lazy_rulep[i].hideseparatorb,
                                  NULL, /* skipbp */
                                  NULL, /* declp */
                                  NULL, /* callpp */
                                  NULL /* separatorcallp */);
    if (MARPAESLIF_UNLIKELY(rulep == NULL)) {
      goto err;
    }
    GENERICSTACK_SET_PTR(grammarp->ruleStackp, rulep, rulep->idi);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarp->ruleStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "ruleStackp set failure, %s", strerror(errno));
      goto err;
    }
    /* Push is ok: rulep is in grammarp->ruleStackp */
    rulep = NULL;
  }

  goto done;
  
 err:
  _marpaESLIF_terminal_freev(terminalp);
  _marpaESLIF_meta_freev(metap);
  _marpaESLIF_rule_freev(rulep);
  _marpaESLIF_symbol_freev(symbolp);
  _marpaESLIF_grammar_freev(grammarp);
  grammarp = NULL;

 done:
  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", grammarp); */
  return grammarp;
}

/*****************************************************************************/
static inline short _marpaESLIF_numberb(marpaESLIF_t *marpaESLIFp, char *s, size_t sizel, marpaESLIFValueResult_t *marpaESLIFValueResultp, short *confidencebp)
/*****************************************************************************/
{
  static const char                  *funcs       = "_marpaESLIFRecognizer_numberb";
  short                               confidenceb = 1; /* Set to 0 only when we got through the double case */
  char                               *bytes       = s;
  size_t                              bytel       = (sizel <= 0) ? strlen(s) : sizel; /* Remember the doc: caller must make sure it is NUL terminated if sizel is 0 */
  char                               *dups        = NULL; /* For the cases where we modify in place s, we want to restore it */
  char                               *numbers;
  size_t                              numberl;
  char                               *endptrendp;
  char                               *p;
  char                               *q;
  char                               *pmin;
  char                               *pmax;
  char                                dotc;
  char                                exponentc;
  char                               *exponentp;
  long                                exponentl;
  char                               *dotp;
  size_t                              numberOfUnsignificantDigitl;
  char                               *endptrp;
  size_t                              decimall;
  short                               isFloatb;
  short                               isNegb;
  size_t                              charsl;
  size_t                              prevCharsl;
  size_t                              l;
  size_t                              shiftl;
#if defined(MARPAESLIF_HAVE_LONG_LONG) && defined(C_STRTOLL)
  MARPAESLIF_LONG_LONG                valuell;
#else
  long                                valuel;
#endif
#if (defined(C_STRTOLD) && defined(MARPAESLIF_HUGE_VALL)) || (defined(C_STRTOD) && defined(MARPAESLIF_HUGE_VAL))
  short                               decimalPointb;
  char                               *decimalPoints;
#  if defined(C_STRTOLD) && defined(MARPAESLIF_HUGE_VALL)
  long double                         valueld;
#  else
  double                              valued;
#  endif
#endif
  marpaESLIFValueResult_t             marpaESLIFValueResult;
  /* Longest integer that we support */
#ifdef MARPAESLIF_HAVE_LONG_LONG
  char                                integers[MARPAESLIF_MAX_DECIMAL_DIGITS_LONGLONG + 1];
#else
  char                                integers[MARPAESLIF_MAX_DECIMAL_DIGITS_LONG + 1];
#endif
  short                               rcb;

  if (bytes[0] == '+') {
    MARPAESLIF_TRACE(marpaESLIFp, funcs, "Removing leading '+' sign");
    numbers = ++bytes;
    numberl = --bytel;
  } else {
    numbers = bytes;
    numberl = bytel;
  }

  /* From now on the work area is numbers, with numberl ASCII characters, ending with a '\0' at indice numberl */
  endptrendp = numbers + numberl;

  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %ld bytes", (int) numberl, numbers, (unsigned long) numberl);

  /* Look for the eventual exponent */
  exponentp = NULL;
  for (p = endptrendp - 1; p >= numbers; p--) {
    exponentc = *p;
    if ((exponentc == 'e') || (exponentc == 'E')) {
      exponentp = p;
      break;
    }
  }

  /* Look for the eventual dot */
  dotp = NULL;
  for (p = numbers; p < endptrendp; p++) {
    dotc = *p;
    if (dotc == '.') {
      dotp = p;
      break;
    }
  }

  /* Remove non significant digits on the left, not possible with the strict grammar */

  /* Locate where the scanning will start */
  pmin = numbers;
  if (*pmin == '-') {
    pmin++;
  }

  /* Locate where the scanning will stop */
  if (dotp != NULL) {
    /* Dot character is present */
    pmax = dotp;
  } else if (exponentp != NULL) {
    /* No dot character but there is the exponent character */
    pmax = exponentp;
  } else {
    /* The string is made only with digits */
    pmax = endptrendp;
  }

  numberOfUnsignificantDigitl = 0;
  for (p = pmin; p < pmax; p++) {
    if (*p != '0') {
      break;
    }
    numberOfUnsignificantDigitl++;
  }

  if ((numberOfUnsignificantDigitl > 0) && (p == pmax)) {
    /* We want to retain at least one digit before the dot, e.g. we do not want to remove everything */

    /* If we match:  */
    /* 000000.456000 */
    /* ^pmin         */
    /*       ^pmax   */
    /*       ^p      */
    /*               */
    /* we change to: */
    /* 000000.456000 */
    /* ^pmin         */
    /*       ^pmax   */
    /*      ^p       */
    if (--numberOfUnsignificantDigitl > 0) {
      --p;
    }
  }

  if (numberOfUnsignificantDigitl > 0) {
    /* Note that is guaranteed that p < pmax */

    /* 000123.456000 */
    /* ^pmin         */
    /*       ^pmax   */
    /*    ^p         */

    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: Removing %ld non significant left digits", (int) numberl, numbers, (unsigned long) numberOfUnsignificantDigitl);
    /* We modify the input in place, keep a copy for restoring at the end */
    dups = strdup(s);
    if (MARPAESLIF_UNLIKELY(dups == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
    memmove(pmin, p, endptrendp - p + 1); /* + 1 for the NUL byte */

    /* Impact of the memmove() */
    numberl -= numberOfUnsignificantDigitl;
    endptrendp -= numberOfUnsignificantDigitl;
    if (dotp != NULL) {
      dotp -= numberOfUnsignificantDigitl;
    }
    if (exponentp != NULL) {
      exponentp -= numberOfUnsignificantDigitl;
    }

    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: Now %ld bytes", (int) numberl, numbers, (unsigned long) numberl);
  }

  /* Remove non significant digits after the dot character. */
  if (dotp != NULL) {
    pmin = dotp + 1;
    if (exponentp != NULL) {
      pmax = exponentp;
    } else {
      pmax = endptrendp;
    }

    numberOfUnsignificantDigitl = 0;
    /* We voluntarily say p > pmin so that */
    /* we always retain at least one digit */
    /* after the dot.                      */
    for (p = pmax - 1; p > pmin; p--) {
      if (*p != '0') {
        break;
      }
      numberOfUnsignificantDigitl++;
    }

    if ((numberOfUnsignificantDigitl > 0) || ((p == pmin) && (*p == '0'))) {
      /* It is guaranteed that numberOfUnsignificantDigitl is < total number of digits after the dot. */

      if ((p == pmin) && (*p == '0')) {
        /* Special case of (p == pmin) && (*p == '0'), then it means that it something like e.g.; */
        /* 123.000000      */
        /*    ^dotp        */
        /*     ^pmin       */
        /*           ^pmax */
        /*     ^p          */
        numberOfUnsignificantDigitl += 2;
        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: Removing the dot part", (int) numberl, numbers, (unsigned long) numberOfUnsignificantDigitl);
        if (dups == NULL) {
          /* No backup copy yet */
          dups = strdup(s);
          if (MARPAESLIF_UNLIKELY(dups == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
            goto err;
          }
        }
        memmove(dotp, pmax, endptrendp - pmax + 1); /* + 1 for the NUL byte */
        dotp = NULL;
      } else {
        /* 123.456000      */
        /*     ^pmin       */
        /*           ^pmax */
        /*       ^p        */
        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: Removing %ld non significant right digits", (int) numberl, numbers, (unsigned long) numberOfUnsignificantDigitl);
        ++p;
        if (dups == NULL) {
          /* No backup copy yet */
          dups = strdup(s);
          if (MARPAESLIF_UNLIKELY(dups == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
            goto err;
          }
        }
        memmove(p, pmax, endptrendp - pmax + 1); /* + 1 for the NUL byte */
      }

      /* Impact of the memmove() */
      numberl -= numberOfUnsignificantDigitl;
      endptrendp -= numberOfUnsignificantDigitl;
      if (exponentp != NULL) {
        exponentp -= numberOfUnsignificantDigitl;
      }

      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: Now %ld bytes", (int) numberl, numbers, (unsigned long) numberl);
    }
  }

  /* We now have a number with no unsignificant digit. We want to know if this is a true floating point number. */

  /* If there is an exponent, take its value - we assume that using a long is fair enough. */
  if (exponentp == NULL) {
    exponentl = 0;
  } else {
    endptrp = NULL;
    errno = 0;    /* To distinguish success/failure after call */
    exponentl = strtol(exponentp + 1, &endptrp, 10);
    /* Note that the exponent in a JSON number always have at least one digit */
    if ((endptrp != endptrendp) || (errno != 0)) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: Exponent parsing failure", (int) numberl, numbers, errno != 0 ? strerror(errno) : "bad final pointer");
      goto parsing_to_double;
    }
  }

  if (dotp == NULL) {
    decimall = 0;
  } else {
    pmin = dotp + 1;
    if (exponentp != NULL) {
      pmax = exponentp;
    } else {
      pmax = endptrendp;
    }
    decimall = pmax - pmin;
  }

  /* Check the eventual signedness */
  isNegb = (numbers[0] == '-') ? 1 : 0;

  /* Count the total number of digits needed to represent this non-floating number.                              */
  /* Take care: decimall is unsigned; exponentl is signed and will be converted to unsigned if we do comparison. */
  /* The value of charsl is guaranteed to be set only if isFloatb == 0.                                          */
  if (decimall == 0) {
    if (exponentl < 0) {
      isFloatb = 1;
    } else {
      isFloatb = 0;
      if (exponentp != NULL) {
        /* [-]123E[+]789 */
        charsl = exponentp - numbers;
        prevCharsl = charsl;
        charsl += exponentl;
        if (MARPAESLIF_UNLIKELY(charsl < prevCharsl)) { /* Turnaround */
          goto parsing_to_double;
        }
      } else {
        /* [-]123 */
        charsl = numberl;
      }
    }
  } else {
    /* Per def decimall here is > 0 */
    if (exponentl <= 0) {
      isFloatb = 1;
    } else {
      /* decimall is > 0, exponentl is > 0 and unsigned automatic conversion will not change its value */
      /* I may change to a temporary variable of another type or use compiler's #pragma because        */
      /* sometimes there is a warning.                                                                 */
      if (exponentl < decimall) {
        isFloatb = 1;
      } else {
        /* [-]123.456E[+]789 */
        isFloatb = 0;
        charsl = dotp - numbers;
        prevCharsl = charsl;
        charsl += exponentl;
        if (MARPAESLIF_UNLIKELY(charsl < prevCharsl)) { /* Turnaround */
          goto parsing_to_double;
        }
      }
    }
  }

  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %ld decimals, exponent value is %ld => %sa true floating point number", (int) numberl, numbers, (unsigned long) decimall, (long) exponentl, isFloatb ? "" : "not ");

  if (isFloatb) {
    /* A floating point number always trigger the proposal */
    goto parsing_to_double;
  }

  /* We have a special case in our algorithm: the representation -0 or -0Exx where xx >= 0  */
  /* Since the sign of zero can only be handled by a floating point number, and since zero  */
  /* is always exactly represented by the later, this special case is moved to the proposal */
  /* where we use floating pointer.                                                         */
  if ((numbers[0] == '-') && (numbers[1] == '0')) {
    /* It is a signed zero. This test is enough because we removed all non significant digits on */
    /* the left side, keeping at most one digit. If this digit is '0' we are done.               */
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: signed zero detected, forcing true floating point number", (int) numberl, numbers);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_DOUBLE;
    marpaESLIFValueResult.u.d             = -0.;
    goto proposal;
  }

  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %ld characters are needed to completely represent this non-floating pointer number", (int) numberl, numbers, (unsigned long) charsl);

  /* Is it too long for the largest non-floating pointer integer that we have */
  if (isNegb) {
#ifdef MARPAESLIF_HAVE_LONG_LONG
    if (charsl > marpaESLIFp->llongmincharsl) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: charsl is %ld > %ld (LLONG_MIN) : go to proposal", (int) numberl, numbers, (unsigned long) charsl, (unsigned long) marpaESLIFp->llongmincharsl);
      goto parsing_to_double;
    }
#else
    if (charsl > marpaESLIFp->longmincharsl) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: charsl is %ld > %ld (LONG_MIN) : go to proposal", (int) numberl, numbers, (unsigned long) charsl, (unsigned long) marpaESLIFp->longmincharsl);
      goto parsing_to_double;
    }
#endif
  } else {
#ifdef MARPAESLIF_HAVE_LONG_LONG
    if (charsl > marpaESLIFp->llongmaxcharsl) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: charsl is %ld > %ld (LLONG_MAX) : go to proposal", (int) numberl, numbers, (unsigned long) charsl, (unsigned long) marpaESLIFp->llongmaxcharsl);
      goto parsing_to_double;
    }
#else
    if (charsl > marpaESLIFp->longmaxcharsl) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: charsl is %ld > %ld (LONG_MAX) : go to proposal", (int) numberl, numbers, (unsigned long) charsl, (unsigned long) marpaESLIFp->longmaxcharsl);
      goto parsing_to_double
    }
#endif
  }

  /* The only possibities are: */
  /* [-]123                    */
  /* [-]123E[+]789             */
  /* [-]123.456E[+]789         */
  p = integers;
  if (dotp == NULL) {
    if (exponentp == NULL) {
      /* [-]123                */
      memcpy(p, numbers, numberl);
    } else {
      /* [-]123E[+]789        */
      l = exponentp - numbers;
      memcpy(p, numbers, l);
      q = p + l;
      /* exponentl is positive by definition here.                                                     */
      /* I may change to a temporary variable of another type or use compiler's #pragma because        */
      /* sometimes there is a warning.                                                                 */
      for (l = 0; l < exponentl; l++, q++) {
        *q = '0';
      }
    }
  } else {
    /* By definition decimall and exponentl are positive */
    /* [-]123.456E[+]789      */
    l = dotp - numbers;
    memcpy(p, numbers, l);
    q = p + l;

    l = exponentp - dotp - 1;
    memcpy(q, dotp + 1, l);
    q += l;

    shiftl = exponentl - decimall;
    for (l = 0; l < shiftl; l++, q++) {
      *q = '0';
    }
  }

  integers[charsl] = '\0';
  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: Transformed for parsing to %s", (int) numberl, numbers, integers);
  endptrendp = integers + charsl;

#if defined(MARPAESLIF_HAVE_LONG_LONG) && defined(C_STRTOLL)
  endptrp = NULL;
  errno = 0;    /* To distinguish success/failure after call */
  valuell = C_STRTOLL(integers, &endptrp, 10);
  /* Note that the exponent in a JSON number always have at least one digit */
  if ((endptrp != endptrendp) || (errno != 0)) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %s parsing failure, %s", (int) numberl, numbers, integers, errno != 0 ? strerror(errno) : "bad final pointer");
    goto parsing_to_double;
  }
  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %s parsing success", (int) numberl, numbers, integers);
  /* Can we promote it to a less higher thingy ? */
  if ((SHRT_MIN <= valuell) && (valuell <= SHRT_MAX)) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %d fits in a SHORT", (int) numberl, numbers, (int) valuell);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_SHORT;
    marpaESLIFValueResult.u.b             = (short) valuell;
  } else if ((INT_MIN <= valuell) && (valuell <= INT_MAX)) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %d fits in an INT", (int) numberl, numbers, (int) valuell);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_INT;
    marpaESLIFValueResult.u.i             = (int) valuell;
  } else if ((LONG_MIN <= valuell) && (valuell <= LONG_MAX)) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %ld fits in a LONG", (int) numberl, numbers, (long) valuell);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_LONG;
    marpaESLIFValueResult.u.l             = (long) valuell;
  } else {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: " MARPAESLIF_LONG_LONG_FMT " remains a LONG LONG", (int) numberl, numbers, valuell);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_LONG_LONG;
    marpaESLIFValueResult.u.ll            = valuell;
  }
#else
  endptrp = NULL;
  errno = 0;    /* To distinguish success/failure after call */
  valuel = strtol(integers, &endptrp, 10);
  /* Note that the exponent in a JSON number always have at least one digit */
  if ((endptrp != endptrendp) || (errno != 0)) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %s parsing failure, %s", (int) numberl, numbers, integers, errno != 0 ? strerror(errno) : "bad final pointer");
    goto parsing_to_double;
  }
  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %s parsing success", (int) numberl, numbers, integers);
  /* Can we promote it to a less higher thingy ? */
  if ((SHRT_MIN <= valuel) && (valuel <= SHRT_MAX)) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %d fits in a SHORT", (int) numberl, numbers, (int) valuel);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_SHORT;
    marpaESLIFValueResult.u.b             = (short) valuel;
  } else if ((INT_MIN <= valuel) && (valuel <= INT_MAX)) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %d fits in an INT", (int) numberl, numbers, (int) valuel);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_INT;
    marpaESLIFValueResult.u.i             = (int) valuel;
  } else if ((LONG_MIN <= valuel) && (valuel <= LONG_MAX)) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: %ld remains a LONG", (int) numberl, numbers, valuel);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_LONG;
    marpaESLIFValueResult.u.l             = valuel;
  }
#endif

  goto proposal;

 parsing_to_double:
  confidenceb = 0;
  /* In the proposal we go back to the original string, as if nothing has happened. Only the eventual leading '+' */
  /* remains removed. It is never needed.                                                                         */
#if defined(C_STRTOLD) && defined(MARPAESLIF_HUGE_VALL)
  endptrendp = numbers + numberl;
  /* Do we have to change the decimal point representation ? */
  decimalPoints = strchr(numbers, '.');
  decimalPointb = ((decimalPoints != NULL) && (*decimalPoints != marpaESLIFp->decimalPointc)) ? 1 : 0;
  if (decimalPointb) {
    *decimalPoints = marpaESLIFp->decimalPointc;
  }

  endptrp = NULL;
  errno = 0;    /* To distinguish success/failure after call */
  valueld = C_STRTOLD(numbers, &endptrp);
  if (! ((endptrp != endptrendp) /* Parsing error */
         ||
         ((errno == ERANGE) && ((valueld == MARPAESLIF_HUGE_VALL) || (valueld == -MARPAESLIF_HUGE_VALL))) /* Overflow */
         ||
         ((valueld == 0.) && (errno != 0)) /* Underflow */
         )) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: long double parsing success", (int) numberl, numbers);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_LONG_DOUBLE;
    marpaESLIFValueResult.u.ld            = valueld;
  } else {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: long double parsing failure, %s", (int) numberl, numbers, errno != 0 ? strerror(errno) : "bad final pointer");
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_UNDEF;
  }
  if (decimalPointb) {
    *decimalPoints = '.';
  }
#else /* C_STRTOLD && MARPAESLIF_HUGE_VALL */
#  if defined(C_STRTOD) && defined(MARPAESLIF_HUGE_VAL)
  endptrendp = numbers + numberl;
  /* Do we have to change the decimal point representation ? */
  decimalPoints = strchr(numbers, '.');
  decimalPointb = ((decimalPoints != NULL) && (*decimalPoints != marpaESLIFp->decimalPointc)) ? 1 : 0;
  if (decimalPointb) {
    *decimalPoints = marpaESLIFp->decimalPointc;
  }

  endptrp = NULL;
  errno = 0;    /* To distinguish success/failure after call */
  valued = C_STRTOD(numbers, &endptrp);
  if (! ((endptrp != endptrendp) /* Parsing error */
         ||
         ((errno == ERANGE) && ((valued == MARPAESLIF_HUGE_VAL) || (valued == -MARPAESLIF_HUGE_VAL))) /* Overflow */
         ||
         ((valued == 0.) && (errno != 0)) /* Underflow */
         )) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: double parsing success", (int) numberl, numbers);
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_DOUBLE;
    marpaESLIFValueResult.u.d             = valued;
  } else {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: double parsing failure, %s", (int) numberl, numbers, errno != 0 ? strerror(errno) : "bad final pointer");
    marpaESLIFValueResult.contextp        = NULL;
    marpaESLIFValueResult.representationp = NULL;
    marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_UNDEF;
  }
  if (decimalPointb) {
    *decimalPoints = '.';
  }
#  else /* C_STRTOD && MARPAESLIF_HUGE_VAL */
  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%.*s: No lib call available for parsing", (int) numberl, numbers);
  marpaESLIFValueResult.contextp        = NULL;
  marpaESLIFValueResult.representationp = NULL;
  marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_UNDEF;
#  endif  /* C_STRTOD && MARPAESLIF_HUGE_VAL */
#endif /* C_STRTOLD && MARPAESLIF_HUGE_VALL */

 proposal:
  if (confidencebp != NULL) {
    *confidencebp = confidenceb;
  }
  if (marpaESLIFValueResultp != NULL) {
    *marpaESLIFValueResultp = marpaESLIFValueResult;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  if (dups != NULL) {
    /* We changed the input... Restore it */
    memcpy(s, dups, sizel);
    free(dups);
  }

  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFGrammar_validateb(marpaESLIFGrammar_t *marpaESLIFGrammarp, short ignoreLazyb, char *forcedStartSymbols, int forcedStartSymbolLeveli)
/*****************************************************************************/
{
  static const char                *funcs                                  = "_marpaESLIFGrammar_validateb";
  marpaESLIF_t                     *marpaESLIFp                            = marpaESLIFGrammarp->marpaESLIFp;
  genericStack_t                   *grammarStackp                          = marpaESLIFGrammarp->grammarStackp;
  marpaWrapperGrammar_t            *marpaWrapperGrammarStartClonep         = NULL;
  marpaWrapperGrammar_t            *marpaWrapperGrammarStartNoEventClonep  = NULL;
  marpaWrapperRecognizer_t         *marpaWrapperRecognizerp                = NULL;
  marpaESLIF_meta_t                *metap;
  genericStack_t                   *symbolStackp;
  genericStack_t                   *ruleStackp;
  genericStack_t                   *lhsRuleStackp;
  int                               grammari;
  int                               grammarj;
  marpaESLIF_symbol_t              *symbolp;
  marpaESLIF_symbol_t              *subSymbolp;
  marpaESLIF_rule_t                *subRulep;
  int                               symboli;
  marpaESLIF_rule_t                *rulep;
  marpaESLIF_rule_t                *ruletmpp;
  int                               rulei;
  int                               rulej;
  marpaESLIF_grammar_t             *grammarp;
  marpaESLIF_grammar_t             *subGrammarp;
  marpaESLIF_grammar_t             *grammar2p;
  marpaESLIF_symbol_t              *startp;
  marpaESLIF_symbol_t              *discardp;
  marpaESLIF_symbol_t              *exceptionp;
  short                             rcb;
  size_t                            rhsl;
  size_t                            asciishowl;
  short                             haveLexemeb;
  marpaESLIF_cloneContext_t         marpaESLIF_cloneContext;
  marpaWrapperGrammarCloneOption_t  marpaWrapperGrammarCloneOption;
  marpaWrapperRecognizerOption_t    marpaWrapperRecognizerOption;
  size_t                            nTerminalPristinel;
  size_t                            nTerminalDiscardPristinel;
  size_t                            symboll;
  int                              *symbolIdArrayp;
  short                             fastDiscardb;

  marpaESLIF_cloneContext.marpaESLIFp = marpaESLIFp;
  marpaESLIF_cloneContext.grammarp    = NULL;

  marpaWrapperGrammarCloneOption.userDatavp = (void *) &marpaESLIF_cloneContext;
  marpaWrapperGrammarCloneOption.grammarOptionSetterp = NULL; /* Changed at run-time see below */
  marpaWrapperGrammarCloneOption.symbolOptionSetterp = NULL; /* Changed at run-time see below */
  marpaWrapperGrammarCloneOption.ruleOptionSetterp = NULL; /* Always NULL */

  marpaWrapperRecognizerOption.genericLoggerp    = marpaESLIFp->marpaESLIFOption.genericLoggerp;
  marpaWrapperRecognizerOption.disableThresholdb = 0;
  marpaWrapperRecognizerOption.exhaustionEventb  = 0;

  /* MARPAESLIF_TRACE(marpaESLIFp, funcs, "Validating ESLIF grammar"); */

  /* There must be a grammar at level 0 */
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_PTR(grammarStackp, 0))) {
    MARPAESLIF_ERROR(marpaESLIFp, "No top-level grammar");
    goto err;
  }
  grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, 0);

  /* Precompile eventual luascript */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIF_lua_grammar_precompileb(marpaESLIFGrammarp))) {
    goto err;
  }

  /* Set default symbol and rule action if not done, terminal's regex-action */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      /* Sparse item in grammarStackp -; */
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    symbolStackp = grammarp->symbolStackp;
    ruleStackp = grammarp->ruleStackp;

    if (grammarp->defaultSymbolActionp == NULL) {
      grammarp->defaultSymbolActionp = (marpaESLIF_action_t *) malloc(sizeof(marpaESLIF_action_t));
      if (MARPAESLIF_UNLIKELY(grammarp->defaultSymbolActionp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      grammarp->defaultSymbolActionp->type    = MARPAESLIF_ACTION_TYPE_NAME;
      grammarp->defaultSymbolActionp->u.names = strdup("::transfer");
      if (MARPAESLIF_UNLIKELY(grammarp->defaultSymbolActionp->u.names == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }

    if (grammarp->defaultRuleActionp == NULL) {
      grammarp->defaultRuleActionp = (marpaESLIF_action_t *) malloc(sizeof(marpaESLIF_action_t));
      if (MARPAESLIF_UNLIKELY(grammarp->defaultRuleActionp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      grammarp->defaultRuleActionp->type    = MARPAESLIF_ACTION_TYPE_NAME;
      grammarp->defaultRuleActionp->u.names = strdup("::concat");
      if (MARPAESLIF_UNLIKELY(grammarp->defaultRuleActionp->u.names == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }

    /* Nothing on defaultEventActionp - it can be NULL */
    /* Nothing on defaultRegexActionp - it can be NULL */
    /* Nothing on defaultEncodings - it can be NULL */
    /* Nothing on fallbackEncodings - it can be NULL */

    /* :start meta symbol check is embedded here */
    startp = NULL;
    if ((forcedStartSymbolLeveli == grammari) && (forcedStartSymbols != NULL)) {
      /* Lookup this symbol */
      /* Reset any eventual startb, set startb to the found symbol */
      for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
        MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);
        if (strcmp(symbolp->descp->asciis, forcedStartSymbols) == 0) {
          /* This is indeed the one we forced */
          startp = symbolp;
          if (! symbolp->startb) {
            MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s), forcing startb flag of symbol %d <%s>", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis);
            symbolp->startb = 1;
          }
        } else {
          if (symbolp->startb) {
            /* This is not the one we forced */
            MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s), removing startb flag of symbol %d <%s>", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis);
            symbolp->startb = 0;
          }
        }
      }
      /* We force start to a symbol unknown ? */
      if (MARPAESLIF_UNLIKELY(startp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d (%s), forced start symbol <%s> not found", grammari, grammarp->descp->asciis, forcedStartSymbols);
        goto err;
      }
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s), forced start symbol <%s> found", grammari, grammarp->descp->asciis, forcedStartSymbols);
    } else {
      for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
        MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);
        if (symbolp->startb) {
          if (MARPAESLIF_LIKELY(startp == NULL)) {
            startp = symbolp;
          } else {
            MARPAESLIF_ERRORF(marpaESLIFp, "More than one :start symbol at grammar level %d (%s): symbols %d <%s> and %d <%s>", grammari, grammarp->descp->asciis, startp->idi, startp->descp->asciis, symbolp->idi, symbolp->descp->asciis);
            goto err;
          }
        }
      }
    }

    /* Before precomputing we have to clone. Why ? This is because the bootstrap is changing symbols event behaviours after creating them. */
    /* But Marpa does not know about it. */
    marpaESLIF_cloneContext.grammarp = grammarp;
    marpaWrapperGrammarCloneOption.grammarOptionSetterp = NULL;
    marpaWrapperGrammarCloneOption.symbolOptionSetterp = _marpaESLIFGrammar_symbolOptionSetterInitb;
    marpaWrapperGrammarStartClonep = marpaWrapperGrammar_clonep(grammarp->marpaWrapperGrammarStartp, &marpaWrapperGrammarCloneOption);
    if (MARPAESLIF_UNLIKELY(marpaWrapperGrammarStartClonep == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Grammar level %d (%s): cloning failure", grammari, grammarp->descp->asciis);
        goto err;
    }
    if (grammarp->marpaWrapperGrammarStartp != NULL) {
      marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarStartp);
    }
    grammarp->marpaWrapperGrammarStartp = marpaWrapperGrammarStartClonep;
    marpaWrapperGrammarStartClonep = NULL;

    /* Same but with no event */
    marpaWrapperGrammarCloneOption.grammarOptionSetterp = NULL;
    marpaWrapperGrammarCloneOption.symbolOptionSetterp = _marpaESLIFGrammar_symbolOptionSetterInternalb; /* No event but internal :discard[on/off/switch] */
    marpaWrapperGrammarStartNoEventClonep = marpaWrapperGrammar_clonep(grammarp->marpaWrapperGrammarStartp, &marpaWrapperGrammarCloneOption);
    if (MARPAESLIF_UNLIKELY(marpaWrapperGrammarStartNoEventClonep == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Grammar level %d (%s): cloning failure", grammari, grammarp->descp->asciis);
        goto err;
    }
    if (grammarp->marpaWrapperGrammarStartNoEventp != NULL) {
      marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarStartNoEventp);
    }
    grammarp->marpaWrapperGrammarStartNoEventp = marpaWrapperGrammarStartNoEventClonep;
    marpaWrapperGrammarStartNoEventClonep = NULL;

    if (startp == NULL) {
      /* Use the first non internal rule */
      rulep = NULL;
      for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackp); rulei++) {
        MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei);
        /* :discard, :start and proxy rules */
        if (rulep->internalb) {
          rulep = NULL;
          continue;
        }
        break;
      }
      if (MARPAESLIF_UNLIKELY(rulep == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing grammar level %d (%s) is impossible: no rule", grammari, grammarp->descp->asciis);
        goto err;
      }

      startp = rulep->lhsp;

      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Precomputing grammar level %d (%s) at start symbol %d <%s>", grammari, grammarp->descp->asciis, rulep->lhsp->idi, rulep->lhsp->descp->asciis);
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_precompute_startb(grammarp->marpaWrapperGrammarStartp, rulep->lhsp->idi))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing grammar level %d (%s) at start symbol %d <%s> failure", grammari, grammarp->descp->asciis, rulep->lhsp->idi, rulep->lhsp->descp->asciis);
        goto err;
      }
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Precomputing \"no event\" grammar level %d (%s) at start symbol %d <%s>", grammari, grammarp->descp->asciis, rulep->lhsp->idi, rulep->lhsp->descp->asciis);
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_precompute_startb(grammarp->marpaWrapperGrammarStartNoEventp, rulep->lhsp->idi))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing \"no event\" grammar level %d (%s) at start symbol %d <%s> failure", grammari, grammarp->descp->asciis, rulep->lhsp->idi, rulep->lhsp->descp->asciis);
        goto err;
      }

    } else {

      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Precomputing grammar level %d (%s) at start symbol %d <%s>", grammari, grammarp->descp->asciis, startp->idi, startp->descp->asciis);
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_precompute_startb(grammarp->marpaWrapperGrammarStartp, startp->idi))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing grammar level %d (%s) at start symbol %d <%s> failure", grammari, grammarp->descp->asciis, startp->idi, startp->descp->asciis);
        goto err;
      }
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Precomputing \"no event\" grammar level %d (%s) at start symbol %d <%s>", grammari, grammarp->descp->asciis, startp->idi, startp->descp->asciis);
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_precompute_startb(grammarp->marpaWrapperGrammarStartNoEventp, startp->idi))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing \"no event\" grammar level %d (%s) at start symbol %d <%s> failure", grammari, grammarp->descp->asciis, startp->idi, startp->descp->asciis);
        goto err;
      }

    }

    startp->topb = 1;
    grammarp->starti = startp->idi;
    grammarp->starts = startp->descp->asciis;

    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Getting start first terminals in grammar level %d (%s)", grammari, grammarp->descp->asciis);
    marpaWrapperRecognizerp = marpaWrapperRecognizer_newp(grammarp->marpaWrapperGrammarStartp, &marpaWrapperRecognizerOption);
    if (MARPAESLIF_UNLIKELY(marpaWrapperRecognizerp == NULL)) {
      goto err;
    }
    if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_expectedb(marpaWrapperRecognizerp, &nTerminalPristinel, &symbolIdArrayp))) {
      goto err;
    }
    if ((nTerminalPristinel > 0) && (symbolIdArrayp != NULL)) {
      grammarp->nTerminalPristinel = nTerminalPristinel;

      if (grammarp->terminalArrayPristinepp == NULL) {
        grammarp->terminalArrayPristinepp = (marpaESLIF_symbol_t **) malloc(nTerminalPristinel * sizeof(marpaESLIF_symbol_t *));
        if (MARPAESLIF_UNLIKELY(grammarp->terminalArrayPristinepp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        for (symboll = 0; symboll < nTerminalPristinel; symboll++) {
          MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, grammarp->terminalArrayPristinepp[symboll], symbolStackp, symbolIdArrayp[symboll]);
          MARPAESLIF_TRACEF(marpaESLIFp, funcs, "... Found symbol No %d <%s>", grammarp->terminalArrayPristinepp[symboll]->idi, grammarp->terminalArrayPristinepp[symboll]->descp->asciis);
        }
        MARPAESLIF_QSORT(marpaESLIF_symbol_t *, grammarp->terminalArrayPristinepp, nTerminalPristinel, _marpaESLIF_symbol_priority_sort_inlinedi, _marpaESLIF_symbol_priority_sorti);
      }

      if (grammarp->terminalIdArrayPristinep == NULL) {
        grammarp->terminalIdArrayPristinep = (int *) malloc(nTerminalPristinel * sizeof(int));
        if (MARPAESLIF_UNLIKELY(grammarp->terminalIdArrayPristinep == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        /* Recuperate symbols Ids sorted by priority */
        for (symboll = 0; symboll < nTerminalPristinel; symboll++) {
          grammarp->terminalIdArrayPristinep[symboll] = grammarp->terminalArrayPristinepp[symboll]->idi;
        }
      }
    }
    marpaWrapperRecognizer_freev(marpaWrapperRecognizerp);
    marpaWrapperRecognizerp = NULL;

    MARPAESLIFGRAMMAR_GET_TERMINALS(marpaESLIFp, funcs, ":start", grammarp, grammarp->marpaWrapperGrammarStartp, grammarp->nTerminall, grammarp->symbolArraypp);
    if (grammarp->nTerminall > 0) {
      /* Prepare room for excepted terminals asked by the end-user */
      if (grammarp->expectedTerminalIdArrayp == NULL) {
        grammarp->expectedTerminalIdArrayp = (int *) malloc(sizeof(int) * grammarp->nTerminall);
        if (MARPAESLIF_UNLIKELY(grammarp->expectedTerminalIdArrayp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
      }
      if (grammarp->expectedTerminalArraypp == NULL) {
        grammarp->expectedTerminalArraypp = (marpaESLIF_symbol_t **) malloc(sizeof(marpaESLIF_symbol_t *) * grammarp->nTerminall);
        if (MARPAESLIF_UNLIKELY(grammarp->expectedTerminalArraypp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
      }
    }

    if (GENERICSTACK_USED(symbolStackp) > 0) {
      if (grammarp->allSymbolsArraypp == NULL) {
        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Flattening all symbols in grammar level %d (%s)", grammari, grammarp->descp->asciis);
        grammarp->allSymbolsArraypp = (marpaESLIF_symbol_t **) malloc(sizeof(marpaESLIF_symbol_t *) * GENERICSTACK_USED(symbolStackp));
        if (MARPAESLIF_UNLIKELY(grammarp->allSymbolsArraypp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
          MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);
          grammarp->allSymbolsArraypp[symboli] = symbolp;
        }
      }
    }

    if (GENERICSTACK_USED(ruleStackp) > 0) {
      if (grammarp->allRulesArraypp == NULL) {
        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Flattening all rules in grammar level %d (%s)", grammari, grammarp->descp->asciis);
        grammarp->allRulesArraypp = (marpaESLIF_rule_t **) malloc(sizeof(marpaESLIF_rule_t *) * GENERICSTACK_USED(ruleStackp));
        if (MARPAESLIF_UNLIKELY(grammarp->allRulesArraypp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackp); rulei++) {
          MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei);
          grammarp->allRulesArraypp[rulei] = rulep;
        }
      }
    }

    discardp = NULL;
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);
      if (symbolp->discardb) {
        if (MARPAESLIF_LIKELY(discardp == NULL)) {
          discardp = symbolp;
        } else {
          MARPAESLIF_ERRORF(marpaESLIFp, "More than one :discard symbol at grammar level %d (%s): symbols %d <%s> and %d <%s>", grammari, grammarp->descp->asciis, discardp->idi, discardp->descp->asciis, symbolp->idi, symbolp->descp->asciis);
          goto err;
        }
      }
    }

    if (discardp != NULL) {
      /* The :discard symbol itself never have any event */
      if (MARPAESLIF_UNLIKELY((discardp->eventBefores    != NULL) ||
                              (discardp->eventAfters     != NULL) ||
                              (discardp->eventPredicteds != NULL) ||
                              (discardp->eventNulleds    != NULL) ||
                              (discardp->eventCompleteds != NULL) ||
                              (discardp->discardEvents   != NULL))) {
        MARPAESLIF_ERRORF(marpaESLIFp, ":discard symbol at grammar level %d (%s) must have no event", grammari, grammarp->descp->asciis);
        goto err;
      }
      /* If not all :discard rules are in the form :discard ::= terminal then we switch off the fastDiscardb flag */
      fastDiscardb = 1;

      /* Per def a :discard rule has only one RHS, we mark its discardRhsb flag and copy the rule's discard settings */
      /* (Note that saying :discard :[x]:= RHS event => EVENT twice will overwrite first setting) */
      for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackp); rulei++) {
        MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei);
        if (rulep->lhsp != discardp) {
          continue;
        }
        if (rulep->nrhsl != 1) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Looking at grammar level %d (%s) and discard symbol %d <%s>: a :discard rule must have exactly one RHS", grammari, grammarp->descp->asciis, discardp->idi, discardp->descp->asciis);
          goto err;
        }
        symbolp = rulep->rhspp[0];
        symbolp->discardRhsb = 1;
        symbolp->discardEvents = rulep->discardEvents;
        symbolp->discardEventb = rulep->discardEventb;
        symbolp->discardEvente = rulep->discardEvente;

        if (! MARPAESLIF_IS_TERMINAL(symbolp)) {
          fastDiscardb = 0;
        }
      }

      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Precomputing grammar level %d (%s) at discard symbol %d <%s> sets fast discard mode to %s", grammari, grammarp->descp->asciis, discardp->idi, discardp->descp->asciis, fastDiscardb ? "true" : "false");
      grammarp->fastDiscardb = fastDiscardb;

      marpaESLIF_cloneContext.grammarp = grammarp;
      /* Clone for the discard mode at grammar level */
      marpaWrapperGrammarCloneOption.grammarOptionSetterp = _marpaESLIFGrammar_grammarOptionSetterNoLoggerb;
      marpaWrapperGrammarCloneOption.symbolOptionSetterp  = _marpaESLIFGrammar_symbolOptionSetterDiscardb; /* No event but internal discard completion */
      marpaWrapperGrammarStartClonep = marpaWrapperGrammar_clonep(grammarp->marpaWrapperGrammarStartp, &marpaWrapperGrammarCloneOption);
      if (MARPAESLIF_UNLIKELY(marpaWrapperGrammarStartClonep == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Grammar level %d (%s) at discard symbol %d <%s>: cloning failure", grammari, grammarp->descp->asciis, discardp->idi, discardp->descp->asciis);
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_precompute_startb(marpaWrapperGrammarStartClonep, discardp->idi))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing grammar level %d (%s) at discard symbol %d <%s> failure", grammari, grammarp->descp->asciis, discardp->idi, discardp->descp->asciis);
        goto err;
      }
      if (grammarp->marpaWrapperGrammarDiscardp != NULL) {
        marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarDiscardp);
      }      
      grammarp->marpaWrapperGrammarDiscardp = marpaWrapperGrammarStartClonep;
      marpaWrapperGrammarStartClonep = NULL;
      /* Same but with no event */
      marpaWrapperGrammarCloneOption.grammarOptionSetterp = _marpaESLIFGrammar_grammarOptionSetterNoLoggerb;
      marpaWrapperGrammarCloneOption.symbolOptionSetterp  = _marpaESLIFGrammar_symbolOptionSetterInternalNoeventb;
      marpaWrapperGrammarStartNoEventClonep = marpaWrapperGrammar_clonep(grammarp->marpaWrapperGrammarStartp, &marpaWrapperGrammarCloneOption);
      if (MARPAESLIF_UNLIKELY(marpaWrapperGrammarStartNoEventClonep == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Grammar level %d (%s) at discard symbol %d <%s>: cloning failure", grammari, grammarp->descp->asciis, discardp->idi, discardp->descp->asciis);
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_precompute_startb(marpaWrapperGrammarStartNoEventClonep, discardp->idi))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing grammar level %d (%s) at discard symbol %d <%s> failure", grammari, grammarp->descp->asciis, discardp->idi, discardp->descp->asciis);
        goto err;
      }
      if (grammarp->marpaWrapperGrammarDiscardNoEventp != NULL) {
        marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarDiscardNoEventp);
      }      
      grammarp->marpaWrapperGrammarDiscardNoEventp = marpaWrapperGrammarStartNoEventClonep;
      marpaWrapperGrammarStartNoEventClonep = NULL;

      grammarp->discardp = discardp;
      grammarp->discardi = discardp->idi;

      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Getting discard first terminals in grammar level %d (%s)", grammari, grammarp->descp->asciis);
      marpaWrapperRecognizerp = marpaWrapperRecognizer_newp(grammarp->marpaWrapperGrammarDiscardp, &marpaWrapperRecognizerOption);
      if (MARPAESLIF_UNLIKELY(marpaWrapperRecognizerp == NULL)) {
	goto err;
      }
      if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_expectedb(marpaWrapperRecognizerp, &nTerminalDiscardPristinel, &symbolIdArrayp))) {
	goto err;
      }
      if ((nTerminalDiscardPristinel > 0) && (symbolIdArrayp != NULL)) {
	grammarp->nTerminalDiscardPristinel = nTerminalDiscardPristinel;

        if (grammarp->terminalArrayDiscardPristinepp == NULL) {
          grammarp->terminalArrayDiscardPristinepp = (marpaESLIF_symbol_t **) malloc(nTerminalDiscardPristinel * sizeof(marpaESLIF_symbol_t *));
          if (MARPAESLIF_UNLIKELY(grammarp->terminalArrayDiscardPristinepp == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
            goto err;
          }
          for (symboll = 0; symboll < nTerminalDiscardPristinel; symboll++) {
            MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, grammarp->terminalArrayDiscardPristinepp[symboll], symbolStackp, symbolIdArrayp[symboll]);
            MARPAESLIF_TRACEF(marpaESLIFp, funcs, "... Found symbol No %d (%s)", grammarp->terminalArrayDiscardPristinepp[symboll]->idi, grammarp->terminalArrayDiscardPristinepp[symboll]->descp->asciis);
          }
          MARPAESLIF_QSORT(marpaESLIF_symbol_t *, grammarp->terminalArrayDiscardPristinepp, nTerminalDiscardPristinel, _marpaESLIF_symbol_priority_sort_inlinedi, _marpaESLIF_symbol_priority_sorti);
        }

        if (grammarp->terminalIdArrayDiscardPristinep == NULL) {
          grammarp->terminalIdArrayDiscardPristinep = (int *) malloc(nTerminalDiscardPristinel * sizeof(int));
          if (MARPAESLIF_UNLIKELY(grammarp->terminalIdArrayDiscardPristinep == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
            goto err;
          }
          /* Recuperate symbol Ids sorted by priority */
          for (symboll = 0; symboll < nTerminalDiscardPristinel; symboll++) {
            grammarp->terminalIdArrayDiscardPristinep[symboll] = grammarp->terminalArrayDiscardPristinepp[symboll]->idi;
          }
        }
        /* nTerminalDiscardPristinel and terminalIdArrayDiscardPristinep contains the first terminals that every pristine */
        /* recognizer would try when executing :discard as a complete parse.                        */
      }
      marpaWrapperRecognizer_freev(marpaWrapperRecognizerp);
      marpaWrapperRecognizerp = NULL;
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Getting discard first terminals in grammar level %d (%s): %ld symbols found", grammari, grammarp->descp->asciis, (unsigned long) nTerminalDiscardPristinel);
    }
  }
  
  /*
    3. In any rule of any grammar, an RHS can be at any level as well. Default being the current one.
    When the RHS level is the current level, if this RHS never appear as an LHS of another rule at the
    same level, then it must be an LHS of grammar at a resolved level, which must de-factor must also exist.
    
    Therefore every grammar is first scanned to detect all symbols that are truely LHS's at this level.
    Then every RHS of every rule is verified: it is must be an LHS at its specified grammar level. When found,
    This resolved grammar is precomputed at this found LHS and the result is attached to the symbol of the
    parent grammar.

    It is illegal to have an LHS defined multiple times with different number of parameters.
  */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      /* Sparse item in grammarStackp -; */
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Looking at symbols in grammar level %d (%s)", grammari, grammarp->descp->asciis);

    /* Loop on LHS symbols */
    symbolStackp = grammarp->symbolStackp;
    ruleStackp = grammarp->ruleStackp;
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);

      lhsRuleStackp = symbolp->lhsRuleStackp;
      for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackp); rulei++) {
        MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei);
        if (rulep->lhsp == symbolp) {
          GENERICSTACK_PUSH_PTR(lhsRuleStackp, rulep);
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(lhsRuleStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFp, "lhsRuleStackp push failure, %s", strerror(errno));
            goto err;
          }
        }
      }

      symbolp->lhsb = GENERICSTACK_USED(lhsRuleStackp) > 0 ? 1 : 0;
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Looking at rules in grammar level %d (%s): Symbol No %d <%s> lhsb flag set to %d", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis, (int) symbolp->lhsb);
    }
  }

  /* From grammar point of view, an expected symbol will always be either symbols explicitely created as terminals,
     either symbols not being an LHS. Per definition symbols created as terminals cannot be LHS symbols: precomputing
     the grammar will automatically fail. This is made sure by always precomputing at least grammar at level 0, and
     by precomputing any needed grammar at any other level with an alternative starting symbol.
  */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {

    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Looking at rules in grammar level %d (%s)", grammari, grammarp->descp->asciis);

    symbolStackp = grammarp->symbolStackp;
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);

      /* Only lexemes should be looked */
      if (! MARPAESLIF_IS_LEXEME(symbolp)) {
        symbolp->lookupResolvedLeveli = grammarp->leveli;
        symbolp->lookupLevelDeltai = 0;
        continue;
      }

      /* Generator symbols are special: they have no correspondance in the grammar. _marpaESLIFRecognizer_meta_matcherb() will catch them */
      if (symbolp->generatorActionp != NULL) {
        symbolp->lookupResolvedLeveli = grammarp->leveli;
        symbolp->lookupLevelDeltai = 0;
        continue;
      }

      /* In any case, this is a a meta symbol */
      metap = symbolp->u.metap;

      /* Lazy symbols are special and aim to get removed at ESLIF bootstrap */
      if (metap->lazyb && ignoreLazyb) {
        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Grammar level %d (%s): symbol %d <%s> is lazy", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis);
        continue;
      }

      if (symbolp->lookupSymbolp != NULL) {
        subSymbolp = symbolp->lookupSymbolp;
        subGrammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, grammarp->leveli + symbolp->lookupLevelDeltai, NULL /* descp */);

        if (MARPAESLIF_UNLIKELY(subGrammarp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Looking at rules in grammar level %d (%s): No grammar at level %d", grammari, grammarp->descp->asciis, grammarp->leveli + symbolp->lookupLevelDeltai);
          goto err;
        }
      } else {
        /* Resolve the symbol: Either the next grammar, either the current grammar */
        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Grammar level %d (%s): symbol %d <%s> must be symbol <%s> in grammar level %d or %d", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis, symbolp->u.metap->asciinames, grammarp->leveli, grammarp->leveli + symbolp->lookupLevelDeltai);

        /* In current grammar ? */
        subSymbolp = _marpaESLIF_resolveLhsp(marpaESLIFp, grammarStackp, grammarp, symbolp->u.metap->asciinames, symbolp->parami, 0, NULL, &subGrammarp, 1 /* silentb */);
        if (subSymbolp == NULL) {
          /* In next grammar ? */
          subSymbolp = _marpaESLIF_resolveLhsp(marpaESLIFp, grammarStackp, grammarp, symbolp->u.metap->asciinames, symbolp->parami, symbolp->lookupLevelDeltai, NULL, &subGrammarp, 1 /* silentb */);
        }

        if (MARPAESLIF_UNLIKELY(subSymbolp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Looking at rules in grammar level %d (%s): symbol %d <%s> must be resolved as <%s> in grammar at level %d or %d", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis, symbolp->descp->asciis, grammarp->leveli, grammarp->leveli + symbolp->lookupLevelDeltai);
          goto err;
        }
      }

      /* Since we loop on symbols of every rule, it can very well happen that we hit */
      /* the same meta symbol more than once.                                        */
      if (metap->marpaWrapperGrammarStartp == NULL) {
        /* Clone for the symbol in lexeme mode: no event except when this is on the left side of an exception character '-' */
        /* meta terminals are an exception: they will raise a peeking recognizer, then we want to keep everything intact.   */
        marpaESLIF_cloneContext.grammarp = subGrammarp;
        marpaWrapperGrammarCloneOption.grammarOptionSetterp = NULL; /* _marpaESLIFGrammar_grammarOptionSetterNoLoggerb; */
        /* If subGrammarp is the same as current grammar then it is either a generator symbol, or a paramterized symbol */
        /* addressing something at the same level.                                                                      */
        marpaWrapperGrammarCloneOption.symbolOptionSetterp  = NULL;
        marpaWrapperGrammarStartClonep = marpaWrapperGrammar_clonep(subGrammarp->marpaWrapperGrammarStartp, &marpaWrapperGrammarCloneOption);
        if (MARPAESLIF_UNLIKELY(marpaWrapperGrammarStartClonep == NULL)) {
          goto err;
        }

        if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_precompute_startb(marpaWrapperGrammarStartClonep, subSymbolp->idi))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing grammar level %d (%s) at symbol %d <%s> failure", subGrammarp->leveli, subGrammarp->descp->asciis, subSymbolp->idi, subSymbolp->descp->asciis);
          goto err;
        }

        /* The total list of terminals of a meta grammar is always the same as the destination grammar */
        metap->nTerminall    = subGrammarp->nTerminall;
        if (metap->nTerminall > 0) {
          metap->symbolArraypp = (marpaESLIF_symbol_t **) malloc(sizeof(marpaESLIF_symbol_t *) * metap->nTerminall);
          if (MARPAESLIF_UNLIKELY(metap->symbolArraypp == NULL)) {
              MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
              goto err;
          }
          memcpy(metap->symbolArraypp, subGrammarp->symbolArraypp, sizeof(marpaESLIF_symbol_t *) * metap->nTerminall);
        }

        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Getting start first terminals in grammar level %d (%s) at symbol %d <%s>", subGrammarp->leveli, subGrammarp->descp->asciis, subSymbolp->idi, subSymbolp->descp->asciis);
        marpaWrapperRecognizerp = marpaWrapperRecognizer_newp(marpaWrapperGrammarStartClonep, &marpaWrapperRecognizerOption);
        if (MARPAESLIF_UNLIKELY(marpaWrapperRecognizerp == NULL)) {
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_expectedb(marpaWrapperRecognizerp, &nTerminalPristinel, &symbolIdArrayp))) {
          goto err;
        }
        if ((nTerminalPristinel > 0) && (symbolIdArrayp != NULL)) {
          metap->nTerminalPristinel = nTerminalPristinel;

          if (metap->terminalArrayPristinepp == NULL) {
            metap->terminalArrayPristinepp = (marpaESLIF_symbol_t **) malloc(nTerminalPristinel * sizeof(marpaESLIF_symbol_t *));
            if (MARPAESLIF_UNLIKELY(metap->terminalArrayPristinepp == NULL)) {
              MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
              goto err;
            }
            for (symboll = 0; symboll < nTerminalPristinel; symboll++) {
              MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, metap->terminalArrayPristinepp[symboll], subGrammarp->symbolStackp, symbolIdArrayp[symboll]);
              MARPAESLIF_TRACEF(marpaESLIFp, funcs, "... Found symbol No %d <%s>", metap->terminalArrayPristinepp[symboll]->idi, metap->terminalArrayPristinepp[symboll]->descp->asciis);
            }
            MARPAESLIF_QSORT(marpaESLIF_symbol_t *, metap->terminalArrayPristinepp, nTerminalPristinel, _marpaESLIF_symbol_priority_sort_inlinedi, _marpaESLIF_symbol_priority_sorti);
          }

          if (metap->terminalIdArrayPristinep == NULL) {
            metap->terminalIdArrayPristinep = (int *) malloc(nTerminalPristinel * sizeof(int));
            if (MARPAESLIF_UNLIKELY(metap->terminalIdArrayPristinep == NULL)) {
              MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
              goto err;
            }
            /* Recuperate symbol Ids sorted by priority */
            for (symboll = 0; symboll < nTerminalPristinel; symboll++) {
              metap->terminalIdArrayPristinep[symboll] = metap->terminalArrayPristinepp[symboll]->idi;
            }
          }
        }
        marpaWrapperRecognizer_freev(marpaWrapperRecognizerp);
        marpaWrapperRecognizerp = NULL;
        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Getting start first terminals in grammar level %d (%s) at symbol %d <%s>: %ld symbols found", subGrammarp->leveli, subGrammarp->descp->asciis, subSymbolp->idi, subSymbolp->descp->asciis, (unsigned long) nTerminalPristinel);

        metap->marpaWrapperGrammarStartp = marpaWrapperGrammarStartClonep;
        marpaWrapperGrammarStartClonep = NULL; /* It is in metap->marpaWrapperGrammarLexemeClonep */
      }

      /* Since we loop on symbols of every rule, it can very well happen that we hit */
      /* the same meta symbol more than once.                                        */
      if (metap->marpaWrapperGrammarStartNoEventp == NULL) {
        /* Clone for the symbol in lexeme mode: no event except when this is on the left side of an exception character '-' */
        /* meta terminals are an exception: they will raise a peeking recognizer, then we want to keep everything intact.   */
        marpaESLIF_cloneContext.grammarp = subGrammarp;
        marpaWrapperGrammarCloneOption.grammarOptionSetterp = NULL; /* _marpaESLIFGrammar_grammarOptionSetterNoLoggerb; */
        /* If subGrammarp is the same as current grammar then it is either a generator symbol, or a paramterized symbol */
        /* addressing something at the same level.                                                                      */
        marpaWrapperGrammarCloneOption.symbolOptionSetterp  = _marpaESLIFGrammar_symbolOptionSetterInternalb;
        marpaWrapperGrammarStartNoEventClonep = marpaWrapperGrammar_clonep(subGrammarp->marpaWrapperGrammarStartp, &marpaWrapperGrammarCloneOption);
        if (MARPAESLIF_UNLIKELY(marpaWrapperGrammarStartNoEventClonep == NULL)) {
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_precompute_startb(marpaWrapperGrammarStartNoEventClonep, subSymbolp->idi))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Precomputing  \"no event\" grammar level %d (%s) at symbol %d <%s> failure", subGrammarp->leveli, subGrammarp->descp->asciis, subSymbolp->idi, subSymbolp->descp->asciis);
          goto err;
        }

        metap->marpaWrapperGrammarStartNoEventp = marpaWrapperGrammarStartNoEventClonep;
        marpaWrapperGrammarStartNoEventClonep = NULL; /* It is in metap->marpaWrapperGrammarLexemeClonep */
      }

      /* Assign all shallow things */
      /* lexeme matches all goes through the _marpaESLIFRecognizer_meta_matcherb() method, that creates internally */
      /* a recognizer. Recognizers allocation is quite optimized using a hash of pristine recognizers, but in any case */
      /* whereas the final recognizers comes from a hash or a malloc, there is a marpaESLIFGrammarp in it that have */
      /* a big cost if it is on the stack and not in fake mode. */
      /* So we arrange for this grammar to be on the heap instead: */

      
      /* A meta grammar is the same as the sub-grammar EXCEPT at start */
      metap->lexemeIdi                                 = subSymbolp->idi;
      metap->_grammar                                  = *subGrammarp;
      metap->_grammar.marpaWrapperGrammarStartp        = metap->marpaWrapperGrammarStartp;
      metap->_grammar.marpaWrapperGrammarStartNoEventp = metap->marpaWrapperGrammarStartNoEventp;
      metap->_grammar.starti                           = metap->lexemeIdi;
      metap->_grammar.nTerminall                       = metap->nTerminall;
      metap->_grammar.symbolArraypp                    = metap->symbolArraypp;
      metap->_grammar.nTerminalPristinel               = metap->nTerminalPristinel;
      metap->_grammar.terminalIdArrayPristinep         = metap->terminalIdArrayPristinep;
      metap->_grammar.terminalArrayPristinepp          = metap->terminalArrayPristinepp;
      metap->_marpaESLIFGrammarLexemeClone             = *marpaESLIFGrammarp;
      metap->_marpaESLIFGrammarLexemeClone.grammarp    = &(metap->_grammar);
      metap->marpaESLIFGrammarLexemeClonep             = &(metap->_marpaESLIFGrammarLexemeClone);

      /* Commit resolved level in symbol */
      symbolp->lookupSymbolp = subSymbolp;
      symbolp->lookupResolvedLeveli = subGrammarp->leveli;
      symbolp->lookupLevelDeltai = subGrammarp->leveli - grammarp->leveli;

      MARPAESLIF_TRACEF(marpaESLIFp,  funcs, "Grammar level %d (%s): symbol %d <%s> have grammar resolved level set to %d", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis, symbolp->lookupResolvedLeveli);
    }
  }

  /*
   4. Exception rules:
      - must consist only of lexemes
      - left side of the exception is unique in the whole grammar
      - right side of the exception is unique in the whole grammar
      - both sides must must not have any sub lexeme

      Note that these constraints makes the russel paradox impossible, because they apply to
      any grammar at any level.

  */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      /* Sparse item in grammarStackp -; */
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    ruleStackp = grammarp->ruleStackp;
    for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackp); rulei++) {
      MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei);
      exceptionp = rulep->exceptionp;
      if (exceptionp == NULL) {
        continue;
      }

      symbolp = rulep->rhspp[0];

      /* ---------------------------------------- */
      /* Left side must be a lexeme or a terminal */
      /* ---------------------------------------- */
      if (MARPAESLIF_UNLIKELY(! MARPAESLIF_IS_LEXEME_OR_TERMINAL(symbolp))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d (%s), symbol %d <%s> is on the left side of an exception and must be a lexeme or a terminal", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis);
        goto err;
      }
      /* ----------------------------------------- */
      /* Right side must be a lexeme or a terminal */
      /* ----------------------------------------- */
      if (MARPAESLIF_UNLIKELY(! MARPAESLIF_IS_LEXEME_OR_TERMINAL(exceptionp))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d (%s), symbol %d <%s> is on the right side of an exception and must be a lexeme or a terminal", grammari, grammarp->descp->asciis, exceptionp->idi, exceptionp->descp->asciis);
        goto err;
      }
      /* --------------------------------------------------------- */
      /* left side of the exception is unique in the whole grammar */
      /* --------------------------------------------------------- */
      for (rulej = 0; rulej < GENERICSTACK_USED(ruleStackp); rulej++) {
        if (rulei == rulej) {
          continue;
        }
        MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, ruletmpp, ruleStackp, rulej);
        for (rhsl = 0; rhsl < ruletmpp->nrhsl; rhsl++) {
          if (MARPAESLIF_UNLIKELY(ruletmpp->rhspp[rhsl] == symbolp)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d (%s), symbol %d <%s> is on the left side of an exception: it must be a lexeme that does not appear anywhere else in the grammar, because the exception is considered as being part of the lexeme definition", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis);
            MARPAESLIF_ERRORF(marpaESLIFp, "It has been found in a rule that have this LHS: %s", ruletmpp->lhsp->descp->asciis);
            goto err;
          }
        }
      }

      /* -------------------------------------------- */
      /* both sides must must not have any sub lexeme */
      /* -------------------------------------------- */
      /* They are lexemes, so per def metap->marpaWrapperGrammarLexemeClonep is not NULL */
      /* A special case is with parameterized symbol - we use a double indirection */
      if (MARPAESLIF_IS_LEXEME(symbolp)) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFGrammar_haveLexemeb(marpaESLIFGrammarp, grammarp->leveli + symbolp->lookupLevelDeltai, symbolp->u.metap->marpaWrapperGrammarStartp, &haveLexemeb))) {
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(haveLexemeb)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d (%s), symbol %d <%s> is on the left side of an exception: it must have no sub-lexeme", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis);
          goto err;
        }
      }
      if (MARPAESLIF_IS_LEXEME(exceptionp)) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFGrammar_haveLexemeb(marpaESLIFGrammarp, grammarp->leveli + exceptionp->lookupLevelDeltai, exceptionp->u.metap->marpaWrapperGrammarStartp, &haveLexemeb))) {
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(haveLexemeb)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d (%s), symbol %d <%s> is on the right side of an exception: it must have no sub-lexeme", grammari, grammarp->descp->asciis, exceptionp->idi, exceptionp->descp->asciis);
          goto err;
        }
      }

      /* Remember that this RHS is the member of an exception */
      symbolp->exceptionp = exceptionp;
    }
  }

  /*
   6. The semantic of a nullable LHS must be unique
  */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Checking nullable LHS semantic in grammar level %d (%s)", grammarp->leveli, grammarp->descp->asciis);
    /* First we collect the nullable rule Ids by LHS Id */
    ruleStackp = grammarp->ruleStackp;
    for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackp); rulei++) {
      MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei);
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_rulePropertyb(grammarp->marpaWrapperGrammarStartp, rulep->idi, &(rulep->propertyBitSet)))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "marpaWrapperGrammar_rulePropertyb failure for grammar level %d (%s)", grammarp->leveli, grammarp->descp->asciis);
        goto err;
      }
      if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_NULLABLE) == MARPAWRAPPER_RULE_IS_NULLABLE) {
        GENERICSTACK_PUSH_PTR(rulep->lhsp->nullableRuleStackp, rulep);
        if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(rulep->lhsp->nullableRuleStackp))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "rulep->lhsp->nullableRuleStackp push failure, %s", strerror(errno));
          goto err;
        }
      }
    }

    /* Then we determine the nullable semantic */
    symbolStackp = grammarp->symbolStackp;
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);
      /* Always fetch properties and events - this is used in the grammar show */
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_symbolPropertyb(grammarp->marpaWrapperGrammarStartp, symbolp->idi, &(symbolp->propertyBitSet)))) {
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_symbolEventb(grammarp->marpaWrapperGrammarStartp, symbolp->idi, &(symbolp->eventBitSet)))) {
        goto err;
      }
      if (GENERICSTACK_USED(symbolp->nullableRuleStackp) <= 0) {
        continue;
      }
      if (GENERICSTACK_USED(symbolp->nullableRuleStackp) == 1) {
        /* Just one nullable rule: nullable semantic is this rule's semantic */
        if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_PTR(symbolp->nullableRuleStackp, 0))) {
          /* Impossible */
          MARPAESLIF_ERRORF(marpaESLIFp, "symbolp->nullableRuleStackp at indice 0 is not PTR (got %s, value %d)", _marpaESLIF_genericStack_i_types(symbolp->nullableRuleStackp, 0), GENERICSTACKITEMTYPE(symbolp->nullableRuleStackp, 0));
          goto err;
        }
        rulep = (marpaESLIF_rule_t *) GENERICSTACK_GET_PTR(symbolp->nullableRuleStackp, 0);
        symbolp->nullableActionp = rulep->actionp;
#ifndef MARPAESLIF_NTRACE
        if (symbolp->nullableActionp != NULL) {
          MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Nullable semantic of symbol %d <%s> is %s", symbolp->idi, symbolp->descp->asciis, _marpaESLIF_action2asciis(symbolp->nullableActionp));
        } else {
          MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Nullable semantic of symbol %d <%s> is grammar's default", symbolp->idi, symbolp->descp->asciis);
        }
#endif
      } else {
        short foundEmptyb = 0;
        /* More than one rule. If there is an empty rule, use it. Please note that Marpa precomputation made sure that the */
        /* empty rule is unique (there cannot be LHS ::= ; twice). */
        for (rulei = 0; rulei < GENERICSTACK_USED(symbolp->nullableRuleStackp); rulei++) {
          if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_PTR(symbolp->nullableRuleStackp, rulei))) {
            /* Impossible */
            MARPAESLIF_ERRORF(marpaESLIFp, "symbolp->nullableRuleStackp at indice %d is not PTR (got %s, value %d)", rulei, _marpaESLIF_genericStack_i_types(symbolp->nullableRuleStackp, rulei), GENERICSTACKITEMTYPE(symbolp->nullableRuleStackp, rulei));
            goto err;
          }
          rulep = (marpaESLIF_rule_t *) GENERICSTACK_GET_PTR(symbolp->nullableRuleStackp, rulei);
          if (rulep->nrhsl <= 0) {
            foundEmptyb = 1;
            symbolp->nullableActionp = rulep->actionp;
#ifndef MARPAESLIF_NTRACE
            if (symbolp->nullableActionp != NULL) {
              MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Nullable semantic of symbol %d <%s> is %s", symbolp->idi, symbolp->descp->asciis, _marpaESLIF_action2asciis(symbolp->nullableActionp));
            } else {
              MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Nullable semantic of symbol %d <%s> is grammar's default", symbolp->idi, symbolp->descp->asciis);
            }
#endif
          }
        }
        if (! foundEmptyb) {
          short                doneFirstSemanticb = 0;
          marpaESLIF_action_t *firstSemanticp;

          /* None of the rules is empty. Then the all must have the same semantic */
          for (rulei = 0; rulei < GENERICSTACK_USED(symbolp->nullableRuleStackp); rulei++) {
            if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_PTR(symbolp->nullableRuleStackp, rulei))) {
              /* Impossible */
              MARPAESLIF_ERRORF(marpaESLIFp, "symbolp->nullableRuleStackp at indice %d is not PTR (got %s, value  %d)", rulei, _marpaESLIF_genericStack_i_types(symbolp->nullableRuleStackp, rulei), GENERICSTACKITEMTYPE(symbolp->nullableRuleStackp, rulei));
              goto err;
            }
            rulep = (marpaESLIF_rule_t *) GENERICSTACK_GET_PTR(symbolp->nullableRuleStackp, rulei);
            if (! doneFirstSemanticb) {
              firstSemanticp = rulep->actionp;
              doneFirstSemanticb = 1;
            } else {
              /* This is is ok if it is NULL btw */
              if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_eqb(firstSemanticp, rulep->actionp))) {
                MARPAESLIF_ERRORF(marpaESLIFp, "When nulled, symbol %d <%s> can have more than one semantic, and this is not allowed", symbolp->idi, symbolp->descp->asciis);
                goto err;
              }
            }
          }
          symbolp->nullableActionp = firstSemanticp;
#ifndef MARPAESLIF_NTRACE
          if (symbolp->nullableActionp != NULL) {
            MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Nullable semantic of symbol %d <%s> is %s", symbolp->idi, symbolp->descp->asciis, _marpaESLIF_action2asciis(symbolp->nullableActionp));
          } else {
            MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Nullable semantic of symbol %d <%s> is grammar's default", symbolp->idi, symbolp->descp->asciis);
          }
#endif
        }
      }
    }
  }

  /*
    7. lexeme events are meaningul only on lexemes -; Non-lexeme events are meaningful only on non-lexemes.
       The second case is a bit vicious because marpa allows terminals to be predicted, but not to be completed.
       We restrict the "event" keyword to non-terminals, and the "lexeme event" to terminals.
  */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Checking lexeme events in grammar level %d (%s)", grammarp->leveli, grammarp->descp->asciis);

    symbolStackp = grammarp->symbolStackp;
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);
      if (MARPAESLIF_IS_LEXEME(symbolp)) {
        if (MARPAESLIF_UNLIKELY((symbolp->eventPredicteds != NULL) || (symbolp->eventNulleds != NULL) || (symbolp->eventCompleteds != NULL))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Event on symbol <%s> at grammar level %d (%s) but it is a lexeme, you must use the \":symbol <%s> pause => eventType event => eventName\" form", symbolp->descp->asciis, grammari, grammarp->descp->asciis, symbolp->descp->asciis);
          goto err;
        }
      } else if (MARPAESLIF_UNLIKELY(MARPAESLIF_IS_TERMINAL(symbolp))) {
        if ((symbolp->eventPredicteds != NULL) || (symbolp->eventNulleds != NULL) || (symbolp->eventCompleteds != NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Event on symbol <%s> at grammar level %d (%s) but it is a terminal, you must use the \":symbol <%s> pause => eventType event => eventName\" form", symbolp->descp->asciis, grammari, grammarp->descp->asciis, symbolp->descp->asciis);
          goto err;
        }
      } else {
        if (MARPAESLIF_UNLIKELY((symbolp->eventBefores != NULL) || (symbolp->eventAfters != NULL))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Lexeme or terminal event on symbol <%s> at grammar level %d (%s) but it is not a lexeme nor a terminal, you must use the \"event eventName = eventType <%s>\" form", symbolp->descp->asciis, grammari, grammarp->descp->asciis, symbolp->descp->asciis);
          goto err;
        }
      }
    }
  }

  /*
    8. Grammar names must all be different
  */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Checking name of of grammar level %d (%s)", grammarp->leveli, grammarp->descp->asciis);

    for (grammarj = 0; grammarj < GENERICSTACK_USED(grammarStackp); grammarj++) {
      if (grammari == grammarj) {
        continue;
      }
      if (! GENERICSTACK_IS_PTR(grammarStackp, grammarj)) {
        continue;
      }
      grammar2p = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammarj);
      if (MARPAESLIF_UNLIKELY(_marpaESLIF_string_utf8_eqb(grammarp->descp, grammar2p->descp))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Grammars at level %d and %d have the same name (%s)", grammarp->leveli, grammar2p->leveli, grammarp->descp->asciis);
        goto err;
      }
    }
  }

  /*
   9. :discard events are possible only if the RHS of the :discard rule is not a lexeme
  */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Checking :discard events in grammar level %d (%s)", grammarp->leveli, grammarp->descp->asciis);

    symbolStackp = grammarp->symbolStackp;
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);
      if (! symbolp->discardRhsb) {
        continue;
      }
      if (symbolp->discardEvents == NULL) {
        continue;
      }

      if (MARPAESLIF_UNLIKELY(! symbolp->lhsb)) {
        /* The bootstrap grammar made sure that, if this is a terminal, it is unique in this grammar, so that is ok to */
        /* have an associated event */
        if (MARPAESLIF_UNLIKELY(! MARPAESLIF_IS_TERMINAL(symbolp))) {
          /* This symbol is not an lhs in this grammar */
          MARPAESLIF_ERRORF(marpaESLIFp, "Discard event \"%s\" is not possible unless the RHS is also an LHS at grammar level %d (%s)", symbolp->discardEvents, grammari, grammarp->descp->asciis);
          goto err;
        }
      }
    }
  }

  /* Fill grammars information */
  /* - rule IDs, rule show (ASCII) */
  /* - symbol IDs, symbol show (ASCII) */
  /* - grammar show (ASCII) */
  /* - total number of marpa terminals */
  /* - Internal event types */
  /* - Effective actions */
  /* - Check if a lookahead is composed only of a terminal */
  for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);

    grammarp->defaultRuleActione   = _ruleActionpToActione(grammarp->defaultRuleActionp);
    grammarp->defaultSymbolActione = _symbolActionpToActione(grammarp->defaultSymbolActionp);

    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Filling rule IDs array in grammar level %d (%s)", grammari, grammarp->descp->asciis);
    ruleStackp = grammarp->ruleStackp;
    grammarp->nrulel = GENERICSTACK_USED(ruleStackp);
    if (grammarp->nrulel > 0) {
      if (grammarp->ruleip == NULL) {
        grammarp->ruleip = (int *) malloc(grammarp->nrulel * sizeof(int));
        if (MARPAESLIF_UNLIKELY(grammarp->ruleip == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackp); rulei++) {
          MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, ruleStackp, rulei);
          grammarp->ruleip[rulei] = rulep->idi;
          if (rulep->asciishows == NULL) {
            _marpaESLIF_rule_createshowv(marpaESLIFp, grammarp, rulep, NULL, &asciishowl);
            rulep->asciishows = (char *) malloc(asciishowl);
            if (MARPAESLIF_UNLIKELY(rulep->asciishows == NULL)) {
              MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
              goto err;
            }
            /* It is guaranteed that asciishowl is >= 1 - c.f. _marpaESLIF_rule_createshowv() */
            rulep->asciishows[0] = '\0';
            _marpaESLIF_rule_createshowv(marpaESLIFp, grammarp, rulep, rulep->asciishows, NULL);

            rulep->discardEvente = _eventActionsToActione(rulep->discardEvents);
            rulep->actione       = _ruleActionpToActione(rulep->actionp);

            rulep->effectiveRuleActionp = (rulep->actionp != NULL) ? rulep->actionp : grammarp->defaultRuleActionp;
            rulep->effectiveRuleActione = (rulep->actionp != NULL) ? rulep->actione : grammarp->defaultRuleActione;
          }
        }
      }
    }

    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Filling symbol IDs array in grammar level %d (%s)", grammari, grammarp->descp->asciis);
    symbolStackp = grammarp->symbolStackp;
    grammarp->nsymboll = GENERICSTACK_USED(symbolStackp);
    if (grammarp->nsymboll > 0) {
      if (grammarp->symbolip == NULL) {
        grammarp->symbolip = (int *) malloc(grammarp->nsymboll * sizeof(int));
        if (MARPAESLIF_UNLIKELY(grammarp->symbolip == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
          MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);
          grammarp->symbolip[symboli] = symbolp->idi;

          symbolp->eventBeforee    = _eventActionsToActione(symbolp->eventBefores);
          symbolp->eventAftere     = _eventActionsToActione(symbolp->eventAfters);
          symbolp->eventPredictede = _eventActionsToActione(symbolp->eventPredicteds);
          symbolp->eventNullede    = _eventActionsToActione(symbolp->eventNulleds);
          symbolp->eventCompletede = _eventActionsToActione(symbolp->eventCompleteds);
          symbolp->discardEvente   = _eventActionsToActione(symbolp->discardEvents);
          symbolp->nullableActione = _ruleActionpToActione(symbolp->nullableActionp);
          symbolp->symbolActione   = _symbolActionpToActione(symbolp->symbolActionp);

          symbolp->effectiveNullableActionp = (symbolp->nullableActionp != NULL) ? symbolp->nullableActionp : grammarp->defaultRuleActionp;
          symbolp->effectiveNullableActione = (symbolp->nullableActionp != NULL) ? symbolp->nullableActione : grammarp->defaultRuleActione;
          symbolp->effectiveSymbolActionp   = (symbolp->symbolActionp   != NULL) ? symbolp->symbolActionp   : grammarp->defaultSymbolActionp;
          symbolp->effectiveSymbolActione   = (symbolp->symbolActionp   != NULL) ? symbolp->symbolActione   : grammarp->defaultSymbolActione;

          /* Look if the lookahead meta is composed only a single terminal */
          if (MARPAESLIF_IS_META_LOOKAHEAD(symbolp)) {
            /* A lookahead symbol is mapped to a symbol in the same grammar that is the LHS of a single rule (c.f. bootstrap.c) */
            subRulep = (marpaESLIF_rule_t *) GENERICSTACK_GET_PTR(symbolp->lookupSymbolp->lhsRuleStackp, 0);
	    symbolp->lookaheadSymbolp = subRulep->rhspp[0];
            symbolp->lookaheadIsTerminalb = MARPAESLIF_IS_TERMINAL(symbolp->lookaheadSymbolp);
	    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s), symbol %d <%s> lookahead %s a terminal", grammari, grammarp->descp->asciis, symbolp->idi, symbolp->descp->asciis, symbolp->lookaheadIsTerminalb ? "is" : "is not");
          }
        }
      }
    }
  }

  rcb = 1;
  goto done;
  
 err:
  rcb = 0;

 done:
  if (marpaWrapperGrammarStartClonep != NULL) {
    marpaWrapperGrammar_freev(marpaWrapperGrammarStartClonep);
  }
  if (marpaWrapperGrammarStartNoEventClonep != NULL) {
    marpaWrapperGrammar_freev(marpaWrapperGrammarStartNoEventClonep);
  }
  if (marpaWrapperRecognizerp != NULL) {
    marpaWrapperRecognizer_freev(marpaWrapperRecognizerp);
  }

  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %d", (int) rcb);
  return rcb;
}

/*****************************************************************************/
static inline marpaESLIF_internal_event_action_t _eventActionsToActione(char *actions)
/*****************************************************************************/
{
  if ((actions != NULL) && (actions[0] == ':')) {
    if (strcmp(actions, ":symbol") == 0) {
      return MARPAESLIF_INTERNAL_EVENT_ACTION__SYMBOL;
    } else if (strcmp(actions, ":discard[on]") == 0) {
      return MARPAESLIF_INTERNAL_EVENT_ACTION__DISCARD_ON;
    } else if (strcmp(actions, ":discard[off]") == 0) {
      return MARPAESLIF_INTERNAL_EVENT_ACTION__DISCARD_OFF;
    } else if (strcmp(actions, ":discard[switch]") == 0) {
      return MARPAESLIF_INTERNAL_EVENT_ACTION__DISCARD_SWITCH;
    }
  }

  return MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
}

/*****************************************************************************/
static inline marpaESLIF_internal_rule_action_t _ruleActionpToActione(marpaESLIFAction_t *actionp)
/*****************************************************************************/
{
  if ((actionp != NULL) && (actionp->type == MARPAESLIF_ACTION_TYPE_NAME)) {
    if (strcmp(actionp->u.names, "::shift") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___SHIFT;
    } else if (strcmp(actionp->u.names, "::undef") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___UNDEF;
    } else if (strcmp(actionp->u.names, "::ascii") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___ASCII;
    } else if (strncmp(actionp->u.names, "::convert", convertl) == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___CONVERT;
    } else if (strcmp(actionp->u.names, "::concat") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___CONCAT;
    } else if (strncmp(actionp->u.names, "::copy", copyl) == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___COPY;
    } else if (strcmp(actionp->u.names, "::true") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___TRUE;
    } else if (strcmp(actionp->u.names, "::false") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___FALSE;
    } else if (strcmp(actionp->u.names, "::json") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___JSON;
    } else if (strcmp(actionp->u.names, "::jsonf") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___JSONF;
    } else if (strcmp(actionp->u.names, "::row") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___ROW;
    } else if (strcmp(actionp->u.names, "::table") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___TABLE;
    } else if (strcmp(actionp->u.names, "::ast") == 0) {
      return MARPAESLIF_INTERNAL_RULE_ACTION___AST;
    }
  }

  return MARPAESLIF_INTERNAL_RULE_ACTION_NA;
}

/*****************************************************************************/
static inline marpaESLIF_internal_symbol_action_t _symbolActionpToActione(marpaESLIFAction_t *actionp)
/*****************************************************************************/
{
  if ((actionp != NULL) && (actionp->type == MARPAESLIF_ACTION_TYPE_NAME)) {
    if (strcmp(actionp->u.names, "::transfer") == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___TRANSFER;
    } else if (strcmp(actionp->u.names, "::undef") == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___UNDEF;
    } else if (strcmp(actionp->u.names, "::ascii") == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___ASCII;
    } else if (strncmp(actionp->u.names, "::convert", convertl) == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___CONVERT;
    } else if (strcmp(actionp->u.names, "::concat") == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___CONCAT;
    } else if (strcmp(actionp->u.names, "::true") == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___TRUE;
    } else if (strcmp(actionp->u.names, "::false") == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___FALSE;
    } else if (strcmp(actionp->u.names, "::json") == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___JSON;
    } else if (strcmp(actionp->u.names, "::jsonf") == 0) {
      return MARPAESLIF_INTERNAL_SYMBOL_ACTION___JSONF;
    }
  }

  return MARPAESLIF_INTERNAL_SYMBOL_ACTION_NA;
}

/*****************************************************************************/
static inline short _marpaESLIFGrammar_haveLexemeb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int grammari, marpaWrapperGrammar_t *marpaWrapperGrammarp, short *haveLexemebp)
/*****************************************************************************/
{
  static const char    *funcs         = "_marpaESLIF_haveLexemeb";
  marpaESLIF_t         *marpaESLIFp   = marpaESLIFGrammarp->marpaESLIFp;
  genericStack_t       *grammarStackp = marpaESLIFGrammarp->grammarStackp;
  short                 haveLexemeb   = 0;
  marpaESLIF_grammar_t *grammarp;
  genericStack_t       *symbolStackp;
  short                 rcb;
  int                   symboli;
  marpaESLIF_symbol_t  *symbolp;
  int                   marpaWrapperSymbolPropertyBitSet;

  /* Get grammar at the wanted level */
  if (MARPAESLIF_UNLIKELY(grammari < 0)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "grammari must be >= 0", grammari);
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_PTR(grammarStackp, grammari))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "No grammar level at level %d", grammari);
    goto err;
  }
  grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);

  /* Lookup all accessible and productive symbols - stop if one of them is a lexeme. */
  symbolStackp = grammarp->symbolStackp;
  for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
    MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFp, symbolp, grammarp, symboli);

    if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_symbolPropertyb(marpaWrapperGrammarp, symboli, &marpaWrapperSymbolPropertyBitSet))) {
      goto err;
    }

    if ((marpaWrapperSymbolPropertyBitSet & MARPAWRAPPER_SYMBOL_IS_PRODUCTIVE) != MARPAWRAPPER_SYMBOL_IS_PRODUCTIVE) {
      continue;
    }

    if ((marpaWrapperSymbolPropertyBitSet & MARPAWRAPPER_SYMBOL_IS_ACCESSIBLE) != MARPAWRAPPER_SYMBOL_IS_ACCESSIBLE) {
      continue;
    }

    if (MARPAESLIF_IS_LEXEME(symbolp)) {
      haveLexemeb = 1;
      break;
    }
  }
  
  rcb = 1;
  if (haveLexemebp != NULL) {
    *haveLexemebp = haveLexemeb;
  }
  goto done;
  
 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline marpaESLIF_grammar_bootstrap_t *_marpaESLIF_grammar_bootstrap_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammarBootstrapp, marpaESLIF_grammar_bootstrap_t *grammarOrigp)
/*****************************************************************************/
{
  static const char              *funcs                 = "_marpaESLIF_grammar_bootstrap_clonep";
  genericStack_t                 *symbolStackOrigp      = grammarOrigp->symbolStackp;
  genericStack_t                 *ruleStackOrigp        = grammarOrigp->ruleStackp;
  int                             leveli                = grammarOrigp->leveli;
  marpaESLIF_grammar_bootstrap_t *grammarp              = NULL;
  marpaESLIF_meta_t              *metap                 = NULL;
  marpaESLIF_symbol_t            *symbolp               = NULL;
  marpaESLIF_terminal_t          *terminalp             = NULL;
  marpaESLIF_terminal_t          *substitutionTerminalp = NULL;
  marpaESLIF_rule_t              *rulep                 = NULL;
  int                             symboli;
  marpaESLIF_symbol_t            *symbolOrigp;
  int                             rulei;
  marpaESLIF_rule_t              *ruleOrigp;
  marpaWrapperGrammarOption_t     marpaWrapperGrammarOption;
  marpaWrapperGrammar_t          *marpaWrapperGrammarStartp;
  genericStack_t                 *symbolStackp;
  genericStack_t                 *ruleStackp;

  marpaWrapperGrammarOption.genericLoggerp    = marpaESLIFp->marpaESLIFOption.genericLoggerp;
  marpaWrapperGrammarOption.warningIsErrorb   = marpaESLIFGrammarBootstrapp->warningIsErrorb;
  marpaWrapperGrammarOption.warningIsIgnoredb = marpaESLIFGrammarBootstrapp->warningIsIgnoredb;
  marpaWrapperGrammarOption.autorankb         = marpaESLIFGrammarBootstrapp->autorankb;

  grammarp = _marpaESLIF_grammar_bootstrap_newp(marpaESLIFp,
                                                marpaESLIFGrammarBootstrapp,
                                                &marpaWrapperGrammarOption,
                                                grammarOrigp->leveli,
                                                GENERICSTACK_USED(symbolStackOrigp),
                                                GENERICSTACK_USED(ruleStackOrigp),
                                                grammarOrigp->descp);
  if (grammarp == NULL) {
    goto err;
  }

  grammarp->nbupdatei          = grammarOrigp->nbupdatei;
  /* grammarp->leveli           = grammarOrigp->leveli; */ /* Done by _marpaESLIF_grammar_bootstrap_newp */
  grammarp->latmb              = grammarOrigp->latmb;
  /* grammarp->descp           = NULL; */ /* Done by _marpaESLIF_grammar_bootstrap_newp */
  /* grammarp->descautob       = 0; */ /* Done by _marpaESLIF_grammar_bootstrap_newp */
  grammarp->discardIsFallbackb = grammarOrigp->discardIsFallbackb;
  if (grammarOrigp->defaultRuleActionp != NULL) {
    grammarp->defaultRuleActionp = _marpaESLIF_action_clonep(marpaESLIFp, grammarOrigp->defaultRuleActionp);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultRuleActionp == NULL)) {
      goto err;
    }
  }
  if (grammarOrigp->defaultSymbolActionp != NULL) {
    grammarp->defaultSymbolActionp = _marpaESLIF_action_clonep(marpaESLIFp, grammarOrigp->defaultSymbolActionp);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultSymbolActionp == NULL)) {
      goto err;
    }
  }
  if (grammarOrigp->defaultEventActionp != NULL) {
    grammarp->defaultEventActionp = _marpaESLIF_action_clonep(marpaESLIFp, grammarOrigp->defaultEventActionp);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultEventActionp == NULL)) {
      goto err;
    }
  }
  if (grammarOrigp->defaultRegexActionp != NULL) {
    grammarp->defaultRegexActionp = _marpaESLIF_action_clonep(marpaESLIFp, grammarOrigp->defaultRegexActionp);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultRegexActionp == NULL)) {
      goto err;
    }
  }
  if (grammarOrigp->defaultEncodings != NULL) {
    grammarp->defaultEncodings = strdup(grammarOrigp->defaultEncodings);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultEncodings == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
  }
  if (grammarOrigp->fallbackEncodings != NULL) {
    grammarp->fallbackEncodings = strdup(grammarOrigp->fallbackEncodings);
    if (MARPAESLIF_UNLIKELY(grammarp->fallbackEncodings == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
  }

  marpaWrapperGrammarStartp = grammarp->marpaWrapperGrammarStartp;

  /* We replay symbols */
  symbolStackp = grammarp->symbolStackp;
  for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackOrigp); symboli++) {
    MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolOrigp, symbolStackOrigp, symboli);
    switch (symbolOrigp->type) {
    case MARPAESLIF_SYMBOL_TYPE_META:
      metap = _marpaESLIF_meta_newp(marpaESLIFp,
                                    grammarp->marpaWrapperGrammarStartp,
                                    MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE,
                                    symbolOrigp->u.metap->asciinames,
                                    NULL /* descEncodings */,
                                    NULL /* descs */,
                                    0 /* descl */,
                                    0 /* lazyb */);
      if (MARPAESLIF_UNLIKELY(metap == NULL)) {
        goto err;
      }
      symbolp = _marpaESLIF_symbol_newp(marpaESLIFp, &(symbolOrigp->marpaESLIFSymbolOption));
      if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
        goto err;
      }
      symbolp->type              = MARPAESLIF_SYMBOL_TYPE_META;
      symbolp->parami            = symbolOrigp->parami;
      symbolp->u.metap           = metap;
      symbolp->idi               = metap->idi;
      if (symbolOrigp->descp != symbolOrigp->u.metap->descp) {
        /* Naming was overwriten */
        symbolp->descp             = _marpaESLIF_string_clonep(marpaESLIFp, symbolOrigp->descp);
        if (MARPAESLIF_UNLIKELY(symbolp->descp == NULL)) {
          goto err;
        }
      } else {
        symbolp->descp             = metap->descp;
      }
      symbolp->parameterizedRhsb = symbolOrigp->parameterizedRhsb;
      metap = NULL; /* metap is now in symbolp */
      break;
    case MARPAESLIF_SYMBOL_TYPE_TERMINAL:
      terminalp = _marpaESLIF_terminal_newp(marpaESLIFp,
                                            grammarp->marpaWrapperGrammarStartp,
                                            MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE,
                                            (symbolOrigp->u.terminalp->descp != NULL) ? symbolOrigp->u.terminalp->descp->encodingasciis : NULL,
					    (symbolOrigp->u.terminalp->descp != NULL) ? symbolOrigp->u.terminalp->descp->bytep : NULL,
                                            (symbolOrigp->u.terminalp->descp != NULL) ? symbolOrigp->u.terminalp->descp->bytel : 0,
                                            symbolOrigp->u.terminalp->type,
                                            symbolOrigp->u.terminalp->modifiers,
                                            symbolOrigp->u.terminalp->pseudob ? NULL : symbolOrigp->u.terminalp->utf8s,
                                            symbolOrigp->u.terminalp->pseudob ? 0 : symbolOrigp->u.terminalp->utf8l,
                                            NULL, /* testFullMatchs */
                                            NULL, /* testPartialMatchs */
                                            symbolOrigp->u.terminalp->pseudob,
                                            symbolOrigp->u.terminalp->regex.characterClassb,
                                            (symbolOrigp->u.terminalp->substitutionPatterns != NULL) ? MARPAESLIF_TERMINAL_TYPE_REGEX : MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                            0 /* substitutionb */);
      if (MARPAESLIF_UNLIKELY(terminalp == NULL)) {
        goto err;
      }
      if (symbolOrigp->u.terminalp->substitutionPatterns != NULL) {
        substitutionTerminalp = _marpaESLIF_terminal_newp(marpaESLIFp,
                                                          grammarp->marpaWrapperGrammarStartp,
                                                          MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE,
                                                          NULL, /* descEncodings */
                                                          NULL, /* descs */
                                                          0, /* descl */
                                                          MARPAESLIF_TERMINAL_TYPE_STRING,
                                                          symbolOrigp->u.terminalp->substitutionModifiers,
                                                          symbolOrigp->u.terminalp->substitutionUtf8s,
                                                          symbolOrigp->u.terminalp->substitutionUtf8l,
                                                          NULL, /* testFullMatchs */
                                                          NULL, /* testPartialMatchs */
                                                          0, /* pseudob */
                                                          0, /* characterClassb */
                                                          MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                                          1 /* substitutionb */);
        if (MARPAESLIF_UNLIKELY(substitutionTerminalp == NULL)) {
          goto err;
        }
      }
      symbolp = _marpaESLIF_symbol_newp(marpaESLIFp, &(symbolOrigp->marpaESLIFSymbolOption));
      if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
        goto err;
      }
      symbolp->type        = MARPAESLIF_SYMBOL_TYPE_TERMINAL;
      symbolp->u.terminalp = terminalp;
      symbolp->idi         = terminalp->idi;
      if (symbolOrigp->descp != symbolOrigp->u.terminalp->descp) {
        /* Naming was overwriten */
        symbolp->descp             = _marpaESLIF_string_clonep(marpaESLIFp, symbolOrigp->descp);
        if (MARPAESLIF_UNLIKELY(symbolp->descp == NULL)) {
          goto err;
        }
      } else {
        symbolp->descp       = terminalp->descp;
      }
      terminalp = NULL; /* terminalp is now in symbolp */

      if (substitutionTerminalp != NULL) {
        symbolp->u.terminalp->substitutionUtf8s     = substitutionTerminalp->utf8s;
        symbolp->u.terminalp->substitutionUtf8l     = substitutionTerminalp->utf8l;
        symbolp->u.terminalp->substitutionModifiers = substitutionTerminalp->modifiers;
        symbolp->u.terminalp->substitutionPatterns  = substitutionTerminalp->patterns;
        symbolp->u.terminalp->substitutionPatternl  = substitutionTerminalp->patternl;
        symbolp->u.terminalp->substitutionPatterni  = substitutionTerminalp->patterni;

        substitutionTerminalp->utf8s     = NULL; /* it is now in symbolp->u.terminalp */
        substitutionTerminalp->modifiers = NULL; /* it is now in symbolp->u.terminalp */
        substitutionTerminalp->patterns  = NULL; /* it is now in symbolp->u.terminalp */
        _marpaESLIF_terminal_freev(substitutionTerminalp);
        substitutionTerminalp = NULL;
      }

      break;
    default:
      MARPAESLIF_ERRORF(marpaESLIFp, "Unknown symbol type %d", symbolp->type);
      goto err;
    }
    /* Common flags that are set by grammar parse */
    symbolp->startb    = symbolOrigp->startb;
    symbolp->discardb  = symbolOrigp->discardb;

    if (symbolOrigp->eventBefores != NULL) {
      symbolp->eventBefores = strdup(symbolOrigp->eventBefores);
      if (MARPAESLIF_UNLIKELY(symbolp->eventBefores == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
    symbolp->eventBeforeb = symbolOrigp->eventBeforeb;

    if (symbolOrigp->eventAfters != NULL) {
      symbolp->eventAfters = strdup(symbolOrigp->eventAfters);
      if (MARPAESLIF_UNLIKELY(symbolp->eventAfters == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
    symbolp->eventAfterb = symbolOrigp->eventAfterb;

    if (symbolOrigp->eventPredicteds != NULL) {
      symbolp->eventPredicteds = strdup(symbolOrigp->eventPredicteds);
      if (MARPAESLIF_UNLIKELY(symbolp->eventPredicteds == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
    symbolp->eventPredictedb = symbolOrigp->eventPredictedb;

    if (symbolOrigp->eventNulleds != NULL) {
      symbolp->eventNulleds = strdup(symbolOrigp->eventNulleds);
      if (MARPAESLIF_UNLIKELY(symbolp->eventNulleds == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
    symbolp->eventNulledb = symbolOrigp->eventNulledb;

    if (symbolOrigp->eventCompleteds != NULL) {
      symbolp->eventCompleteds = strdup(symbolOrigp->eventCompleteds);
      if (MARPAESLIF_UNLIKELY(symbolp->eventCompleteds == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
    symbolp->eventCompletedb = symbolOrigp->eventCompletedb;

    /* It is a non-sense to not have the same idi */
    if (MARPAESLIF_UNLIKELY(symbolp->idi != symbolOrigp->idi)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "symbolp->idi (%d) != symbolOrigp->idi (%d)", symbolp->idi, symbolOrigp->idi);
      goto err;
    }

    /* Some symbol members are set elsewhere in the bootstrap */
    symbolp->priorityi = symbolOrigp->priorityi;

    if (symbolOrigp->symbolActionp != NULL) {
      symbolp->symbolActionp = _marpaESLIF_action_clonep(marpaESLIFp, symbolOrigp->symbolActionp);
      if (MARPAESLIF_UNLIKELY(symbolp->symbolActionp == NULL)) {
        goto err;
      }
    }

    if (symbolOrigp->ifActionp != NULL) {
      symbolp->ifActionp = _marpaESLIF_action_clonep(marpaESLIFp, symbolOrigp->ifActionp);
      if (MARPAESLIF_UNLIKELY(symbolp->ifActionp == NULL)) {
        goto err;
      }
    }

    if (symbolOrigp->generatorActionp != NULL) {
      symbolp->generatorActionp = _marpaESLIF_action_clonep(marpaESLIFp, symbolOrigp->generatorActionp);
      if (MARPAESLIF_UNLIKELY(symbolp->generatorActionp == NULL)) {
        goto err;
      }
    }

    symbolp->verboseb   = symbolOrigp->verboseb;
    symbolp->lookaheadb = symbolOrigp->lookaheadb;

    /* Note that lookupSymbolp requires a second pass - must be done by the caller */

    GENERICSTACK_SET_PTR(symbolStackp, symbolp, symboli);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(symbolStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "symbolStackp push failure, %s", strerror(errno));
      goto err;
    }
    symbolp = NULL; /* symbolp is now in symbolStackp */
  }

  /* We replay rules */
  ruleStackp = grammarp->ruleStackp;
  for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackOrigp); rulei++) {
    MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, ruleOrigp, ruleStackOrigp, rulei);
    rulep = _marpaESLIF_rule_newp(marpaESLIFp,
				  symbolStackp,
				  leveli,
				  marpaWrapperGrammarStartp,
				  (ruleOrigp->descp != NULL) ? ruleOrigp->descp->encodingasciis : NULL,
				  (ruleOrigp->descp != NULL) ? ruleOrigp->descp->bytep : NULL,
				  (ruleOrigp->descp != NULL) ? ruleOrigp->descp->bytel : 0,
				  (ruleOrigp->lhsp != NULL) ? ruleOrigp->lhsp->idi : -1,
				  ruleOrigp->nrhsl,
				  ruleOrigp->rhsip,
				  (ruleOrigp->exceptionp != NULL) ? ruleOrigp->exceptionp->idi : -1,
				  ruleOrigp->ranki,
				  ruleOrigp->nullRanksHighb,
				  ruleOrigp->sequenceb,
				  ruleOrigp->minimumi,
				  (ruleOrigp->separatorp != NULL) ? ruleOrigp->separatorp->idi : -1,
				  ruleOrigp->properb,
				  ruleOrigp->actionp,
				  ruleOrigp->hideseparatorb,
				  ruleOrigp->skipbp,
				  ruleOrigp->declp,
				  ruleOrigp->callpp,
				  ruleOrigp->separatorcallp);
    if (MARPAESLIF_UNLIKELY(rulep == NULL)) {
      goto err;
    }

    /* Some other rule members are set at runtime */
    rulep->internalb = ruleOrigp->internalb;

    if (ruleOrigp->discardEvents != NULL) {
      rulep->discardEvents = strdup(ruleOrigp->discardEvents);
      if (MARPAESLIF_UNLIKELY(rulep->discardEvents == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        goto err;
      }
    }
    rulep->discardEventb = ruleOrigp->discardEventb;
  
    GENERICSTACK_SET_PTR(ruleStackp, rulep, rulei);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(ruleStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "ruleStackp push failure, %s", strerror(errno));
      goto err;
    }
    rulep = NULL; /* rulep is now in ruleStackp */
  }
  
  goto done;

 err:
  _marpaESLIF_grammar_bootstrap_freev(grammarp);
  grammarp = NULL;

 done:
  _marpaESLIF_terminal_freev(terminalp);
  _marpaESLIF_terminal_freev(substitutionTerminalp);
  _marpaESLIF_meta_freev(metap);
  _marpaESLIF_symbol_freev(symbolp);
  _marpaESLIF_rule_freev(rulep);
  return grammarp;
}

/*****************************************************************************/
static inline marpaESLIF_grammar_bootstrap_t *_marpaESLIF_grammar_bootstrap_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammarBootstrapp, marpaWrapperGrammarOption_t *marpaWrapperGrammarOptionp, int leveli, int symbolStackSizei, int ruleStackSizei, marpaESLIF_string_t *descp)
/*****************************************************************************/
{
  static const char              *funcs             = "_marpaESLIF_grammar_bootstrap_newp";
  genericLogger_t                *genericLoggerp    = NULL;
  marpaESLIF_grammar_bootstrap_t *grammarBootstrapp = NULL;
  marpaESLIF_stringGenerator_t    marpaESLIF_stringGenerator;

  if (MARPAESLIF_UNLIKELY(leveli < 0)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Grammar level must be >= 0, current value is %d", leveli);
    goto err;
  }
  
  grammarBootstrapp = (marpaESLIF_grammar_bootstrap_t *) malloc(sizeof(marpaESLIF_grammar_bootstrap_t));
  if (MARPAESLIF_UNLIKELY(grammarBootstrapp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  grammarBootstrapp->marpaESLIFGrammarBootstrapp        = marpaESLIFGrammarBootstrapp;
  grammarBootstrapp->leveli                             = leveli;
  grammarBootstrapp->descp                              = NULL;
  grammarBootstrapp->descautob                          = 0;
  grammarBootstrapp->latmb                              = 1;    /* latmb true is the default */
  grammarBootstrapp->discardIsFallbackb                 = 0;
  grammarBootstrapp->marpaWrapperGrammarStartp          = NULL;
  grammarBootstrapp->symbolStackp                       = NULL; /* Take care, pointer to a stack inside grammar structure */
  grammarBootstrapp->ruleStackp                         = NULL; /* Take care, pointer to a stack inside grammar structure */
  grammarBootstrapp->defaultSymbolActionp               = NULL;
  grammarBootstrapp->defaultRuleActionp                 = NULL;
  grammarBootstrapp->defaultEventActionp                = NULL;
  grammarBootstrapp->defaultRegexActionp                = NULL;
  grammarBootstrapp->nbupdatei                          = 0;    /* Number of updates - used in grammar ESLIF actions */
  grammarBootstrapp->defaultEncodings                   = NULL;
  grammarBootstrapp->fallbackEncodings                  = NULL;

  grammarBootstrapp->marpaWrapperGrammarStartp = marpaWrapperGrammar_newp(marpaWrapperGrammarOptionp);
  if (MARPAESLIF_UNLIKELY(grammarBootstrapp->marpaWrapperGrammarStartp == NULL)) {
    goto err;
  }

  if (descp == NULL) {
    /* Generate a default description */
    marpaESLIF_stringGenerator.marpaESLIFp = marpaESLIFp;
    marpaESLIF_stringGenerator.s           = NULL;
    marpaESLIF_stringGenerator.l           = 0;
    marpaESLIF_stringGenerator.okb         = 0;
    marpaESLIF_stringGenerator.allocl      = 0;

    genericLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIF_generateStringWithLoggerCallback, (void *) &marpaESLIF_stringGenerator, GENERICLOGGER_LOGLEVEL_TRACE);
    if (MARPAESLIF_UNLIKELY(genericLoggerp == NULL)) {
      goto err;
    }
    GENERICLOGGER_TRACEF(genericLoggerp, "Grammar level %d", leveli);
    if (MARPAESLIF_UNLIKELY(! marpaESLIF_stringGenerator.okb)) {
      goto err;
  }
    grammarBootstrapp->descp = _marpaESLIF_string_newp(marpaESLIFp, "ASCII" /* We KNOW we generated an ASCII stringy */, marpaESLIF_stringGenerator.s, strlen(marpaESLIF_stringGenerator.s));
    free(marpaESLIF_stringGenerator.s);
    grammarBootstrapp->descautob = 1;
  } else {
    grammarBootstrapp->descp = _marpaESLIF_string_clonep(marpaESLIFp, descp);
    grammarBootstrapp->descautob = 0;
  }

  if (MARPAESLIF_UNLIKELY(grammarBootstrapp->descp == NULL)) {
    goto err;
  }

  grammarBootstrapp->symbolStackp = &(grammarBootstrapp->_symbolStack);
  if (symbolStackSizei > 0) {
    GENERICSTACK_INIT_SIZED(grammarBootstrapp->symbolStackp, symbolStackSizei);
  } else {
    GENERICSTACK_INIT(grammarBootstrapp->symbolStackp);
  }
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarBootstrapp->symbolStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "symbolStackp initialization failure, %s", strerror(errno));
    grammarBootstrapp->symbolStackp = NULL;
    goto err;
  }

  grammarBootstrapp->ruleStackp = &(grammarBootstrapp->_ruleStack);
  if (ruleStackSizei > 0) {
    GENERICSTACK_INIT_SIZED(grammarBootstrapp->ruleStackp, ruleStackSizei);
  } else {
    GENERICSTACK_INIT(grammarBootstrapp->ruleStackp);
  }
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarBootstrapp->ruleStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "ruleStackp initialization failure, %s", strerror(errno));
    grammarBootstrapp->ruleStackp = NULL;
    goto err;
  }

  goto done;

 err:
  _marpaESLIF_grammar_bootstrap_freev(grammarBootstrapp);
  grammarBootstrapp = NULL;

 done:
  GENERICLOGGER_FREE(genericLoggerp);
  return grammarBootstrapp;
}

/*****************************************************************************/
static inline short _marpaESLIF_grammar_initb(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, int leveli, marpaESLIFGrammar_t *marpaESLIFGrammarp)
/*****************************************************************************/
{
  short rcb;

  grammarp->marpaESLIFGrammarp                 = marpaESLIFGrammarp;
  grammarp->Lsharep                            = (marpaESLIFGrammarp != NULL) ? marpaESLIFGrammarp->Lsharep : NULL;
  grammarp->leveli                             = leveli;
  grammarp->descp                              = NULL;
  grammarp->descautob                          = 0;
  grammarp->latmb                              = 1;    /* latmb true is the default */
  grammarp->discardIsFallbackb                 = 0;
  grammarp->marpaWrapperGrammarStartp          = NULL;
  grammarp->marpaWrapperGrammarStartNoEventp   = NULL;
  grammarp->nTerminall                         = 0;
  grammarp->symbolArraypp                      = NULL;
  grammarp->nTerminalPristinel                 = 0;
  grammarp->terminalIdArrayPristinep           = NULL;
  grammarp->terminalArrayPristinepp            = NULL;
  grammarp->marpaWrapperGrammarDiscardp        = NULL;
  grammarp->marpaWrapperGrammarDiscardNoEventp = NULL;
  grammarp->nTerminalDiscardPristinel          = 0;
  grammarp->terminalIdArrayDiscardPristinep    = NULL;
  grammarp->terminalArrayDiscardPristinepp     = NULL;
  grammarp->discardp                           = NULL;
  grammarp->symbolStackp                       = NULL; /* Take care, pointer to a stack inside grammar structure */
  grammarp->ruleStackp                         = NULL; /* Take care, pointer to a stack inside grammar structure */
  grammarp->defaultSymbolActionp               = NULL;
  grammarp->defaultSymbolActione               = MARPAESLIF_INTERNAL_SYMBOL_ACTION_NA;
  grammarp->defaultRuleActionp                 = NULL;
  grammarp->defaultRuleActione                 = MARPAESLIF_INTERNAL_RULE_ACTION_NA;
  grammarp->defaultEventActionp                = NULL;
  grammarp->defaultRegexActionp                = NULL;
  grammarp->starti                             = 0;    /* Filled during grammar validation */
  grammarp->starts                             = NULL; /* Filled during grammar validation - shallow pointer */
  grammarp->ruleip                             = NULL; /* Filled by grammar validation */
  grammarp->nrulel                             = 0;    /* Filled by grammar validation */
  grammarp->symbolip                           = NULL; /* Filled by grammar validation */
  grammarp->nsymboll                           = 0;    /* Filled by grammar validation */
  grammarp->nbupdatei                          = 0;    /* Number of updates - used in grammar ESLIF actions */
  grammarp->asciishows                         = NULL;
  grammarp->discardi                           = -1;   /* Eventually filled to a value >= 0 during grammar validation */
  grammarp->defaultEncodings                   = NULL;
  grammarp->fallbackEncodings                  = NULL;
  grammarp->fastDiscardb                       = 0;    /* Filled by grammar validation */
  grammarp->allSymbolsArraypp                  = NULL;
  grammarp->allRulesArraypp                    = NULL;
  grammarp->expectedTerminalIdArrayp           = NULL;
  grammarp->expectedTerminalArraypp            = NULL;

  grammarp->symbolStackp = &(grammarp->_symbolStack);
  GENERICSTACK_INIT(grammarp->symbolStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarp->symbolStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "symbolStackp initialization failure, %s", strerror(errno));
    grammarp->symbolStackp = NULL;
    goto err;
  }

  grammarp->ruleStackp = &(grammarp->_ruleStack);
  GENERICSTACK_INIT(grammarp->ruleStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarp->ruleStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "ruleStackp initialization failure, %s", strerror(errno));
    grammarp->ruleStackp = NULL;
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline marpaESLIF_grammar_t *_marpaESLIF_grammar_newp(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaWrapperGrammarOption_t *marpaWrapperGrammarOptionp, int leveli, char *descEncodings, char *descs, size_t descl, marpaESLIF_action_t *defaultSymbolActionp, marpaESLIF_action_t *defaultRuleActionp, marpaESLIF_action_t *defaultEventActionp, marpaESLIF_action_t *defaultRegexActionp, char *defaultEncodings, char *fallbackEncodings)
/*****************************************************************************/
{
  static const char             *funcs          = "_marpaESLIF_grammar_newp";
  marpaESLIF_t                  *marpaESLIFp    = marpaESLIFGrammarp->marpaESLIFp;
  genericLogger_t               *genericLoggerp = NULL;
  marpaESLIF_grammar_t          *grammarp       = NULL;
  marpaESLIF_stringGenerator_t   marpaESLIF_stringGenerator;

  /* MARPAESLIF_TRACE(marpaESLIFp, funcs, "Building ESLIF grammar"); */

  if (MARPAESLIF_UNLIKELY(leveli < 0)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Grammar level must be >= 0, current value is %d", leveli);
    goto err;
  }
  
  grammarp = (marpaESLIF_grammar_t *) malloc(sizeof(marpaESLIF_grammar_t));
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  if (! _marpaESLIF_grammar_initb(marpaESLIFp, grammarp, leveli, marpaESLIFGrammarp)) {
    goto err;
  }

  /* marpaWrapperGrammarOptionp should be NULL ONLY when we are transfering a bootstrap grammar to a non bootstrap grammar */
  if (marpaWrapperGrammarOptionp != NULL) {
    grammarp->marpaWrapperGrammarStartp = marpaWrapperGrammar_newp(marpaWrapperGrammarOptionp);
    if (MARPAESLIF_UNLIKELY(grammarp->marpaWrapperGrammarStartp == NULL)) {
      goto err;
    }
  }

  /* ----------- Grammar description ------------- */
  if ((descs == NULL) || (descl <= 0)) {
    /* Generate a default description */
    marpaESLIF_stringGenerator.marpaESLIFp = marpaESLIFp;
    marpaESLIF_stringGenerator.s           = NULL;
    marpaESLIF_stringGenerator.l           = 0;
    marpaESLIF_stringGenerator.okb         = 0;
    marpaESLIF_stringGenerator.allocl      = 0;

    genericLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIF_generateStringWithLoggerCallback, (void *) &marpaESLIF_stringGenerator, GENERICLOGGER_LOGLEVEL_TRACE);
    if (MARPAESLIF_UNLIKELY(genericLoggerp == NULL)) {
      goto err;
    }
    GENERICLOGGER_TRACEF(genericLoggerp, "Grammar level %d", leveli);
    if (MARPAESLIF_UNLIKELY(! marpaESLIF_stringGenerator.okb)) {
      goto err;
    }
    grammarp->descp = _marpaESLIF_string_newp(marpaESLIFp, "ASCII" /* We KNOW we generated an ASCII stringy */, marpaESLIF_stringGenerator.s, strlen(marpaESLIF_stringGenerator.s));
    free(marpaESLIF_stringGenerator.s);
    grammarp->descautob = 1;
  } else {
    grammarp->descp = _marpaESLIF_string_newp(marpaESLIFp, descEncodings, descs, descl);
    grammarp->descautob = 0;
  }
  if (MARPAESLIF_UNLIKELY(grammarp->descp == NULL)) {
    goto err;
  }

  if (defaultSymbolActionp != NULL) {
    if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, defaultSymbolActionp))) {
      goto err;
    }
    grammarp->defaultSymbolActionp = _marpaESLIF_action_clonep(marpaESLIFp, defaultSymbolActionp);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultSymbolActionp == NULL)) {
      goto err;
    }
  }

  if (defaultRuleActionp != NULL) {
    if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, defaultRuleActionp))) {
      goto err;
    }
    grammarp->defaultRuleActionp = _marpaESLIF_action_clonep(marpaESLIFp, defaultRuleActionp);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultRuleActionp == NULL)) {
      goto err;
    }
  }

  if (defaultEventActionp != NULL) {
    if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, defaultEventActionp))) {
      goto err;
    }
    grammarp->defaultEventActionp = _marpaESLIF_action_clonep(marpaESLIFp, defaultEventActionp);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultEventActionp == NULL)) {
      goto err;
    }
  }

  if (defaultRegexActionp != NULL) {
    if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, defaultRegexActionp))) {
      goto err;
    }
    grammarp->defaultRegexActionp = _marpaESLIF_action_clonep(marpaESLIFp, defaultRegexActionp);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultRegexActionp == NULL)) {
      goto err;
    }
  }

  if (defaultEncodings != NULL) {
    grammarp->defaultEncodings = strdup(defaultEncodings);
    if (MARPAESLIF_UNLIKELY(grammarp->defaultEncodings == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
  }

  if (fallbackEncodings != NULL) {
    grammarp->fallbackEncodings = strdup(fallbackEncodings);
    if (MARPAESLIF_UNLIKELY(grammarp->fallbackEncodings == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
  }

  goto done;

 err:
  _marpaESLIF_grammar_freev(grammarp);
  grammarp = NULL;

 done:
  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", grammarp); */
  GENERICLOGGER_FREE(genericLoggerp);
  return grammarp;
}

/*****************************************************************************/
static inline void _marpaESLIF_grammar_bootstrap_freev(marpaESLIF_grammar_bootstrap_t *grammarp)
/*****************************************************************************/
{
  if (grammarp != NULL) {
    if (grammarp->marpaWrapperGrammarStartp != NULL) {
      marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarStartp);
    }
    _marpaESLIF_string_freev(grammarp->descp, 0 /* onStackb */);
    _marpaESLIF_action_freev(grammarp->defaultRuleActionp);
    _marpaESLIF_action_freev(grammarp->defaultSymbolActionp);
    _marpaESLIF_action_freev(grammarp->defaultEventActionp);
    _marpaESLIF_action_freev(grammarp->defaultRegexActionp);
    if (grammarp->defaultEncodings != NULL) {
      free(grammarp->defaultEncodings);
    }
    if (grammarp->fallbackEncodings != NULL) {
      free(grammarp->fallbackEncodings);
    }
    _marpaESLIF_symbolStack_freev(grammarp->symbolStackp);
    _marpaESLIF_ruleStack_freev(grammarp->ruleStackp);
    free(grammarp);
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_grammar_freev(marpaESLIF_grammar_t *grammarp)
/*****************************************************************************/
{
  if (grammarp != NULL) {
    _marpaESLIF_string_freev(grammarp->descp, 0 /* onStackb */);
    if (grammarp->marpaWrapperGrammarStartp != NULL) {
      marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarStartp);
    }
    if (grammarp->marpaWrapperGrammarStartNoEventp != NULL) {
      marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarStartNoEventp);
    }
    if (grammarp->terminalIdArrayPristinep != NULL) {
      free(grammarp->terminalIdArrayPristinep);
    }
    if (grammarp->terminalArrayPristinepp != NULL) {
      free(grammarp->terminalArrayPristinepp);
    }
    if (grammarp->marpaWrapperGrammarDiscardp != NULL) {
      marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarDiscardp);
    }
    if (grammarp->marpaWrapperGrammarDiscardNoEventp != NULL) {
      marpaWrapperGrammar_freev(grammarp->marpaWrapperGrammarDiscardNoEventp);
    }
    if (grammarp->terminalIdArrayDiscardPristinep != NULL) {
      free(grammarp->terminalIdArrayDiscardPristinep);
    }
    if (grammarp->terminalArrayDiscardPristinepp != NULL) {
      free(grammarp->terminalArrayDiscardPristinepp);
    }
    _marpaESLIF_symbolStack_freev(grammarp->symbolStackp);
    _marpaESLIF_ruleStack_freev(grammarp->ruleStackp);
    if (grammarp->ruleip != NULL) {
      free(grammarp->ruleip);
    }
    if (grammarp->symbolip != NULL) {
      free(grammarp->symbolip);
    }
    _marpaESLIF_action_freev(grammarp->defaultSymbolActionp);
    _marpaESLIF_action_freev(grammarp->defaultRuleActionp);
    _marpaESLIF_action_freev(grammarp->defaultEventActionp);
    _marpaESLIF_action_freev(grammarp->defaultRegexActionp);
    if (grammarp->defaultEncodings != NULL) {
      free(grammarp->defaultEncodings);
    }
    if (grammarp->fallbackEncodings != NULL) {
      free(grammarp->fallbackEncodings);
    }
    if (grammarp->asciishows != NULL) {
      free(grammarp->asciishows);
    }
    if (grammarp->symbolArraypp != NULL) {
      free(grammarp->symbolArraypp);
    }
    if (grammarp->allSymbolsArraypp != NULL) {
      free(grammarp->allSymbolsArraypp);
    }
    if (grammarp->allRulesArraypp != NULL) {
      free(grammarp->allRulesArraypp);
    }
    if (grammarp->expectedTerminalIdArrayp != NULL) {
      free(grammarp->expectedTerminalIdArrayp);
    }
    if (grammarp->expectedTerminalArraypp != NULL) {
      free(grammarp->expectedTerminalArraypp);
    }
    free(grammarp);
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_ruleStack_freev(genericStack_t *ruleStackp)
/*****************************************************************************/
{
  if (ruleStackp != NULL) {
    while (GENERICSTACK_USED(ruleStackp) > 0) {
      if (GENERICSTACK_IS_PTR(ruleStackp, GENERICSTACK_USED(ruleStackp) - 1)) {
	marpaESLIF_rule_t *rulep = (marpaESLIF_rule_t *) GENERICSTACK_POP_PTR(ruleStackp);
	_marpaESLIF_rule_freev(rulep);
      } else {
	GENERICSTACK_USED(ruleStackp)--;
      }
    }
    GENERICSTACK_RESET(ruleStackp); /* Take care, ruleStackp is a pointer to a stack inside grammar structure */
  }
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_lexemeStack_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_lexemeStack_freev";

  if (marpaESLIFRecognizerp->lexemeStackp != NULL) {
    MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

    _marpaESLIFRecognizer_lexemeStack_resetv(marpaESLIFRecognizerp);
    GENERICSTACK_RESET(marpaESLIFRecognizerp->lexemeStackp); /* Take care, lexemeStackp is a pointer to a static genericStack_t in recognizer's structure */

    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "return");
    MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  }

}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_lexemeStack_resetv(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_lexemeStack_resetv";
  int                i;
  int                usedi;

  if (marpaESLIFRecognizerp->lexemeStackp != NULL) {

    usedi = GENERICSTACK_USED(marpaESLIFRecognizerp->lexemeStackp);
    for (i = --usedi; i > 0; --i) {
      /* This will not be executed if we start with usedi <= 1 */
      _marpaESLIFRecognizer_internalStack_i_setb(marpaESLIFRecognizerp,
                                                 marpaESLIFRecognizerp->lexemeStackp,
                                                 i,
                                                 (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef,
                                                 0, /* forgetb */
                                                 NULL /* marpaESLIFValueResultOrigp */);
    }
    GENERICSTACK_RELAX(marpaESLIFRecognizerp->lexemeStackp);
  }
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_lexemeStack_i_setb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, int i, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_lexemeStack_i_setb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Validate the input */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_value_validb(marpaESLIFRecognizerp, marpaESLIFValueResultp, NULL /* userDatavp */, NULL /* callbackp */))) {
    goto err;
  }

  /* Lexeme input stack is a stack of marpaESLIFValueResult */
  rcb = _marpaESLIFRecognizer_internalStack_i_setb(marpaESLIFRecognizerp,
						   marpaESLIFRecognizerp->lexemeStackp,
						   i,
						   marpaESLIFValueResultp,
						   0, /* forgetb */
						   NULL /* marpaESLIFValueResultOrigp */);
  
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);

  return rcb;
}

/*****************************************************************************/
static inline marpaESLIF_rule_t *_marpaESLIF_rule_newp(marpaESLIF_t *marpaESLIFp, genericStack_t *symbolStackp, int leveli, marpaWrapperGrammar_t *marpaWrapperGrammarStartp, char *descEncodings, char *descs, size_t descl, int lhsi, size_t nrhsl, int *rhsip, int exceptioni, int ranki, short nullRanksHighb, short sequenceb, int minimumi, int separatori, short properb, marpaESLIF_action_t *actionp, short hideseparatorb, short *skipbp, marpaESLIF_lua_functiondecl_t *declp, marpaESLIF_lua_functioncall_t **callpp, marpaESLIF_lua_functioncall_t *separatorcallp)
/*****************************************************************************/
{
  static const char               *funcs          = "_marpaESLIF_rule_newp";
  marpaESLIF_rule_t               *rulep          = NULL;
  short                            symbolFoundb   = 0;
  genericLogger_t                 *genericLoggerp = NULL;
  marpaESLIF_stringGenerator_t     marpaESLIF_stringGenerator;
  marpaESLIF_symbol_t             *symbolp;
  marpaESLIF_symbol_t             *rhsp;
  marpaWrapperGrammarRuleOption_t  marpaWrapperGrammarRuleOption;
  size_t                           i;
  size_t                           rhsl;

  /* MARPAESLIF_TRACE(marpaESLIFp, funcs, "Building rule"); */

  /* It is a non-sense to provide skipbp without rhsip */
  if (MARPAESLIF_UNLIKELY((skipbp != NULL) && (rhsip == NULL))) {
    MARPAESLIF_ERROR(marpaESLIFp, "(skipbp != NULL) && (rhsip == NULL)");
    goto err;
  }

  rulep = (marpaESLIF_rule_t *) malloc(sizeof(marpaESLIF_rule_t));
  if (MARPAESLIF_UNLIKELY(rulep == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  rulep->effectiveRuleActionp = NULL;
  rulep->effectiveRuleActione = MARPAESLIF_INTERNAL_RULE_ACTION_NA;

  rulep->idi                = -1;
  rulep->descp              = NULL;
  rulep->descautob          = 0;
  rulep->asciishows         = NULL; /* Filled by grammar validation */
  rulep->lhsp               = NULL;
  rulep->separatorp         = NULL;
  rulep->nrhsl              = nrhsl;
  rulep->rhspp              = NULL;
  rulep->rhsip              = NULL;
  rulep->skipbp             = NULL;
  rulep->exceptionp         = NULL;
  rulep->exceptionIdi       = -1;
  rulep->actionp            = NULL;
  rulep->actione            = MARPAESLIF_INTERNAL_RULE_ACTION_NA;
  rulep->discardEvents      = NULL;
  rulep->discardEventb      = 0;
  rulep->discardEvente      = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  rulep->ranki              = ranki;
  rulep->nullRanksHighb     = nullRanksHighb;
  rulep->sequenceb          = sequenceb;
  rulep->properb            = properb;
  rulep->minimumi           = minimumi;
  rulep->propertyBitSet     = 0; /* Filled by grammar validation */
  rulep->hideseparatorb     = hideseparatorb;
  rulep->declp              = NULL;
  rulep->callpp             = NULL;
  rulep->separatorcallp     = NULL;
  rulep->internalb          = 0;

  if (nrhsl > 0) {
    rulep->rhspp = (marpaESLIF_symbol_t **) malloc(nrhsl * sizeof(marpaESLIF_symbol_t *));
    if (MARPAESLIF_UNLIKELY(rulep->rhspp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    rulep->rhsip = (int *) malloc(nrhsl * sizeof(int));
    if (MARPAESLIF_UNLIKELY(rulep->rhsip == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    rulep->callpp = (marpaESLIF_lua_functioncall_t **) malloc(nrhsl * sizeof(marpaESLIF_lua_functioncall_t *));
    if (MARPAESLIF_UNLIKELY(rulep->callpp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    for (i = 0; i < nrhsl; i++) {
      rulep->callpp[i] = NULL;
    }
  }

  /* Set LHS symbol in rule */
  MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, lhsi);
  rulep->lhsp = symbolp;

  /* Set separator symbol in rule */
  if (sequenceb && (separatori >= 0)) {
    MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, separatori);
    rulep->separatorp = symbolp;
  }

  /* Set RHS symbols and ids in rule */
  for (i = 0; i < nrhsl; i++) {
    MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, rhsip[i]);
    rulep->rhspp[i] = symbolp;
    rulep->rhsip[i] = symbolp->idi;
  }

  /* Set eventual skipped symbols */
  if (nrhsl > 0) {
    if (skipbp != NULL) {
      rulep->skipbp = (short *) malloc(sizeof(short) * nrhsl);
      if (MARPAESLIF_UNLIKELY(rulep->skipbp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      memcpy(rulep->skipbp, skipbp, sizeof(short) * nrhsl);
    }
  }
  
  /* Fill exception symbol */
  if (exceptioni >= 0) {
    MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, rulep->exceptionp, symbolStackp, exceptioni);
    /* ... and make sure that there is only one RHS */
    if (MARPAESLIF_UNLIKELY(nrhsl != 1)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d: Rule <%s>: There must be exactly one RHS, instead of %ld, before the '-' exception sign", leveli, rulep->lhsp->descp->asciis, (unsigned long) nrhsl);
      goto err;
    }
  }

  /* Duplicate declp and callpp */
  if (declp != NULL) {
    rulep->declp = _marpaESLIF_lua_functiondecl_clonep(marpaESLIFp, declp);
    if (MARPAESLIF_UNLIKELY(rulep->declp == NULL)) {
      goto err;
    }
  }
  if (callpp != NULL) {
    for (i = 0; i < nrhsl; i++) {
      if (callpp[i] != NULL) {
        rulep->callpp[i] = _marpaESLIF_lua_functioncall_clonep(marpaESLIFp, callpp[i]);
        if (MARPAESLIF_UNLIKELY(rulep->callpp[i] == NULL)) {
          goto err;
        }
      }
    }
  }
  if (separatorcallp != NULL) {
    rulep->separatorcallp = _marpaESLIF_lua_functioncall_clonep(marpaESLIFp, separatorcallp);
    if (MARPAESLIF_UNLIKELY(rulep->separatorcallp == NULL)) {
      goto err;
    }
  }

  marpaWrapperGrammarRuleOption.ranki            = ranki;
  marpaWrapperGrammarRuleOption.nullRanksHighb   = nullRanksHighb;
  marpaWrapperGrammarRuleOption.sequenceb        = sequenceb;
  marpaWrapperGrammarRuleOption.separatorSymboli = separatori;
  marpaWrapperGrammarRuleOption.properb          = properb;
  marpaWrapperGrammarRuleOption.minimumi         = minimumi;

  /* ----------- Meta Identifier ------------ */
  rulep->idi = marpaWrapperGrammar_newRulei(marpaWrapperGrammarStartp, &marpaWrapperGrammarRuleOption, lhsi, nrhsl, rhsip);
  if (MARPAESLIF_UNLIKELY(rulep->idi < 0)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d: Rule <%s>: Creation failure", leveli, rulep->lhsp->descp->asciis);
    goto err;
  }

  /* ---------------- Action ---------------- */
  if (actionp != NULL) {
    if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, actionp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d: Rule <%s>: Invalid action", leveli, rulep->lhsp->descp->asciis);
      goto err;
    }
    rulep->actionp = _marpaESLIF_action_clonep(marpaESLIFp, actionp);
    if (MARPAESLIF_UNLIKELY(rulep->actionp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "At grammar level %d: Rule <%s>: Clone failure", leveli, rulep->lhsp->descp->asciis);
      goto err;
    }
  }

  /* -------- Rule Description -------- */
  if ((descs == NULL) || (descl <= 0)) {
    /* Generate a default description */
    marpaESLIF_stringGenerator.marpaESLIFp = marpaESLIFp;
    marpaESLIF_stringGenerator.s           = NULL;
    marpaESLIF_stringGenerator.l           = 0;
    marpaESLIF_stringGenerator.okb         = 0;
    marpaESLIF_stringGenerator.allocl      = 0;

    genericLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIF_generateStringWithLoggerCallback, (void *) &marpaESLIF_stringGenerator, GENERICLOGGER_LOGLEVEL_TRACE);
    if (MARPAESLIF_UNLIKELY(genericLoggerp == NULL)) {
      goto err;
    }
    GENERICLOGGER_TRACEF(genericLoggerp, "Rule No %d", rulep->idi);
    if (MARPAESLIF_UNLIKELY(! marpaESLIF_stringGenerator.okb)) {
      goto err;
    }
    rulep->descp = _marpaESLIF_string_newp(marpaESLIFp, "ASCII" /* We KNOW we generated an ASCII stringy */, marpaESLIF_stringGenerator.s, strlen(marpaESLIF_stringGenerator.s));
    rulep->descautob = 1;
    free(marpaESLIF_stringGenerator.s);
  } else {
    rulep->descp = _marpaESLIF_string_newp(marpaESLIFp, descEncodings, descs, descl);
    rulep->descautob = 0;
  }
  if (MARPAESLIF_UNLIKELY(rulep->descp == NULL)) {
    goto err;
  }

  if (symbolStackp != NULL) {
    /* For every parameterized symbol, that is unique in the grammar, associate shallow pointers to decl and call */
    for (rhsl = 0; rhsl < nrhsl; rhsl++) {
      MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, rhsp, symbolStackp, rhsip[rhsl]);
      if (rhsp->parameterizedRhsb) {
        rhsp->declp = rulep->declp;        /* May be NULL */
        rhsp->callp = rulep->callpp[rhsl]; /* Never null by definition when it is a parameterized symbol */
      }
    }
    if (rulep->separatorp != NULL) {
      rhsp = rulep->separatorp;
      if (rhsp->parameterizedRhsb) {
        rhsp->declp = rulep->declp;          /* May be NULL */
        rhsp->callp = rulep->separatorcallp; /* Never null by definition when it is a parameterized symbol */
      }
    }
  }

  goto done;

 err:
  _marpaESLIF_rule_freev(rulep);
  rulep = NULL;

 done:
  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", rulep); */
  GENERICLOGGER_FREE(genericLoggerp);
  return rulep;
}

/*****************************************************************************/
static inline void _marpaESLIF_rule_freev(marpaESLIF_rule_t *rulep)
/*****************************************************************************/
{
  size_t rhsl;

  if (rulep != NULL) {
    _marpaESLIF_string_freev(rulep->descp, 0 /* onStackb */);
    if (rulep->asciishows != NULL) {
      free(rulep->asciishows);
    }
    _marpaESLIF_action_freev(rulep->actionp);
    if (rulep->rhspp != NULL) {
      free(rulep->rhspp);
    }
    if (rulep->rhsip != NULL) {
      free(rulep->rhsip);
    }
    if (rulep->skipbp != NULL) {
      free(rulep->skipbp);
    }
    if (rulep->discardEvents) {
      free(rulep->discardEvents);
    }
    _marpaESLIF_lua_functiondecl_freev(rulep->declp);
    if (rulep->callpp != NULL) {
      for (rhsl = 0; rhsl < rulep->nrhsl; rhsl++) {
        _marpaESLIF_lua_functioncall_freev(rulep->callpp[rhsl]);
      }
      free(rulep->callpp);
    }
    _marpaESLIF_lua_functioncall_freev(rulep->separatorcallp);
    free(rulep);
  }
}

/*****************************************************************************/
static inline marpaESLIF_symbol_t *_marpaESLIF_symbol_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  static const char   *funcs   = "_marpaESLIF_symbol_newp";
  marpaESLIF_symbol_t *symbolp = NULL;

  /* MARPAESLIF_TRACE(marpaESLIFp, funcs, "Building symbol"); */

  symbolp = (marpaESLIF_symbol_t *) malloc(sizeof(marpaESLIF_symbol_t));
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  /* External symbols will have to set the effective members explicitly - these are all shallow pointers */
  symbolp->effectiveNullableActionp = NULL;
  symbolp->effectiveNullableActione = MARPAESLIF_INTERNAL_RULE_ACTION_NA;
  symbolp->effectiveSymbolActionp   = NULL;
  symbolp->effectiveSymbolActione   = MARPAESLIF_INTERNAL_SYMBOL_ACTION_NA;

  /* Union itself is undetermined at this stage */
  symbolp->type                     = MARPAESLIF_SYMBOL_TYPE_NA;
  symbolp->marpaESLIFp              = marpaESLIFp;
  symbolp->startb                   = 0;
  symbolp->discardb                 = 0;
  symbolp->discardRhsb              = 0;
  symbolp->lhsb                     = 0;
  symbolp->topb                     = 0; /* Revisited by grammar validation */
  symbolp->idi                      = -1;
  symbolp->descp                    = NULL;
  symbolp->eventBefores             = NULL;
  symbolp->eventBeforeb             = 1; /* An event is on by default */
  symbolp->eventBeforee             = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  symbolp->eventAfters              = NULL;
  symbolp->eventAfterb              = 1; /* An event is on by default */
  symbolp->eventAftere              = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  symbolp->eventPredicteds          = NULL;
  symbolp->eventPredictedb          = 1; /* An event is on by default */
  symbolp->eventPredictede          = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  symbolp->eventNulleds             = NULL;
  symbolp->eventNulledb             = 1; /* An event is on by default */
  symbolp->eventNullede             = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  symbolp->eventCompleteds          = NULL;
  symbolp->eventCompletedb          = 1; /* An event is on by default */
  symbolp->eventCompletede          = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  symbolp->eventDeclp               = NULL;
  symbolp->discardEvents            = NULL; /* Shallow copy */
  symbolp->discardEventb            = 1; /* An event is on by default */
  symbolp->discardEvente            = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  symbolp->lookupLevelDeltai        = 1;   /* Default lookup is the next grammar level */
  symbolp->lookupSymbolp            = NULL;
  symbolp->lookupResolvedLeveli     = 0; /* This will be overwriten by _marpaESLIFGrammar_validateb() and used only when symbol is a lexeme from another grammar */
  symbolp->priorityi                = 0; /* Default priority is 0 */
  symbolp->nullableRuleStackp       = NULL; /* Take care, this is a pointer to an stack inside symbol structure */
  symbolp->nullableActionp          = NULL;
  symbolp->nullableActione          = MARPAESLIF_INTERNAL_RULE_ACTION_NA;
  symbolp->propertyBitSet           = 0; /* Filled by grammar validation */
  symbolp->eventBitSet              = 0; /* Filled by grammar validation */
  symbolp->lhsRuleStackp            = NULL;
  symbolp->exceptionp               = NULL;
  symbolp->symbolActionp            = NULL;
  symbolp->symbolActione            = MARPAESLIF_INTERNAL_SYMBOL_ACTION_NA;
  symbolp->ifActionp                = NULL;
  symbolp->generatorActionp         = NULL;
  symbolp->marpaESLIFSymbolOption   = marpaESLIFSymbolOptionp != NULL ? *marpaESLIFSymbolOptionp : marpaESLIFSymbolOption_default_template;
  symbolp->contentIsShallowb        = 0;
  symbolp->marpaESLIFGrammarp       = NULL; /* Shallow pointer, set by marpaESLIFSymbol_meta_newp() only */
  symbolp->verboseb                 = 0; /* Default verbose is 0 */
  symbolp->parami                   = -1;
  symbolp->parameterizedRhsb        = 0;
  symbolp->declp                    = NULL; /* Shallow pointer to rule (a parameterized symbol is always unique) */
  symbolp->callp                    = NULL; /* Shallow pointer to rule (a parameterized symbol is always unique) */
  symbolp->pushContextActionp       = NULL;
  symbolp->lookaheadb               = 0;
  symbolp->lookaheadIsTerminalb     = 0;
  symbolp->lookaheadSymbolp         = NULL;

  symbolp->nullableRuleStackp = &(symbolp->_nullableRuleStack);
  GENERICSTACK_INIT(symbolp->nullableRuleStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(symbolp->nullableRuleStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "symbolp->nullableRuleStackp initialization failure, %s", strerror(errno));
    symbolp->nullableRuleStackp = NULL;
    goto err;
  }

  symbolp->lhsRuleStackp = &(symbolp->_lhsRuleStack);
  GENERICSTACK_INIT(symbolp->lhsRuleStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(symbolp->lhsRuleStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "symbolp->lhsRuleStackp initialization failure, %s", strerror(errno));
    symbolp->lhsRuleStackp = NULL;
    goto err;
  }
  
  goto done;

 err:
  _marpaESLIF_symbol_freev(symbolp);
  symbolp = NULL;

 done:
  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", symbolp); */
  return symbolp;
}

/*****************************************************************************/
static inline void _marpaESLIF_symbol_freev(marpaESLIF_symbol_t *symbolp)
/*****************************************************************************/
{
  if (symbolp != NULL) {
    if (! symbolp->contentIsShallowb) {
      /* All pointers are the top level of this structure are shallow pointers EXCEPT luaexplist family */
      switch (symbolp->type) {
      case MARPAESLIF_SYMBOL_TYPE_TERMINAL:
        if ((symbolp->descp != NULL) && (symbolp->descp != symbolp->u.terminalp->descp)) {
          /* A :terminal or :symbol rule overwrote default description */
          _marpaESLIF_string_freev(symbolp->descp, 0 /* onStackb */);
        }
        _marpaESLIF_terminal_freev(symbolp->u.terminalp);
        break;
      case MARPAESLIF_SYMBOL_TYPE_META:
        if ((symbolp->descp != NULL) && (symbolp->descp != symbolp->u.metap->descp)) {
          /* A :lexeme or :symbol rule overwrote default description */
          _marpaESLIF_string_freev(symbolp->descp, 0 /* onStackb */);
        }
        _marpaESLIF_meta_freev(symbolp->u.metap);
        break;
      default:
        break;
      }
      if (symbolp->eventBefores != NULL) {
        free(symbolp->eventBefores);
      }
      if (symbolp->eventAfters != NULL) {
        free(symbolp->eventAfters);
      }
      if (symbolp->eventPredicteds) {
        free(symbolp->eventPredicteds);
      }
      if (symbolp->eventNulleds) {
        free(symbolp->eventNulleds);
      }
      if (symbolp->eventCompleteds) {
        free(symbolp->eventCompleteds);
      }
      _marpaESLIF_lua_functiondecl_freev(symbolp->eventDeclp);
      _marpaESLIF_action_freev(symbolp->symbolActionp);
      _marpaESLIF_action_freev(symbolp->ifActionp);
      _marpaESLIF_action_freev(symbolp->generatorActionp);
      _marpaESLIF_action_freev(symbolp->pushContextActionp);

      GENERICSTACK_RESET(symbolp->nullableRuleStackp); /* Take care, this is a pointer to stack internal to symbol structure */
      GENERICSTACK_RESET(symbolp->lhsRuleStackp); /* Take care, this is a pointer to stack internal to symbol structure */
    } /* contentIsShallowb */

    free(symbolp);
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_symbolStack_freev(genericStack_t *symbolStackp)
/*****************************************************************************/
{
  if (symbolStackp != NULL) {
    while (GENERICSTACK_USED(symbolStackp) > 0) {
      if (GENERICSTACK_IS_PTR(symbolStackp, GENERICSTACK_USED(symbolStackp) - 1)) {
	marpaESLIF_symbol_t *symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_POP_PTR(symbolStackp);
	_marpaESLIF_symbol_freev(symbolp);
      } else {
	GENERICSTACK_USED(symbolStackp)--;
      }
    }
    GENERICSTACK_RESET(symbolStackp); /* Take care, this is a pointer to a stack inside symbol structure */
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_terminal_freev(marpaESLIF_terminal_t *terminalp)
/*****************************************************************************/
{
  if (terminalp != NULL) {
    if (terminalp->utf8s != NULL) {
      free(terminalp->utf8s);
    }
    _marpaESLIF_string_freev(terminalp->descp, 0 /* onStackb */);
    if (terminalp->modifiers != NULL) {
      free(terminalp->modifiers);
    }
    if (terminalp->patterns != NULL) {
      free(terminalp->patterns);
    }
    if (terminalp->substitutionUtf8s != NULL) {
      free(terminalp->substitutionUtf8s);
    }
    if (terminalp->substitutionModifiers != NULL) {
      free(terminalp->substitutionModifiers);
    }
    if (terminalp->substitutionPatterns != NULL) {
      free(terminalp->substitutionPatterns);
    }
    if (terminalp->regex.match_datap != NULL) {
      pcre2_match_data_free(terminalp->regex.match_datap);
    }
    if (terminalp->regex.patternp != NULL) {
      pcre2_code_free(terminalp->regex.patternp);
    }
    if (terminalp->regex.compile_contextp != NULL) {
      pcre2_compile_context_free(terminalp->regex.compile_contextp);
    }
    if (terminalp->regex.match_contextp != NULL) {
      pcre2_match_context_free(terminalp->regex.match_contextp);
    }
    if (terminalp->bytes != NULL) {
      free(terminalp->bytes);
    }
    free(terminalp);
  }
}

/*****************************************************************************/
short marpaESLIF_versionb(marpaESLIF_t *marpaESLIFp, char **versionsp)
/*****************************************************************************/
{
  short rcb;
  
  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (versionsp != NULL) {
    *versionsp = marpaESLIFp->versions;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIF_versionMajorb(marpaESLIF_t *marpaESLIFp, int *versionMajorip)
/*****************************************************************************/
{
  short rcb;
  
  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (versionMajorip != NULL) {
    *versionMajorip = marpaESLIFp->versionMajori;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIF_versionMinorb(marpaESLIF_t *marpaESLIFp, int *versionMinorip)
/*****************************************************************************/
{
  short rcb;
  
  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (versionMinorip != NULL) {
    *versionMinorip = marpaESLIFp->versionMinori;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIF_versionPatchb(marpaESLIF_t *marpaESLIFp, int *versionPatchip)
/*****************************************************************************/
{
  short rcb;
  
  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (versionPatchip != NULL) {
    *versionPatchip = marpaESLIFp->versionPatchi;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
marpaESLIF_t *marpaESLIF_newp(marpaESLIFOption_t *marpaESLIFOptionp)
/*****************************************************************************/
{
  return _marpaESLIF_newp(marpaESLIFOptionp);
}

/*****************************************************************************/
static inline marpaESLIF_t *_marpaESLIF_newp(marpaESLIFOption_t *marpaESLIFOptionp)
/*****************************************************************************/
{
  static const char            *funcs       = "marpaESLIF_newp";
  marpaESLIF_grammar_t         *grammarp    = NULL;
  marpaESLIF_grammar_t         *grammar2p   = NULL;
  marpaESLIF_t                 *marpaESLIFp = NULL;
  void                         *NULLp       = NULL;
  int                           zeroInteger = 0;
  void                         *p           = NULL;
#ifdef MARPAESLIF_NAN
  float                         nanf        = MARPAESLIF_NAN;
#endif /*  MARPAESLIF_NAN */
  genericLogger_t              *genericLoggerp;
  genericLoggerLevel_t          genericLoggerLeveli;
  marpaESLIFString_t            newlineString;
  int                           i;
#ifdef MARPAESLIF_HAVE_LONG_LONG
  char                          tmps[MARPAESLIF_MAX_DECIMAL_DIGITS_LONGLONG + 1];
#else
  char                          tmps[MARPAESLIF_MAX_DECIMAL_DIGITS_LONG + 1];
#endif
  marpaESLIFString_t            jsonString;

  if (marpaESLIFOptionp == NULL) {
    marpaESLIFOptionp = &marpaESLIFOption_default_template;
  }

  genericLoggerp = marpaESLIFOptionp->genericLoggerp;
  if (genericLoggerp != NULL) {
    genericLoggerLeveli = genericLogger_logLevel_geti(genericLoggerp);
  }

#ifndef MARPAESLIF_NTRACE
  if (genericLoggerp != NULL) {
    GENERICLOGGER_TRACEF(genericLoggerp, "[%s] Building ESLIF", funcs);
  }
#endif

  marpaESLIFp = (marpaESLIF_t *) malloc(sizeof(marpaESLIF_t));
  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    if (genericLoggerp != NULL) {
      GENERICLOGGER_ERRORF(genericLoggerp, "malloc failure, %s", strerror(errno));
    }
    goto err;
  }

  marpaESLIFp->marpaESLIFGrammarLuap     = NULL;
  marpaESLIFp->marpaESLIFGrammarLuapp[0] = NULL;
  marpaESLIFp->marpaESLIFGrammarLuapp[1] = NULL;
  marpaESLIFp->marpaESLIFOption          = *marpaESLIFOptionp;
  marpaESLIFp->marpaESLIFGrammarp        = NULL;
  marpaESLIFp->anycharp                  = NULL;
  marpaESLIFp->newlinep                  = NULL;
  marpaESLIFp->newlineSymbolp            = NULL;
  marpaESLIFp->stringModifiersp          = NULL;
  marpaESLIFp->substitutionModifiersp    = NULL;
  marpaESLIFp->characterClassModifiersp  = NULL;
  marpaESLIFp->regexModifiersp           = NULL;
  marpaESLIFp->traceLoggerp              = NULL;
  marpaESLIFp->NULLisZeroBytesb          = 0;
  marpaESLIFp->ZeroIntegerisZeroBytesb   = 0;
  marpaESLIFp->versions                  = (char *) MARPAESLIF_VERSION_STATIC;
  marpaESLIFp->versionMajori             = (int) MARPAESLIF_VERSION_MAJOR_STATIC;
  marpaESLIFp->versionMinori             = (int) MARPAESLIF_VERSION_MINOR_STATIC;
  marpaESLIFp->versionPatchi             = (int) MARPAESLIF_VERSION_PATCH_STATIC;
  marpaESLIFp->marpaESLIFValueResultTrue.contextp         = NULL;
  marpaESLIFp->marpaESLIFValueResultTrue.representationp  = NULL;
  marpaESLIFp->marpaESLIFValueResultTrue.type             = MARPAESLIF_VALUE_TYPE_BOOL;
  marpaESLIFp->marpaESLIFValueResultTrue.u.y              = MARPAESLIFVALUERESULTBOOL_TRUE;

  marpaESLIFp->marpaESLIFValueResultFalse.contextp        = NULL;
  marpaESLIFp->marpaESLIFValueResultFalse.representationp = NULL;
  marpaESLIFp->marpaESLIFValueResultFalse.type            = MARPAESLIF_VALUE_TYPE_BOOL;
  marpaESLIFp->marpaESLIFValueResultFalse.u.y             = MARPAESLIFVALUERESULTBOOL_FALSE;

#ifdef HAVE_LOCALE_H
  marpaESLIFp->lconvp                                     = localeconv(); /* Always succeed as per the doc */
  marpaESLIFp->decimalPointc                              = ((marpaESLIFp->lconvp != NULL) && (marpaESLIFp->lconvp->decimal_point != NULL) && (*(marpaESLIFp->lconvp->decimal_point) != '\0')) ? *(marpaESLIFp->lconvp->decimal_point) : '.';
#else
  marpaESLIFp->decimalPointc                              = '.';
#endif

  marpaESLIFp->tablesp = NULL;

#ifdef MARPAESLIF_HAVE_LONG_LONG
  marpaESLIFp->llongmincharsl                             = 0; /* Number of digits of LLONG_MIN */
  marpaESLIFp->llongmaxcharsl                             = 0; /* Number of digits of LLONG_MAX */
#else
  marpaESLIFp->longmincharsl                              = 0; /* Number of digits of LONG_MIN */
  marpaESLIFp->longmaxcharsl                              = 0; /* Number of digits of LONG_MAX */
#endif
#ifdef MARPAESLIF_INFINITY
  marpaESLIFp->positiveinfinityf                          = MARPAESLIF_INFINITY;           /* +Inf */
  marpaESLIFp->negativeinfinityf                          = -MARPAESLIF_INFINITY;          /* -Inf */
#endif
#ifdef MARPAESLIF_NAN
  /* NaN is much more problematic than Inf: Inf is a truely signed thing, every math library */
  /* have to honour its sign. But NaN sign depends. On some system (0.0 / 0.0) for example   */
  /* will produce -NaN.                                                                      */
  /* Note that C_SIGNBIT is always defined, c.f. at the top of this file for the worst case. */
  if ((C_SIGNBIT(nanf) == 0) && (C_SIGNBIT(-nanf) != 0)) {
    marpaESLIFp->positivenanf                             = nanf;
    marpaESLIFp->negativenanf                             = -nanf;
    marpaESLIFp->nanconfidenceb                           = 1;
  } else if ((C_SIGNBIT(-nanf) == 0) && (C_SIGNBIT(+nanf) != 0)) {
    marpaESLIFp->positivenanf                             = -nanf;
    marpaESLIFp->negativenanf                             = nanf;
    marpaESLIFp->nanconfidenceb                           = 1;
  } else {
    /* I believe this case should never happen, but who knows */
    _marpaESLIF_guessNanv(marpaESLIFp);
  }
#endif /* MARPAESLIF_NAN */

#ifdef MARPAESLIF_HAVE_LONG_LONG
  sprintf(tmps, MARPAESLIF_LONG_LONG_FMT, MARPAESLIF_LLONG_MIN);
  marpaESLIFp->llongmincharsl = strlen(tmps);

  sprintf(tmps, MARPAESLIF_LONG_LONG_FMT, MARPAESLIF_LLONG_MAX);
  marpaESLIFp->llongmaxcharsl = strlen(tmps);
#else
  sprintf(tmps, MARPAESLIF_LONG_LONG_FMT, "%ld", LONG_MIN);
  marpaESLIFp->longmincharsl = strlen(tmps);

  sprintf(tmps, MARPAESLIF_LONG_LONG_FMT, "%ld", LONG_MAX);
  marpaESLIFp->longmaxcharsl = strlen(tmps);
#endif

  for (i = 0; i < _MARPAESLIF_JSON_TYPE_LAST; i++) {
    marpaESLIFp->jsonStringpp[i] = NULL;
    marpaESLIFp->jsonConstantOrNumberpp[i] = NULL;
  }

  marpaESLIFp->Lshare.L                                 = NULL;
  marpaESLIFp->Lshare.marpaESLIFRecognizerUnsharedTopp  = NULL;
  marpaESLIFp->Lshare.marpaESLIFRecognizerLastInjectedp = NULL;
  marpaESLIFp->Lshare.marpaESLIFValueLastInjectedp      = NULL;

  marpaESLIFp->tablesp = pcre2_maketables(NULL);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->tablesp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "pcre2_maketables failure, %s", strerror(errno));
    goto err;
  }

  /* Check if zero bytes (.i.e calloc'ed memory) is the same thing as NULL */
  p = calloc(1, sizeof(void *));
  if (MARPAESLIF_UNLIKELY(p == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "calloc failure, %s", strerror(errno));
    goto err;
  }

  marpaESLIFp->NULLisZeroBytesb = (memcmp(p, &NULLp, sizeof(void *)) == 0);
  free(p);
  p = NULL;

  /* Check if zero bytes (.i.e calloc'ed memory) is the same thing as zero integer */
  p = calloc(1, sizeof(int));
  if (MARPAESLIF_UNLIKELY(p == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "calloc failure, %s", strerror(errno));
    goto err;
  }

  marpaESLIFp->ZeroIntegerisZeroBytesb = (memcmp(p, &zeroInteger, sizeof(int)) == 0);
  free(p);
  p = NULL;

  /* **************************************************************** */
  /* It is very important to NOT create terminals of type STRING here */
  /* **************************************************************** */
  
  /* Create internal anychar regex */
  marpaESLIFp->anycharp = _marpaESLIF_terminal_newp(marpaESLIFp,
                                                    NULL, /* marpaWrapperGrammarStartp */
                                                    MARPAESLIF_EVENTTYPE_NONE, /* eventSeti */
                                                    "ASCII", /* We KNOW this is an ASCII thingy */
                                                    INTERNAL_ANYCHAR_PATTERN, /* descs */
                                                    strlen(INTERNAL_ANYCHAR_PATTERN), /* descl */
                                                    MARPAESLIF_TERMINAL_TYPE_REGEX, /* type */
                                                    "su", /* modifiers */
                                                    INTERNAL_ANYCHAR_PATTERN, /* utf8s */
                                                    strlen(INTERNAL_ANYCHAR_PATTERN), /* utf8l */
                                                    NULL, /* testFullMatchs */
                                                    NULL,  /* testPartialMatchs */
                                                    0, /* pseudob */
                                                    0, /* characterClassb */
                                                    MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                                    0 /* substitutionb */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->anycharp == NULL)) {
    goto err;
  }

  /* Create internal newline regex */
  /* Please note that the newline regexp does NOT require UTF-8 correctness -; */
  marpaESLIFp->newlinep = _marpaESLIF_terminal_newp(marpaESLIFp,
                                                    NULL /* marpaWrapperGrammarStartp */,
                                                    MARPAESLIF_EVENTTYPE_NONE, /* eventSeti */
                                                    "ASCII", /* We KNOW this is an ASCII thingy */
                                                    INTERNAL_NEWLINE_PATTERN /* descs */,
                                                    strlen(INTERNAL_NEWLINE_PATTERN) /* descl */,
                                                    MARPAESLIF_TERMINAL_TYPE_REGEX, /* type */
                                                    NULL, /* modifiers */
                                                    INTERNAL_NEWLINE_PATTERN, /* utf8s */
                                                    strlen(INTERNAL_NEWLINE_PATTERN), /* utf8l */
                                                    NULL, /* testFullMatchs */
                                                    NULL,  /* testPartialMatchs */
                                                    0, /* pseudob */
                                                    0, /* characterClassb */
                                                    MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                                    0 /* substitutionb */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->newlinep == NULL)) {
    goto err;
  }

  /* Create the external symbol that corresponds to newlinep */
  newlineString.bytep          = (char *) INTERNAL_NEWLINE_PATTERN;
  newlineString.bytel          = strlen(INTERNAL_NEWLINE_PATTERN);
  newlineString.encodingasciis = (char *) MARPAESLIF_UTF8_STRING;
  newlineString.asciis         = (char *) INTERNAL_NEWLINE_PATTERN;
  marpaESLIFp->newlineSymbolp = _marpaESLIFSymbol_terminal_newp(marpaESLIFp,
                                                                MARPAESLIF_TERMINAL_TYPE_REGEX,
                                                                &newlineString,
                                                                NULL, /* modifiers */
                                                                NULL, /* substitutionStringp */
                                                                NULL, /* substitutionModifiers */
                                                                NULL /* marpaESLIFSymbolOptionp */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->newlineSymbolp == NULL)) {
    goto err;
  }

  /* Create internal anychar regex */
  marpaESLIFp->stringModifiersp = _marpaESLIF_terminal_newp(marpaESLIFp,
                                                            NULL, /* marpaWrapperGrammarStartp */
                                                            MARPAESLIF_EVENTTYPE_NONE, /* eventSeti */
                                                            "ASCII", /* We KNOW this is an ASCII thingy */
                                                            INTERNAL_STRINGMODIFIERS_PATTERN, /* descs */
                                                            strlen(INTERNAL_STRINGMODIFIERS_PATTERN), /* descl */
                                                            MARPAESLIF_TERMINAL_TYPE_REGEX, /* type */
                                                            "Au", /* modifiers */
                                                            INTERNAL_STRINGMODIFIERS_PATTERN, /* utf8s */
                                                            strlen(INTERNAL_STRINGMODIFIERS_PATTERN), /* utf8l */
                                                            NULL, /* testFullMatchs */
                                                            NULL,  /* testPartialMatchs */
                                                            0, /* pseudob */
                                                            0, /* characterClassb */
                                                            MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                                            0 /* substitutionb */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->stringModifiersp == NULL)) {
    goto err;
  }

  /* Create internal substitution regex */
  marpaESLIFp->substitutionModifiersp = _marpaESLIF_terminal_newp(marpaESLIFp,
                                                                  NULL, /* marpaWrapperGrammarStartp */
                                                                  MARPAESLIF_EVENTTYPE_NONE, /* eventSeti */
                                                                  "ASCII", /* We KNOW this is an ASCII thingy */
                                                                  INTERNAL_SUBSTITUTIONMODIFIERS_PATTERN, /* descs */
                                                                  strlen(INTERNAL_SUBSTITUTIONMODIFIERS_PATTERN), /* descl */
                                                                  MARPAESLIF_TERMINAL_TYPE_REGEX, /* type */
                                                                  "Au", /* modifiers */
                                                                  INTERNAL_SUBSTITUTIONMODIFIERS_PATTERN, /* utf8s */
                                                                  strlen(INTERNAL_SUBSTITUTIONMODIFIERS_PATTERN), /* utf8l */
                                                                  NULL, /* testFullMatchs */
                                                                  NULL,  /* testPartialMatchs */
                                                                  0, /* pseudob */
                                                                  0, /* characterClassb */
                                                                  MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                                                  0 /* substitutionb */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->substitutionModifiersp == NULL)) {
    goto err;
  }

  /* Create internal anychar regex */
  marpaESLIFp->characterClassModifiersp = _marpaESLIF_terminal_newp(marpaESLIFp,
                                                                    NULL, /* marpaWrapperGrammarStartp */
                                                                    MARPAESLIF_EVENTTYPE_NONE, /* eventSeti */
                                                                    "ASCII", /* We KNOW this is an ASCII thingy */
                                                                    INTERNAL_CHARACTERCLASSMODIFIERS_PATTERN, /* descs */
                                                                    strlen(INTERNAL_CHARACTERCLASSMODIFIERS_PATTERN), /* descl */
                                                                    MARPAESLIF_TERMINAL_TYPE_REGEX, /* type */
                                                                    "Au", /* modifiers */
                                                                    INTERNAL_CHARACTERCLASSMODIFIERS_PATTERN, /* utf8s */
                                                                    strlen(INTERNAL_CHARACTERCLASSMODIFIERS_PATTERN), /* utf8l */
                                                                    NULL, /* testFullMatchs */
                                                                    NULL,  /* testPartialMatchs */
                                                                    0, /* pseudob */
                                                                    0, /* characterClassb */
                                                                    MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                                                    0 /* substitutionb */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->characterClassModifiersp == NULL)) {
    goto err;
  }

  /* Create internal anychar regex */
  marpaESLIFp->regexModifiersp = _marpaESLIF_terminal_newp(marpaESLIFp,
                                                           NULL, /* marpaWrapperGrammarStartp */
                                                           MARPAESLIF_EVENTTYPE_NONE, /* eventSeti */
                                                           "ASCII", /* We KNOW this is an ASCII thingy */
                                                           INTERNAL_REGEXMODIFIERS_PATTERN, /* descs */
                                                           strlen(INTERNAL_REGEXMODIFIERS_PATTERN), /* descl */
                                                           MARPAESLIF_TERMINAL_TYPE_REGEX, /* type */
                                                           "Au", /* modifiers */
                                                           INTERNAL_REGEXMODIFIERS_PATTERN, /* utf8s */
                                                           strlen(INTERNAL_REGEXMODIFIERS_PATTERN), /* utf8l */
                                                           NULL, /* testFullMatchs */
                                                           NULL,  /* testPartialMatchs */
                                                           0, /* pseudob */
                                                           0, /* characterClassb */
                                                           MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                                           0 /* substitutionb */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->regexModifiersp == NULL)) {
    goto err;
  }

  marpaESLIFp->traceLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIF_traceLoggerCallbackv, (void *) marpaESLIFp, GENERICLOGGER_LOGLEVEL_TRACE);
  /* Although this should never happen, it is okay if the trace logger is NULL */
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->traceLoggerp == NULL)) {
    GENERICLOGGER_TRACEF(marpaESLIFOptionp->genericLoggerp, "genericLogger initialization failure, %s", strerror(errno));
  }

  /* From now on we can use MARPAESLIF_ERROR and al. */
  marpaESLIFp->Lshare.L = _marpaESLIF_lua_newp(marpaESLIFp);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->Lshare.L == NULL)) {
    goto err;
  }
  
  /* Create internal JSON symbols */
  jsonString.encodingasciis = "ASCII";
  jsonString.asciis         = NULL;
  for (i = 0; i < _MARPAESLIF_JSON_TYPE_LAST; i++) {
    jsonString.bytep = (char *) jsonStringRegexsp[i];
    jsonString.bytel = strlen(jsonStringRegexsp[i]);
    marpaESLIFp->jsonStringpp[i] = _marpaESLIFSymbol_regex_newp(marpaESLIFp,
                                                                &jsonString,
                                                                (char *) jsonStringRegexModifiersp[i],
                                                                NULL, /* substitutionStringp */
                                                                NULL, /* substitutionModifiers */
                                                                NULL /* marpaESLIFSymbolOptionp */);
    if (MARPAESLIF_UNLIKELY(marpaESLIFp->jsonStringpp[i] == NULL)) {
      goto err;
    }

    jsonString.bytep = (char *) jsonConstantOrNumberRegexsp[i];
    jsonString.bytel = strlen(jsonConstantOrNumberRegexsp[i]);
    marpaESLIFp->jsonConstantOrNumberpp[i] = _marpaESLIFSymbol_regex_newp(marpaESLIFp,
                                                                          &jsonString,
                                                                          (char *) jsonConstantOrNumberRegexModifiersp[i],
                                                                          NULL, /* substitutionStringp */
                                                                          NULL, /* substitutionModifiers */
                                                                          NULL /* marpaESLIFSymbolOptionp */);
    if (MARPAESLIF_UNLIKELY(marpaESLIFp->jsonConstantOrNumberpp[i] == NULL)) {
      goto err;
    }
  }

  /* Create internal ESLIF grammar - it is important to set the option first */
  marpaESLIFp->marpaESLIFGrammarp = _marpaESLIFGrammar_newp(marpaESLIFp, &marpaESLIFGrammarOption_default_template, &(marpaESLIFp->Lshare), 1 /* bootstrapb */, 0 /* rememberGrammarUtf8b */, NULL /* forcedStartSymbols */, -1 /* forcedStartSymbolLeveli */, NULL /* marpaESLIFGrammar_bootstrapp */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->marpaESLIFGrammarp == NULL)) {
    goto err;
  }

  marpaESLIFp->marpaESLIFGrammarp->grammarStackp = &(marpaESLIFp->marpaESLIFGrammarp->_grammarStack);
  GENERICSTACK_INIT(marpaESLIFp->marpaESLIFGrammarp->grammarStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFp->marpaESLIFGrammarp->grammarStackp initialization failure, %s", strerror(errno));
    marpaESLIFp->marpaESLIFGrammarp->grammarStackp = NULL;
    goto err;
  }

  GENERICSTACK_INIT(marpaESLIFp->marpaESLIFGrammarp->grammarStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFp->marpaESLIFGrammarp->grammarStackp initialization failure, %s", strerror(errno));
    marpaESLIFp->marpaESLIFGrammarp->grammarStackp = NULL;
    goto err;
  }

#ifdef MARPAESLIF_NTRACE
  /* When we bootstrap we do no want to log unless there is an error */
  if (marpaESLIFOptionp->genericLoggerp != NULL) {
    genericLogger_logLevel_seti(marpaESLIFOptionp->genericLoggerp, GENERICLOGGER_LOGLEVEL_INFO);
  }
#endif
  
  /* ----------------------------------- */
  /* First without the lazy rules        */
  /* ----------------------------------- */

  /* G1 */
  grammarp = _marpaESLIF_bootstrap_grammar_G1p(marpaESLIFp->marpaESLIFGrammarp, 0 /* withLazyb */);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    goto err;
  }
  GENERICSTACK_SET_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, grammarp, grammarp->leveli);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFp->marpaESLIFGrammarp->grammarStackp set failure, %s", strerror(errno));
    goto err;
  }
  grammarp = NULL;

  /* L0 */
  grammarp = _marpaESLIF_bootstrap_grammar_L0p(marpaESLIFp->marpaESLIFGrammarp, 0 /* withLazyb */);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    goto err;
  }
  GENERICSTACK_SET_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, grammarp, grammarp->leveli);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFp->marpaESLIFGrammarp->grammarStackp set failure, %s", strerror(errno));
    goto err;
  }
  grammarp = NULL;

  /* Validate the bootstrap grammar - this will precompute it: it can never be modified */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFGrammar_validateb(marpaESLIFp->marpaESLIFGrammarp, 1 /* ignoreLazyb */, NULL /* forcedStartSymbols */, -1 /* forcedStartSymbolLeveli */))) {
    goto err;
  }

  /* Check there is a top-level grammar */
#ifndef MARPAESLIF_NTRACE
  /* Should never happen */
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, 0))) {
    GENERICLOGGER_ERROR(marpaESLIFOptionp->genericLoggerp, "No top level grammar after bootstrap");
    goto err;
  }
#endif
  marpaESLIFp->marpaESLIFGrammarp->grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, 0);

#ifndef MARPAESLIF_NTRACE
  GENERICLOGGER_TRACE(marpaESLIFp->marpaESLIFOption.genericLoggerp, "=====================");
  GENERICLOGGER_TRACE(marpaESLIFp->marpaESLIFOption.genericLoggerp, "ESLIF phase 1 follows");
  GENERICLOGGER_TRACE(marpaESLIFp->marpaESLIFOption.genericLoggerp, "=====================");
  _marpaESLIF_dump(marpaESLIFp);
#endif

  /* ----------------------------------------------------- */
  /* Prepare lazy stuff by first compiling the lua grammar */
  /* ----------------------------------------------------- */

  /* marpaESLIFp is complete usable now: get the lua grammar and do a quite terrible hook by  */
  /* moving lua grammar into ESLIF, and revisit the lazy lexeme resolving.                    */
  /* We doing so ? This is because ESLIF by itself is minimal, and rewriting the whole Lua    */
  /* grammar by hand using the bootstrap mechanism is very prone to error. By doing such hack */
  /* it is more maintanable, modulo the hook below, and makes easier to extends ESLIF.        */
  marpaESLIFp->marpaESLIFGrammarLuap = _marpaESLIF_lua_grammarp(marpaESLIFp, NULL);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->marpaESLIFGrammarLuap == NULL)) {
    goto err;
  }
  if (! _marpaESLIF_transfer_grammarb(marpaESLIFp, marpaESLIFp->marpaESLIFGrammarp, 2, marpaESLIFp->marpaESLIFGrammarLuap, 2)) {
    goto err;
  }
  if (! _marpaESLIF_transfer_grammarb(marpaESLIFp, marpaESLIFp->marpaESLIFGrammarp, 3, marpaESLIFp->marpaESLIFGrammarLuap, 3)) {
    goto err;
  }

  /* Prepare stuff for bootstrap: it needs to know the number of arguments and parameters for */
  /* parameterized symbols.                                                                   */
  marpaESLIFp->marpaESLIFGrammarLuapp[MARPAESLIFGRAMMARLUA_FOR_PARLIST] = _marpaESLIF_lua_grammarp(marpaESLIFp, G1_META_LUA_OPTIONAL_PARLIST_AFTER_LPAREN_DESC);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->marpaESLIFGrammarLuapp[MARPAESLIFGRAMMARLUA_FOR_PARLIST] == NULL)) {
    goto err;
  }
  marpaESLIFp->marpaESLIFGrammarLuapp[MARPAESLIFGRAMMARLUA_FOR_EXPLIST] = _marpaESLIF_lua_grammarp(marpaESLIFp, G1_META_LUA_ARGS_AFTER_LPAREN_DESC);
  if (MARPAESLIF_UNLIKELY(marpaESLIFp->marpaESLIFGrammarLuapp[MARPAESLIFGRAMMARLUA_FOR_EXPLIST] == NULL)) {
    goto err;
  }

  /* --------------------------------- */
  /* Second with the lazy rules        */
  /* --------------------------------- */

  /* G1 */
  grammar2p = _marpaESLIF_bootstrap_grammar_G1p(marpaESLIFp->marpaESLIFGrammarp, 1 /* withLazyb */);
  if (MARPAESLIF_UNLIKELY(grammar2p == NULL)) {
    goto err;
  }

  grammarp = GENERICSTACK_GET_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, grammar2p->leveli);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFp->marpaESLIFGrammarp->grammarStackp get failure, %s", strerror(errno));
    goto err;
  }
  GENERICSTACK_SET_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, grammar2p, grammar2p->leveli);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFp->marpaESLIFGrammarp->grammarStackp set failure, %s", strerror(errno));
    goto err;
  }
  grammar2p = NULL;
  _marpaESLIF_grammar_freev(grammarp);
  grammarp = NULL;

  /* L0 */
  grammar2p = _marpaESLIF_bootstrap_grammar_L0p(marpaESLIFp->marpaESLIFGrammarp, 1 /* withLazyb */);
  if (MARPAESLIF_UNLIKELY(grammar2p == NULL)) {
    goto err;
  }

  grammarp = GENERICSTACK_GET_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, grammar2p->leveli);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFp->marpaESLIFGrammarp->grammarStackp get failure, %s", strerror(errno));
    goto err;
  }
  GENERICSTACK_SET_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, grammar2p, grammar2p->leveli);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFp->marpaESLIFGrammarp->grammarStackp set failure, %s", strerror(errno));
    goto err;
  }
  grammar2p = NULL;
  _marpaESLIF_grammar_freev(grammarp);
  grammarp = NULL;

  /* Validate again the bootstrap grammar */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFGrammar_validateb(marpaESLIFp->marpaESLIFGrammarp, 0 /* ignoreLazyb */, NULL /* forcedStartSymbols */, -1 /* forcedStartSymbolLeveli */))) {
    goto err;
  }

  /* Check there is a top-level grammar */
#ifndef MARPAESLIF_NTRACE
  /* Should never happen */
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, 0))) {
    GENERICLOGGER_ERROR(marpaESLIFOptionp->genericLoggerp, "No top level grammar after bootstrap");
    goto err;
  }
#endif
  marpaESLIFp->marpaESLIFGrammarp->grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(marpaESLIFp->marpaESLIFGrammarp->grammarStackp, 0);

  
#ifndef MARPAESLIF_NTRACE
  GENERICLOGGER_TRACE(marpaESLIFp->marpaESLIFOption.genericLoggerp, "=====================");
  GENERICLOGGER_TRACE(marpaESLIFp->marpaESLIFOption.genericLoggerp, "ESLIF phase 2 follows");
  GENERICLOGGER_TRACE(marpaESLIFp->marpaESLIFOption.genericLoggerp, "=====================");
  _marpaESLIF_dump(marpaESLIFp);
#endif

  goto done;
  
 err:
  marpaESLIF_freev(marpaESLIFp);
  marpaESLIFp = NULL;

 done:
  /* Restore log-level if user provided one */
  if (marpaESLIFOptionp->genericLoggerp != NULL) {
    genericLogger_logLevel_seti(marpaESLIFOptionp->genericLoggerp, genericLoggerLeveli);
  }
  
  _marpaESLIF_grammar_freev(grammarp);
#ifndef MARPAESLIF_NTRACE
  if ((marpaESLIFp != NULL) && (genericLoggerp != NULL)) {
    int     ngrammari;
    int    *ruleip;
    size_t  rulel;
    int     leveli;
    size_t  l;

    if (marpaESLIFGrammar_ngrammarib(marpaESLIFp->marpaESLIFGrammarp, &ngrammari)) {
      for (leveli = 0; leveli < ngrammari; leveli++) {
        if (marpaESLIFGrammar_rulearray_by_levelb(marpaESLIFp->marpaESLIFGrammarp, &ruleip, &rulel, leveli, NULL /* descp */)) {
          GENERICLOGGER_TRACEF(genericLoggerp, "[%s] -------------------------", funcs);
          GENERICLOGGER_TRACEF(genericLoggerp, "[%s] ESLIF grammar at level %d:", funcs, leveli);
          GENERICLOGGER_TRACEF(genericLoggerp, "[%s] -------------------------", funcs);
          for (l = 0; l < rulel; l++) {
            char *ruleshows;
            if (marpaESLIFGrammar_ruleshowform_by_levelb(marpaESLIFp->marpaESLIFGrammarp, l, &ruleshows, leveli, NULL /* descp */)) {
              GENERICLOGGER_TRACEF(genericLoggerp, "[%s] %s", funcs, ruleshows);
            }
          }
        }
      }
    }

    GENERICLOGGER_TRACEF(genericLoggerp, "[%s] return %p", funcs, marpaESLIFp);
  }
#endif
	
  return marpaESLIFp;
}

/*****************************************************************************/
marpaESLIFOption_t *marpaESLIF_optionp(marpaESLIF_t *marpaESLIFp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIF_optionp";

  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    return NULL;
  }

  return &(marpaESLIFp->marpaESLIFOption);
}

/*****************************************************************************/
void marpaESLIF_freev(marpaESLIF_t *marpaESLIFp)
/*****************************************************************************/
{
  int i;

  if (marpaESLIFp != NULL) {
    _marpaESLIFGrammar_freev(marpaESLIFp->marpaESLIFGrammarLuap, 0 /* onStackb */);
    _marpaESLIFGrammar_freev(marpaESLIFp->marpaESLIFGrammarLuapp[0], 0 /* onStackb */);
    _marpaESLIFGrammar_freev(marpaESLIFp->marpaESLIFGrammarLuapp[1], 0 /* onStackb */);
    _marpaESLIFGrammar_freev(marpaESLIFp->marpaESLIFGrammarp, 0 /* onStackb */);
    _marpaESLIF_terminal_freev(marpaESLIFp->anycharp);
    _marpaESLIF_terminal_freev(marpaESLIFp->newlinep);
    _marpaESLIF_symbol_freev(marpaESLIFp->newlineSymbolp);
    _marpaESLIF_terminal_freev(marpaESLIFp->stringModifiersp);
    _marpaESLIF_terminal_freev(marpaESLIFp->substitutionModifiersp);
    _marpaESLIF_terminal_freev(marpaESLIFp->characterClassModifiersp);
    _marpaESLIF_terminal_freev(marpaESLIFp->regexModifiersp);
    if (marpaESLIFp->traceLoggerp != NULL) {
      genericLogger_freev(&(marpaESLIFp->traceLoggerp));
    }
    if (marpaESLIFp->tablesp != NULL) {
      /* Well, our built-in do not export pcre2_maketables_free */
#ifdef pcre2_maketables_free
      pcre2_maketables_free(NULL, marpaESLIFp->tablesp);
#else
      free((void *) marpaESLIFp->tablesp);
#endif
    }
    for (i = 0; i < _MARPAESLIF_JSON_TYPE_LAST; i++) {
      _marpaESLIF_symbol_freev(marpaESLIFp->jsonStringpp[i]); /* This is NULL protected */
      _marpaESLIF_symbol_freev(marpaESLIFp->jsonConstantOrNumberpp[i]); /* This is NULL protected */
    }
    _marpaESLIF_lua_freev(marpaESLIFp);
    /* free(marpaESLIFp->lconvp); */ /* output of localeconv() should never be freed */
    free(marpaESLIFp);
  }
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_stream_t *marpaESLIF_streamp, marpaESLIF_terminal_t *terminalp, char *inputs, size_t inputl, short eofb, marpaESLIF_matcher_value_t *rcip, marpaESLIFValueResult_t *marpaESLIFValueResultp, size_t *matchedLengthlp)
/*****************************************************************************/
/* This method is call extremely often, we want to minimize at much as       */
/* possible the instructions in it:                                          */
/* - rcip            must be != NULL                                         */
/* - matchedLengthlp must be != NULL                                         */
/*****************************************************************************/
{
  static const char                 *funcs          = "_marpaESLIFRecognizer_terminal_matcherb";
  short                              allocb         = 0;
  size_t                             matchedLengthl = 0;
  char                              *matchedp       = NULL;
  PCRE2_UCHAR                       *outputbufferp  = NULL;
  PCRE2_SIZE                         outputbufferl  = 0;
  short                              substitutionb  = 0;
  PCRE2_UCHAR                       *outputbuffertmpp;
  marpaESLIF_matcher_value_t         rci;
  marpaESLIF_regex_t                *marpaESLIF_regexp;
  int                                pcre2Errornumberi;
  PCRE2_UCHAR                        pcre2ErrorBuffer[256];
  PCRE2_SIZE                        *pcre2_ovectorp;
  marpaESLIF_uint32_t                pcre2_optioni;
  marpaESLIF_uint32_t                pcre2_substitute_optioni;
  short                              binmodeb;
  short                              needUtf8Validationb;
  short                              rcb;
  short                              rcMatcherb;
  marpaESLIFValueResult_t            marpaESLIFValueResultArray;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /*********************************************************************************/
  /* A matcher tries to match a terminal v.s. input that is eventually incomplete. */
  /* It return 1 on success, 0 on failure, -1 if more data is needed in rcip       */
  /* The method return value itself is 0 on error, 1 on success, -1 on fatal error */
  /*********************************************************************************/

  /* Most common cases first */

  /* It it very rare that there is no byte in input */
  if (MARPAESLIF_LIKELY(inputl > 0)) {

    if (terminalp->memcmpb && ((! terminalp->regex.utfb) /* No need for character validation : binary test */
                               ||
                               marpaESLIF_streamp->utfb /* Characters validated */)) {
      /* -------------------------------------------------------------------------------------------------------------------------------------------- */
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Doing memcmp on %ld bytes, inputl=%ld", (unsigned long) terminalp->bytel, (unsigned long) inputl);
      /* -------------------------------------------------------------------------------------------------------------------------------------------- */

      if (terminalp->bytel > 0) {
        /* No need to call memcmp() if the first byte is not the same - appears to (always ?) be faster */
        if (inputs[0] == terminalp->bytes[0]) {
          if (inputl >= terminalp->bytel) {
            /* No need to call memcmp() if the length to check if == 1 */
            if ((terminalp->bytel == 1) || (memcmp(inputs, terminalp->bytes, terminalp->bytel) == 0)) {
              rci = MARPAESLIF_MATCH_OK;
              matchedp       = inputs;
              matchedLengthl = terminalp->bytel;
	      /* Need to alloc when eof is reached */
	      if (! eofb) {
                allocb = 1;
              }
            } else {
              rci = MARPAESLIF_MATCH_FAILURE;
            }
          } else {
            /* No need to call memcmp() if the length to check if == 1 */
            if ((inputl == 1) || (memcmp(inputs, terminalp->bytes, inputl) == 0)) {
              /* Partial match */
              if (eofb) {
                rci = MARPAESLIF_MATCH_FAILURE;
              } else {
                rci = MARPAESLIF_MATCH_AGAIN;
              }
            } else {
              rci = MARPAESLIF_MATCH_FAILURE;
            }
          }
        } else {
          rci = MARPAESLIF_MATCH_FAILURE;
        }
      } else {
        /* Empty string is allowed and never matches */
        rci = MARPAESLIF_MATCH_FAILURE;
      }

      /* We are done in any case */
      goto fast_done;

    } else if (! terminalp->pseudob) {
      /* -------------------------------------------------------------------------------------------------------------------------------------------- */
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Doing regex, inputl=%ld", (unsigned long) inputl);
      /* -------------------------------------------------------------------------------------------------------------------------------------------- */

      marpaESLIF_regexp = &(terminalp->regex);

      /* If the regexp is working in UTF mode then we check that character conversion   */
      /* was done. This is how we are sure that calling regexp with PCRE2_NO_UTF_CHECK  */
      /* is ok: we have done ourself the UTF-8 validation on the subject.               */

      if (marpaESLIF_regexp->utfb) {                   /* UTF-8 correctness is required */
        if (marpaESLIF_streamp->utfb) {
          pcre2_optioni = PCRE2_NOTEMPTY|PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK; /* We made sure this is ok */
          binmodeb = 0;
          needUtf8Validationb = 0;
        } else {
          pcre2_optioni = PCRE2_NOTEMPTY|PCRE2_NOTEMPTY_ATSTART;                    /* PCRE2 will do the check */
          binmodeb = 1;
          needUtf8Validationb = 1;
        }
      } else {
        pcre2_optioni = PCRE2_NOTEMPTY|PCRE2_NOTEMPTY_ATSTART|PCRE2_NO_UTF_CHECK;   /* No check needed         */
        binmodeb = 1;
        needUtf8Validationb = 0;
      }

      pcre2_substitute_optioni = pcre2_optioni;

      if (! eofb) {
        pcre2_optioni |= PCRE2_PARTIAL_HARD;                 /* Partial has precedence  */
      }

      /* --------------------------------------------------------- */
      /* Anchored regex...                                         */
      /* --------------------------------------------------------- */
      /*
        Patterns are always compiled with PCRE2_ANCHORED by default,
        except when there is the "A" modifier. In this case, we allow
        to execute the regex ONLY if the whole stream was read in one
        call to the user's read callback.
      */
      if ((! marpaESLIF_regexp->isAnchoredb) && (! marpaESLIF_streamp->noAnchorIsOkb)) {
        /* This is an error unless we are at EOF */
        if (MARPAESLIF_UNLIKELY(! eofb)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: You used the \"A\" modifier to set the pattern non-anchored, but then you must read the whole input in one go, and you have not reached EOF yet", terminalp->descp->asciis);
          goto err;
        }
      }

      /* Update callout userdata context - take care this will segfault IF you have callouts in the regexp during bootstrap. */
      marpaESLIF_regexp->callout_context.marpaESLIFRecognizerp = marpaESLIFRecognizerp;

      /* Always try to JIT fast path first */
      if (marpaESLIF_regexp->jitb && (! needUtf8Validationb)) {
        /* JIT fast path is not doing UTF-8 validation */
        pcre2Errornumberi = pcre2_jit_match(marpaESLIF_regexp->patternp,      /* code */
                                            (PCRE2_SPTR) inputs,              /* subject */
                                            (PCRE2_SIZE) inputl,              /* length */
                                            (PCRE2_SIZE) 0,                   /* startoffset */
                                            pcre2_optioni,                    /* options */
                                            marpaESLIF_regexp->match_datap,   /* match data */
                                            marpaESLIF_regexp->match_contextp /* match context */
                                            );
      } else {
        /* Call the matcher */
      match_retry:
        pcre2Errornumberi = pcre2_match(marpaESLIF_regexp->patternp,      /* code */
                                        (PCRE2_SPTR) inputs,              /* subject */
                                        (PCRE2_SIZE) inputl,              /* length */
                                        (PCRE2_SIZE) 0,                   /* startoffset */
                                        pcre2_optioni,                    /* options */
                                        marpaESLIF_regexp->match_datap,   /* match data */
                                        marpaESLIF_regexp->match_contextp /* match context */
                                        );
      }

      /* Success if pcre2Errornumberi is > 0 */
      if (pcre2Errornumberi < 0) {
        /* Only PCRE2_ERROR_NOMATCH and PCRE2_ERROR_PARTIAL are acceptable errors - PCRE2_ERROR_JIT_STACKLIMIT is a special case */

        /* We are in a very hot function and we prefer a predicted if rather than a switch */
        if (MARPAESLIF_LIKELY(pcre2Errornumberi == PCRE2_ERROR_NOMATCH)) {
          rci = MARPAESLIF_MATCH_FAILURE;
        } else if (MARPAESLIF_LIKELY(pcre2Errornumberi == PCRE2_ERROR_PARTIAL)) {
          rci = MARPAESLIF_MATCH_AGAIN;
        } else {
          /* This is always fatal unless JIT stack limit. In this case we retry without JIT. */
#ifdef PCRE2_ERROR_JIT_STACKLIMIT
          if (pcre2Errornumberi == PCRE2_ERROR_JIT_STACKLIMIT) {
            if ((pcre2_optioni & PCRE2_NO_JIT) != PCRE2_NO_JIT) {
              pcre2_optioni &= PCRE2_NO_JIT;
              pcre2_substitute_optioni = pcre2_optioni;
              goto match_retry;
            }
          }
          /* Definitely a fatal error */
          pcre2_get_error_message(pcre2Errornumberi, pcre2ErrorBuffer, sizeof(pcre2ErrorBuffer));
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Uncaught pcre2 match failure: %s", terminalp->descp->asciis, pcre2ErrorBuffer);
          goto fatal;
#endif
        }
      } else {
        /* -------------------------------------------------- */
        /* Regex succeeded or failed with an acceptable error */
        /* -------------------------------------------------- */

        /* Set UTF buffer correctness if needed - this makes a further call to pcre2_match having the option PCRE2_NO_UTF_CHECK */
        if (needUtf8Validationb /* Usually it is false, so it has precedence over testing binmode */ && binmodeb) {
          /* Either regex is successful, either it failed with the accepted failure code PCRE2_ERROR_NOMATCH */
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: UTF-8 correctness successful and remembered", terminalp->descp->asciis);
          marpaESLIF_streamp->utfb = 1;
        }

#ifndef MARPAESLIF_NTRACE
        /* Paranoid test: check the length of matched data */
        if (MARPAESLIF_UNLIKELY(pcre2_get_ovector_count(marpaESLIF_regexp->match_datap) <= 0)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: pcre2_get_ovector_count returned no number of pairs of values", terminalp->descp->asciis);
          goto err;
        }
#endif

        /* Get match length */
        pcre2_ovectorp = pcre2_get_ovector_pointer(marpaESLIF_regexp->match_datap);
#ifndef MARPAESLIF_NTRACE
        /* Paranoid test, we assume that PCRE2 cannot fail at this point */
        if (MARPAESLIF_UNLIKELY(pcre2_ovectorp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: pcre2_get_ovector_pointer returned NULL", terminalp->descp->asciis);
          goto err;
        }
#endif

        matchedLengthl = pcre2_ovectorp[1] - pcre2_ovectorp[0];
#ifndef MARPAESLIF_NTRACE
        /* We said PCRE2_NOTEMPTY so this cannot be empty - test is done only in paranoid mode */
        if (MARPAESLIF_UNLIKELY(matchedLengthl <= 0)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Empty match when it is configured as not possible", terminalp->descp->asciis);
          goto err;
        }
#endif
        matchedp = inputs + pcre2_ovectorp[0];

        if (terminalp->substitutionPatterns != NULL) {
          substitutionb = 1;
          /* The most common case is to  extract part of the match, so we pre-allocate that */
          outputbufferl = matchedLengthl;
          if (outputbufferl > 0) {
            outputbufferp = (PCRE2_UCHAR *) malloc((outputbufferl + 1) * sizeof(PCRE2_UCHAR)); /* + 1 for a NUL byte */
            if (MARPAESLIF_UNLIKELY(outputbufferp == NULL)) {
              MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
              goto err;
            }
            outputbufferp[outputbufferl] = '\0';
          }

	  if (matchedp == inputs) {
	    /* The most common case is anchored regex: then it is ok to reuse preexisting match data */
	    /* It is ok to not say inputl anymore, match data cannot go beyond matchedLengthl */
	    pcre2_substitute_optioni |= PCRE2_SUBSTITUTE_MATCHED;
	  }

	  pcre2Errornumberi = pcre2_substitute(marpaESLIF_regexp->patternp,                               /* code */
					       (PCRE2_SPTR) matchedp,                                     /* subject */
					       (PCRE2_SIZE) matchedLengthl,                               /* length */
					       (PCRE2_SIZE) 0,                                            /* startoffset */
					       pcre2_substitute_optioni|PCRE2_SUBSTITUTE_OVERFLOW_LENGTH, /* options - PCRE2_ERROR_NOMEMORY can happen */
					       marpaESLIF_regexp->match_datap,                            /* match data */
					       marpaESLIF_regexp->match_contextp,                         /* match context */
					       (PCRE2_SPTR) terminalp->substitutionPatterns,              /* replacement */
					       (PCRE2_SIZE) terminalp->substitutionPatternl,              /* rlength */
					       outputbufferp,
					       &outputbufferl);

          /* It if succeed it returns the number of substitutions, that must be > 0 */
          if (pcre2Errornumberi <= 0) {
            /* Only PCRE2_ERROR_NOMEMORY is an acceptable error */
            switch (pcre2Errornumberi) {
            case PCRE2_ERROR_NOMEMORY:
              /* Realloc and retry */
              outputbuffertmpp = (PCRE2_UCHAR *) realloc(outputbufferp, (outputbufferl + 1) * sizeof(PCRE2_UCHAR)); /* + 1 for a NUL byte */
              if (MARPAESLIF_UNLIKELY(outputbuffertmpp == NULL)) {
                MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "realloc failure, %s", strerror(errno));
                goto err;
              }
              outputbufferp = outputbuffertmpp;
              outputbufferp[outputbufferl] = '\0';
              pcre2Errornumberi = pcre2_substitute(marpaESLIF_regexp->patternp,                               /* code */
                                                   (PCRE2_SPTR) matchedp,                                     /* subject */
                                                   (PCRE2_SIZE) matchedLengthl,                               /* length */
                                                   (PCRE2_SIZE) 0,                                            /* startoffset */
                                                   pcre2_substitute_optioni,                                  /* options */
                                                   marpaESLIF_regexp->match_datap,                            /* match data */
                                                   marpaESLIF_regexp->match_contextp,                         /* match context */
                                                   (PCRE2_SPTR) terminalp->substitutionPatterns,              /* replacement */
                                                   (PCRE2_SIZE) terminalp->substitutionPatternl,              /* rlength */
                                                   outputbufferp,
                                                   &outputbufferl);

              /* Now it must succeed with the number of substitutions, that must be > 0 */
              if (pcre2Errornumberi == 0) {
                MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: No substitution though there was a match", terminalp->descp->asciis);
                goto fatal;
              }
              if (pcre2Errornumberi < 0) {
                pcre2_get_error_message(pcre2Errornumberi, pcre2ErrorBuffer, sizeof(pcre2ErrorBuffer));
                MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Uncaught pcre2 match failure: %s", terminalp->descp->asciis, pcre2ErrorBuffer);
                goto fatal;
              }
              break;
            default:
              pcre2_get_error_message(pcre2Errornumberi, pcre2ErrorBuffer, sizeof(pcre2ErrorBuffer));
              MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Uncaught pcre2 match failure: %s", terminalp->descp->asciis, pcre2ErrorBuffer);
              goto fatal;
            }
          }
        } else {
          /* Need to alloc when eof is reached */
          if (! eofb) {
            allocb = 1;
          }
        }

        rci = MARPAESLIF_MATCH_OK;
      }

      /* We are done in any case */
      goto fast_done;
    }
  }

  if (terminalp->pseudob) {
    /* -------------------------------------------------------------------------------------------------------------------------------------------- */
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Doing pseudo terminal, inputl=%ld", (unsigned long) inputl);
    /* -------------------------------------------------------------------------------------------------------------------------------------------- */

    /* Pseudo terminal: having inputl <= 0 is legal */
    switch (terminalp->type) {
    case MARPAESLIF_TERMINAL_TYPE__EOF:
      /* Eof is reached when eofb is set and there is nothing in the internal buffer */
      if (eofb && (inputl <= 0)) {
        MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, ":eof match");
        rci            = MARPAESLIF_MATCH_OK;
        matchedp       = marpaESLIFRecognizerp->isLexemeb ? inputs /* To have the offset */ : (char *) MARPAESLIF_EMPTY_STRING;
        matchedLengthl = 0;
        /* Note that a pseudo-terminal is never allocated */
      } else {
        rci            = MARPAESLIF_MATCH_FAILURE;
      }
      break;

    case MARPAESLIF_TERMINAL_TYPE__EOL:
      /* :eof implies :eol */
      if (eofb && (inputl <= 0)) {
        MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, ":eol implicit match because of :eof");
        rci            = MARPAESLIF_MATCH_OK;
        matchedp       = marpaESLIFRecognizerp->isLexemeb ? inputs /* To have the offset */ : (char *) MARPAESLIF_EMPTY_STRING;
        matchedLengthl = 0;
        /* Note that a pseudo-terminal is never allocated */
      } else {
        /* Remember that :eol enforced newlineb option - therefore columnl is always accurate. */
        /* :eol is hitted if the next character(s) matches newline.                            */
        rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp,
                                                           marpaESLIF_streamp,
                                                           marpaESLIFRecognizerp->marpaESLIFp->newlineSymbolp,
                                                           &rci,
                                                           &marpaESLIFValueResultArray,
                                                           0, /* maxStartCompletionsi */
                                                           NULL, /* lastSizeBeforeCompletionlp */
                                                           NULL, /* numberOfStartCompletionsip */
                                                           NULL /* matchedLengthlp */);
        if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
          goto fatal;
        }
        if (! rcMatcherb) {
          goto err;
        }
        if (rci == MARPAESLIF_MATCH_OK) { /* C.f. rci default value that is MARPAESLIF_MATCH_FAILURE */
          /* We do not mind about the result */
          _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, &marpaESLIFValueResultArray);

          MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, ":eol match");
          matchedp       = marpaESLIFRecognizerp->isLexemeb ? inputs /* To have the offset */ : (char *) MARPAESLIF_EMPTY_STRING;
          matchedLengthl = 0;
        }
      }
      break;

    case MARPAESLIF_TERMINAL_TYPE__SOL:
      /* Remember that :sol enforced newlineb option. */
      /* The value 1 is the default, so it matches    */
      /* also if nothing has been read yet.           */
      /* Note that a :sol cannot be if :eof is set.   */
      if (eofb && (inputl <= 0)) {
        rci              = MARPAESLIF_MATCH_FAILURE;
      } else {
        if (marpaESLIF_streamp->columnl == 1) {
          MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, ":sol match");
          rci            = MARPAESLIF_MATCH_OK;
          matchedp       = marpaESLIFRecognizerp->isLexemeb ? inputs /* To have the offset */ : (char *) MARPAESLIF_EMPTY_STRING;
          matchedLengthl = 0;
	  /* Note that a pseudo-terminal is never allocated */
        } else {
          rci            = MARPAESLIF_MATCH_FAILURE;
        }
      }
      break;

    case MARPAESLIF_TERMINAL_TYPE__EMPTY:
      /* :empty always matches */
      MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, ":empty match");
      rci            = MARPAESLIF_MATCH_OK;
      matchedp       = marpaESLIFRecognizerp->isLexemeb ? inputs /* To have the offset */ : (char *) MARPAESLIF_EMPTY_STRING;
      matchedLengthl = 0;
      /* Note that a pseudo-terminal is never allocated */
      break;

    default:
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Unsupported terminal type %d", terminalp->type);
      goto fatal;
    }

  } else {
    /* -------------------------------------------------------------------------------------------------------------------------------------------- */
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Doing nothing, inputl=%ld", (unsigned long) inputl);
    /* -------------------------------------------------------------------------------------------------------------------------------------------- */
    /* No data, not a pseudo terminal, no fast path match, no regex match : ok only if we are at eof */
    rci = eofb ? MARPAESLIF_MATCH_FAILURE : MARPAESLIF_MATCH_AGAIN;
  }

 fast_done:
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcher_setb(marpaESLIFRecognizerp, marpaESLIF_streamp, allocb, rci, rcip, marpaESLIFValueResultp, matchedp, matchedLengthl, matchedLengthlp, substitutionb, &outputbufferp, outputbufferl))) {
    goto err;
  }

  rcb = 1;
  goto done;

 fatal:
  rcb = -1;
  goto done;

 err:
  rcb = 0;

 done:
  if (outputbufferp != NULL) {
    free(outputbufferp);
  }
#ifndef MARPAESLIF_NTRACE
  switch (rci) {
  case MARPAESLIF_MATCH_OK:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s for %s", "MARPAESLIF_MATCH_OK", terminalp->descp->asciis);
    break;
  case MARPAESLIF_MATCH_FAILURE:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s for %s", "MARPAESLIF_MATCH_FAILURE", terminalp->descp->asciis);
    break;
  case MARPAESLIF_MATCH_AGAIN:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s for %s", "MARPAESLIF_MATCH_AGAIN", terminalp->descp->asciis);
    break;
  default:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s for %s", "???", terminalp->descp->asciis);
    break;
  }
#endif
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_terminal_matcher_setb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_stream_t *marpaESLIF_streamp, short allocb, marpaESLIF_matcher_value_t rci, marpaESLIF_matcher_value_t *rcip, marpaESLIFValueResult_t *marpaESLIFValueResultp, char *matchedp, size_t matchedLengthl, size_t *matchedLengthlp, short substitutionb, PCRE2_UCHAR **outputbufferpp, PCRE2_SIZE outputbufferl)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_terminal_matcher_setb";
  short              rcb;

  if (rci == MARPAESLIF_MATCH_OK) {
    if (marpaESLIFValueResultp != NULL) {
      if (marpaESLIFRecognizerp->isLexemeb) {
        /* Offset internal mode */
        marpaESLIFValueResultp->contextp           = NULL;
        marpaESLIFValueResultp->representationp    = NULL;
        marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH;
        /* In lexeme mode, stream is guaranteed to never crunch, and buffers to always point to same data (but buffers itself can move via realloc()) */
        marpaESLIFValueResultp->u.o.p              = matchedp - marpaESLIF_streamp->buffers;
        marpaESLIFValueResultp->u.o.sizel          = matchedLengthl;
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Offset mode: returning OFFSET_AND_LENGTH {%ld,%ld}", (long) marpaESLIFValueResultp->u.o.p, marpaESLIFValueResultp->u.o.sizel);
      } else {
        if (substitutionb) {
          marpaESLIFValueResultp->contextp           = NULL;
          marpaESLIFValueResultp->representationp    = NULL;
          marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_ARRAY;
          marpaESLIFValueResultp->u.a.sizel          = (size_t) outputbufferl;
          marpaESLIFValueResultp->u.a.p              = (char *) *outputbufferpp;
          marpaESLIFValueResultp->u.a.shallowb       = 0;
          marpaESLIFValueResultp->u.a.freeUserDatavp = marpaESLIFRecognizerp->marpaESLIFp;
          marpaESLIFValueResultp->u.a.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Substitution mode: returning ARRAY {%p,%ld}", marpaESLIFValueResultp->u.a.p, marpaESLIFValueResultp->u.a.sizel);
          *outputbufferpp = NULL;
        } else {
          marpaESLIFValueResultp->contextp        = NULL;
          marpaESLIFValueResultp->representationp = NULL;
          marpaESLIFValueResultp->type            = MARPAESLIF_VALUE_TYPE_ARRAY;
          marpaESLIFValueResultp->u.a.sizel       = matchedLengthl;
          if (allocb) {
            marpaESLIFValueResultp->u.a.p = (char *) malloc(matchedLengthl + 1); /* We always add a NUL byte for convenience */
            if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.a.p == NULL)) {
              MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
              goto err;
            }
            memcpy(marpaESLIFValueResultp->u.a.p, (void *) matchedp, matchedLengthl);
            marpaESLIFValueResultp->u.a.p[matchedLengthl] = '\0';
            marpaESLIFValueResultp->u.a.shallowb       = 0;
            marpaESLIFValueResultp->u.a.freeUserDatavp = marpaESLIFRecognizerp->marpaESLIFp;
            marpaESLIFValueResultp->u.a.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Alloc mode: returning ARRAY {%p,%ld}", marpaESLIFValueResultp->u.a.p, marpaESLIFValueResultp->u.a.sizel);
          } else {
            marpaESLIFValueResultp->u.a.p              = matchedp;
            marpaESLIFValueResultp->u.a.shallowb       = 1;
            marpaESLIFValueResultp->u.a.freeUserDatavp = NULL;
            marpaESLIFValueResultp->u.a.freeCallbackp  = NULL;
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Shallow mode: returning ARRAY {%p,%ld}", marpaESLIFValueResultp->u.a.p, marpaESLIFValueResultp->u.a.sizel);
          }
        }
      }
    }

    /* By construction matchedLengthlp must always be set */
    *matchedLengthlp = matchedLengthl;
  }

  /* By construction rcip must always be set */
  *rcip = rci;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline marpaESLIF_grammar_t *_marpaESLIFRecognizer_meta_subGrammarp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_symbol_t *symbolp)
/*****************************************************************************/
/* Caller MUST have pushed the context if there is one.                      */
/*****************************************************************************/
{
  static const char                       *funcs                       = "_marpaESLIFRecognizer_meta_subGrammarp";
  marpaESLIF_grammar_t                    *grammarp                    = marpaESLIFRecognizerp->grammarp;
  marpaESLIFGrammar_t                     *marpaESLIFGrammarp          = grammarp->marpaESLIFGrammarp;
  marpaESLIFValueResult_t                  generatedValueResult        = marpaESLIFValueResultUndef;
  marpaESLIF_string_t                     *utf8p                       = NULL;
  marpaESLIF_string_t                     *utf8WithLevelp              = NULL;
  marpaESLIFGrammar_t                     *generatedGrammarp           = NULL;
  marpaESLIFValueResult_t                  context                     = marpaESLIFValueResultUndef;
  marpaESLIFGrammarOption_t                generatedGrammarOption;
  marpaESLIFGrammar_t                     *lexemeGrammarp;
  marpaESLIFRecognizerGeneratorCallback_t  generatorCallbackp;
  marpaESLIF_string_t                      generatedString;
  char                                     startSymbols[1024];
  char                                     levels[1024];
  char                                    *p;
  marpaESLIF_grammar_t                    *rcp;
  int                                      nextSymboli;
#ifndef MARPAESLIF_NTRACE
  char                                    *grammarshows;
#endif

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

#ifndef MARPAESLIF_NTRACE
  /* Safe check - should never happen though */
  if (MARPAESLIF_UNLIKELY(symbolp->type != MARPAESLIF_SYMBOL_TYPE_META)) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s called for a symbol that is not a meta symbol (type %d)", funcs, symbolp->type);
    goto err;
  }
#endif

  if (symbolp->generatorActionp != NULL) {
    /* Note that we do not re-inject the context: by definition a generator action is parameterized: called */
    /* should have made sure it already injected the context.                                               */

    /* Recuperate the context,  a marpaESLIFValueResult that we own and will have to be freed */
    if (MARPAESLIF_UNLIKELY(_marpaESLIFRecognizer_context_getp(marpaESLIFRecognizerp, &context) == NULL)) {
      goto err;
    }

    /* Note that by definition when a generator action is attached to a symbol, the symbol is parameterized */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_recognizerGeneratorActionCallbackb(marpaESLIFRecognizerp, symbolp->descp->asciis, symbolp->generatorActionp, &generatorCallbackp))) {
      goto err;
    }

    /* Get the generated string - it is enough to set p member to NULL to check if the called tried to fool us */
    generatedValueResult.u.s.p              = NULL;
    generatedValueResult.u.s.shallowb       = 0;
    generatedValueResult.u.s.freeUserDatavp = NULL;
    generatedValueResult.u.s.freeCallbackp  = NULL;
    generatedValueResult.u.s.sizel          = 0;
    generatedValueResult.u.s.encodingasciis = NULL;
    if (! generatorCallbackp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, marpaESLIFRecognizerp, &context, &(generatedValueResult.u.s))) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s callback failed", _marpaESLIF_action2asciis(symbolp->generatorActionp));
      goto err;
    }

    /* Callback success: mark it as string and do a basic check */
    generatedValueResult.type = MARPAESLIF_VALUE_TYPE_STRING;
    if (MARPAESLIF_UNLIKELY(generatedValueResult.u.s.p == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s callback success but points to NULL", _marpaESLIF_action2asciis(symbolp->generatorActionp));
      goto err;
    }
    if (MARPAESLIF_UNLIKELY(generatedValueResult.u.s.sizel <= 0)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s callback success but it is empty", _marpaESLIF_action2asciis(symbolp->generatorActionp));
      goto err;
    }

    /* Convert it to UTF-8 */
    generatedString.bytep          = (char *) generatedValueResult.u.s.p;
    generatedString.bytel          = generatedValueResult.u.s.sizel;
    generatedString.encodingasciis = generatedValueResult.u.s.encodingasciis;
    generatedString.asciis         = NULL;
    utf8p = _marpaESLIF_string2utf8p(marpaESLIFRecognizerp->marpaESLIFp, &generatedString, 0 /* tconvsilentb */);
    if (MARPAESLIF_UNLIKELY(utf8p == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s callback success but cannot be convered to UTF-8", _marpaESLIF_action2asciis(symbolp->generatorActionp));
      goto err;
    }

    /* Before checking the eventual precompiled grammar from cache we want to make it unique.   */
    /* Uniqueness of a generated grammar depend on two things: the grammar level and the output */
    /* of the callback.                                                                         */
    /* We want to recuperate the original grammar */

    /* We have:                                                                                 */
    /* LHS<-(parlists) ::= . => <lua function>->(explists)                                      */
    /*                                                                                          */
    /* <lua function>->(explists) will generate a grammar that is injected like this:           */
    /* <Internal[]><-(parlists)  ::= <generated grammar>                                        */
    /*                                                                                          */
    /* Where explists is injected on-the-fly.                                                   */

    nextSymboli = GENERICSTACK_USED(grammarp->symbolStackp);
    sprintf(startSymbols, "Internal[%d]", nextSymboli);
    sprintf(levels, " :[%d]:= ", grammarp->leveli);

    utf8WithLevelp = _marpaESLIF_string_newp(marpaESLIFRecognizerp->marpaESLIFp, (char *) MARPAESLIF_UTF8_STRING, NULL /* bytep */, 0 /* bytel */);
    if (MARPAESLIF_UNLIKELY(utf8WithLevelp == NULL)) {
      goto err;
    }
    /* If symbolp is parameterized, we want to honour it is if using "->" or "-->". This is in symbolp->declp->luaexplistcb. */
    utf8WithLevelp->bytel =
      1 + strlen(startSymbols) + 1                                                                          + /* "<Internal[counti]>" */
      (symbolp->parameterizedRhsb ? (symbolp->callp->luaexplistcb ? 3 /* "<--" */ : 2 /* "<-" */) : 0)      + /* "<--" or "<-" or "" */
      (symbolp->parameterizedRhsb ? (symbolp->declp != NULL ? strlen(symbolp->declp->luaparlists) : 2) : 0) + /* "(parlists) or "()" or "" */
      strlen(levels)                                                                                        + /*  :[leveli]:=  */
      utf8p->bytel                                                                                            /* Generated grammar */
      ;
    utf8WithLevelp->bytep = (char *) malloc(utf8WithLevelp->bytel + 1); /* + 1 for a NUL byte */
    if (MARPAESLIF_UNLIKELY(utf8WithLevelp->bytep == NULL)) {
      goto err;
    }
    p = utf8WithLevelp->bytep;
    *p++ = '<';                                                                      /* < */
    memcpy(p, startSymbols, strlen(startSymbols));                                   /* "Internal[counti]" */
    p += strlen(startSymbols);
    *p++ = '>';                                                                      /* > */
    if (symbolp->parameterizedRhsb) {
      if (symbolp->callp->luaexplistcb) {
        memcpy(p, "<--", 3);                                                         /* <-- */
        p += 3;
      } else {
        memcpy(p, "<-", 2);                                                          /* <- */
        p += 2;
      }
      if (symbolp->declp != NULL) {
        memcpy(p, symbolp->declp->luaparlists, strlen(symbolp->declp->luaparlists)); /* parlists */
        p += strlen(symbolp->declp->luaparlists);
      } else {
        memcpy(p, "()", 2);                                                          /* () */
        p += 2;
      }
    }
    memcpy(p, levels, strlen(levels));                                               /*  :[leveli]:=  */
    p += strlen(levels);
    memcpy(p, utf8p->bytep, utf8p->bytel);                                           /* generated grammar */
    p += utf8p->bytel;
    *p = '\0';                                                                       /* NUL byte */
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Checking generated RHS:\n%s\n", utf8WithLevelp->bytep);

    /* Check if the top recognizer already cached a lexeme grammar corresponding this string */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_getLexemeGrammarFromCachep(marpaESLIFGrammarp, utf8WithLevelp, &lexemeGrammarp))) {
      goto err;
    }

    if (lexemeGrammarp == NULL) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Generating new grammar using:\n%s\n", utf8WithLevelp->bytep);
      /* Try to get a grammar from it. */

      /* Remember the marpaESLIFGrammarp->internalRuleCounti that is in bootstrap.c?   */
      /* It is still here. So here what happens: during bootstrap a parameterized RHS  */
      /* is ALWAYS a single grammar terminal. This mean that:                          */
      /* LHS ::= ... <Parameterized Rhs> ... always guarantee that <Parameterized Rhs> */
      /* is unique.                                                                    */
      /* - We request (as documented) that the generated string is an RHS              */
      /*   Note that it can itself be a parameterized RHS. Then this will recurse.     */
      /* - We create a new internal rule in the form:                                  */
      /* Internal[counti]<--(LHS parlist> <correct op level> <generatedRhsAsUtf8>      */
      /*   Note that by definition counti value is the next available free value.      */
      /* - We extend original grammar with this internal rule.                         */
      /* - We add a :start on it (it is allowed to have several time :start ;-)        */
      /* - We reparse the whole grammar forcing the start symbol at <correct op level> */
      /*   to be at Internal[counti]                                                   */

      /* We do not want to reparse the whole original grammar + the generated action.  */
      /* This can cost at lot. Instead we will:                                        */
      /* - Clone the original grammar                                                  */
      /* - Call for parsing. This will natively append to the clone.                   */
      
      /* Only external grammars can have generators. So a copy of the grammar should   */
      /* never be unset.                                                               */
      generatedGrammarOption.bytel     =
        6                                                                                                     + /* ":start" */
        strlen(levels)                                                                                        + /* " :[leveli]:= " */
        1 + strlen(startSymbols) + 1                                                                          + /* "<Internal[counti]>" */
        (symbolp->parameterizedRhsb ? (symbolp->callp->luaexplistcb ? 3 /* "-->" */ : 2 /* "->" */) : 0)      + /* "-->" or "->" or "" */
        (symbolp->parameterizedRhsb ? (symbolp->declp != NULL ? strlen(symbolp->declp->luaparlists) : 2) : 0) + /* "(parlists) or "()" or "" */
        1                                                                                                     + /* \n */
        utf8WithLevelp->bytel                                                                                 /* "Internal[counti] :[leveli]:= generated grammar " */
        ;
      generatedGrammarOption.bytep     = (char *) malloc(generatedGrammarOption.bytel + 1); /* + 1 for a NUL byte */
      if (MARPAESLIF_UNLIKELY(generatedGrammarOption.bytep == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }

      p = generatedGrammarOption.bytep;
      memcpy(p, MARPAESLIF__START, strlen(MARPAESLIF__START));                              /* ":start" */
      p += strlen(MARPAESLIF__START);
      memcpy(p, levels, strlen(levels));                                                    /* " :[leveli]:= " */
      p += strlen(levels);
      *p++ = '<';                                                                           /* < */
      memcpy(p, startSymbols, strlen(startSymbols));                                        /* "Internal[counti]" */
      p += strlen(startSymbols);
      *p++ = '>';                                                                           /* > */
      if (symbolp->parameterizedRhsb) {
        if (symbolp->callp->luaexplistcb) {
          memcpy(p, "-->", 3);
          p += 3;
        } else {
          memcpy(p, "->", 2);
          p += 2;
        }
        if (symbolp->declp != NULL) {
          memcpy(p, symbolp->declp->luaparlists, strlen(symbolp->declp->luaparlists));
          p += strlen(symbolp->declp->luaparlists);
        } else {
          memcpy(p, "()", 2);
          p += 2;
        }
      }
      *p++ = '\n';                                                                          /* \n */
      memcpy(p, utf8WithLevelp->bytep, utf8WithLevelp->bytel);                              /* "Internal[counti] :[leveli]:= generated grammar" */
      p += utf8WithLevelp->bytel;
      *p = '\0';                                                                            /* NUL byte */

      generatedGrammarOption.encodings = (char *) MARPAESLIF_UTF8_STRING;
      generatedGrammarOption.encodingl = strlen(MARPAESLIF_UTF8_STRING);

      generatedGrammarp = _marpaESLIFGrammar_newp(marpaESLIFRecognizerp->marpaESLIFp, &generatedGrammarOption, marpaESLIFGrammarp->Lsharep, 0 /* bootstrapb */, 1 /* rememberGrammarUtf8b */, startSymbols, grammarp->leveli, marpaESLIFGrammarp->marpaESLIFGrammar_bootstrapp /* marpaESLIFGrammar_bootstrapOrigp */);

      /* Whatever happens we can free generatedGrammarOption.bytep */
      free(generatedGrammarOption.bytep);
      generatedGrammarOption.bytep = NULL;
      
      if (generatedGrammarp == NULL) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s callback returned a string that cannot be converted to a grammar", _marpaESLIF_action2asciis(symbolp->generatorActionp));
        goto err;
      }

      /* Put it to cache */
      if (! _marpaESLIFRecognizer_putLexemeGrammarToCacheb(marpaESLIFGrammarp, utf8WithLevelp, generatedGrammarp)) {
        goto err;
      }

      lexemeGrammarp = generatedGrammarp;

      /* utf8WithLevelp and generatedGrammarp are now in the hash */
      utf8WithLevelp = NULL;
      generatedGrammarp = NULL;
    } else {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Got cached grammar for generated RHS:\n%s\n", utf8WithLevelp->bytep);
    }

    /* We recuperate the exact sub grammar from the generated grammar */
    rcp = _marpaESLIFGrammar_grammar_findp(lexemeGrammarp, grammarp->leveli, NULL /* descp */);
  } else {

    lexemeGrammarp = symbolp->u.metap->marpaESLIFGrammarLexemeClonep;
    rcp = lexemeGrammarp->grammarp;
  }

  goto done;
  
 err:
  rcp = NULL;

 done:
  if (! _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, &context, 1 /* deepb */)) {
    rcp = NULL;
  }
  _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, &generatedValueResult);
  if ((utf8p != NULL) && (utf8p != &generatedString)) {
    /* We remain paranoid even if this can never happen: this is a string that comes from outside */
    _marpaESLIF_string_freev(utf8p, 0 /* onStstackb */);
  }
  _marpaESLIFGrammar_freev(generatedGrammarp, 0 /* onStackb */);
  _marpaESLIF_string_freev(utf8WithLevelp, 0 /* onStstackb */);

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %p", (int) rcp);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcp;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_meta_matcherb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_symbol_t *symbolp, marpaESLIF_matcher_value_t *rcip, marpaESLIFValueResult_t *marpaESLIFValueResultp, short *isExhaustedbp, int maxStartCompletionsi, size_t *lastSizeBeforeCompletionlp, int *numberOfStartCompletionsip, size_t *matchedLengthlp)
/*****************************************************************************/
{
  /* All in all, this routine is the core of this module, and the cause of recursion -; */
  static const char                       *funcs                       = "_marpaESLIFRecognizer_meta_matcherb";
  marpaESLIFRecognizerOption_t             marpaESLIFRecognizerOption  = marpaESLIFRecognizerp->marpaESLIFRecognizerOption; /* This is an internal recognizer */
  marpaESLIFValueOption_t                  marpaESLIFValueOption       = marpaESLIFValueOption_default_template;
  short                                    contextb                    = 0; /* To remember if we have to clear context */
  short                                    rcb;
  short                                    rcMatcherb;
  marpaESLIF_matcher_value_t               rci;
  marpaESLIFValueResult_t                  marpaESLIFValueResult;
  marpaESLIF_grammar_t                    *subGrammarp;
  short                                    discardb;
  short                                    noEventb;
  short                                    silentb;
  size_t                                   matchedLengthl;
  short                                    isLexemeb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

#ifndef MARPAESLIF_NTRACE
  /* Safe check - should never happen though */
  if (MARPAESLIF_UNLIKELY(symbolp->type != MARPAESLIF_SYMBOL_TYPE_META)) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s called for a symbol that is not a meta symbol (type %d)", funcs, symbolp->type);
    goto err;
  }
#endif

  /* If it is a lookahead with a single terminal, do the test immediately for performance - we do not mind about sub grammar or context in this case */
  if (symbolp->lookaheadIsTerminalb) {
    rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp,
						       marpaESLIFRecognizerp->marpaESLIF_streamp,
						       symbolp->lookaheadSymbolp,
						       &rci,
						       &marpaESLIFValueResult,
						       maxStartCompletionsi,
						       lastSizeBeforeCompletionlp,
						       numberOfStartCompletionsip,
                                                       &matchedLengthl);
    if (MARPAESLIF_UNLIKELY(rcMatcherb <= 0)) {
      goto err;
    }
    if (rci != MARPAESLIF_MATCH_OK) {
      goto err;
    }
  } else {

    /* Push context, if any */
    if (symbolp->parameterizedRhsb) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                  funcs,
                                  "Pushing context for symbol %s%s%s: %s<->%s",
                                  symbolp->descp->asciis,
                                  symbolp->callp->luaexplistcb ? "-->" : "->",
                                  symbolp->callp->luaexplists,
                                  symbolp->declp != NULL ? symbolp->declp->luaparlists : "nil",
                                  symbolp->callp->luaexplists);
      if (! _marpaESLIF_lua_recognizer_push_contextb(marpaESLIFRecognizerp, symbolp)) {
        goto err;
      }
      contextb = 1;
    }

    subGrammarp = _marpaESLIFRecognizer_meta_subGrammarp(marpaESLIFRecognizerp, symbolp);
    if (MARPAESLIF_UNLIKELY(subGrammarp == NULL)) {
      /* This is considered fatal */
      goto fatal;
    }

    /* We always want to run an internal recognizer */
    marpaESLIFRecognizerOption = marpaESLIFRecognizerp->marpaESLIFRecognizerOption;

    /* In any case we want to disable threshold warning and allow remaining data after completion, though not beeing polluted by exhaustion event */
    marpaESLIFRecognizerOption.disableThresholdb =  1;
    marpaESLIFRecognizerOption.exhaustedb        = -1;

    /* Is that a true lexeme ? There are two other cases that look like a lexeme but are NOT: */
    /* - contextual RHS                                                                       */
    /* - generator RHS                                                                        */
    /* - lookahead RHS                                                                        */
    if (symbolp->parameterizedRhsb || (symbolp->generatorActionp != NULL) || symbolp->lookaheadb) {
      discardb  = marpaESLIFRecognizerp->discardb;
      noEventb  = marpaESLIFRecognizerp->noEventb;
      silentb   = 1;
      isLexemeb = 0;
    } else {
      /* A true lexeme */
      discardb  = 0;
      noEventb  = 1;
      silentb   = 1;
      isLexemeb  = 1;
    }

    if (! _marpaESLIFGrammar_parseb(marpaESLIFRecognizerp->marpaESLIFp,
				    subGrammarp,
				    &marpaESLIFRecognizerOption,
				    &marpaESLIFValueOption,
				    discardb,
				    noEventb,
				    silentb,
				    marpaESLIFRecognizerp,
				    isExhaustedbp,
				    &marpaESLIFValueResult,
				    maxStartCompletionsi,
				    lastSizeBeforeCompletionlp,
				    numberOfStartCompletionsip,
				    symbolp->verboseb,
                                    &matchedLengthl,
                                    isLexemeb)) {
      goto err;
    }
  }

  if (matchedLengthlp != NULL) {
    *matchedLengthlp = matchedLengthl;
  }

  if (marpaESLIFValueResultp == NULL) {
    /* We do not mind about the result */
    _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, &marpaESLIFValueResult, 1 /* deepb */);
  } else {
    if (isLexemeb && (! marpaESLIFRecognizerp->isLexemeb)) {
      /* We convert OFFSET_AND_LENGTH to ARRAY */
      if (marpaESLIFRecognizerp->marpaESLIF_streamp->eofb) {
        /* No need to allocate */
        marpaESLIFValueResultp->contextp           = NULL;
        marpaESLIFValueResultp->representationp    = NULL;
        marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_ARRAY;
        marpaESLIFValueResultp->u.a.p              = marpaESLIFRecognizerp->marpaESLIF_streamp->buffers + marpaESLIFValueResult.u.o.p;
        marpaESLIFValueResultp->u.a.shallowb       = 1;
        marpaESLIFValueResultp->u.a.freeUserDatavp = NULL;
        marpaESLIFValueResultp->u.a.freeCallbackp  = NULL;
        marpaESLIFValueResultp->u.a.sizel          = marpaESLIFValueResult.u.o.sizel;
      } else {
        /* Stream may move */
        marpaESLIFValueResultp->contextp           = NULL;
        marpaESLIFValueResultp->representationp    = NULL;
        marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_ARRAY;
        marpaESLIFValueResultp->u.a.p              = (char *) malloc(marpaESLIFValueResult.u.o.sizel + 1); /* We always add a NUL byte for convenience */
        if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.a.p == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        memcpy(marpaESLIFValueResultp->u.a.p, (void *) (marpaESLIFRecognizerp->marpaESLIF_streamp->buffers + marpaESLIFValueResult.u.o.p), marpaESLIFValueResult.u.o.sizel);
        marpaESLIFValueResultp->u.a.p[marpaESLIFValueResult.u.o.sizel] = '\0';
        marpaESLIFValueResultp->u.a.shallowb       = 0;
        marpaESLIFValueResultp->u.a.freeUserDatavp = marpaESLIFRecognizerp->marpaESLIFp;
        marpaESLIFValueResultp->u.a.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;
        marpaESLIFValueResultp->u.a.sizel          = marpaESLIFValueResult.u.o.sizel;
      }
    } else {
      *marpaESLIFValueResultp = marpaESLIFValueResult;
    }
  }

  if (rcip != NULL) {
    *rcip = MARPAESLIF_MATCH_OK;
  }

  rcb = 1;
  goto done;
  
 fatal:
  rcb = -1;
  goto done;

 err:
  rcb = 0;

 done:
  /* Pop context if we pushed one */
  if (contextb) {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                funcs,
                                "Popping context for symbol %s%s%s: %s<->%s",
                                symbolp->descp->asciis,
                                symbolp->callp->luaexplistcb ? "-->" : "->",
                                symbolp->callp->luaexplists,
                                symbolp->declp != NULL ? symbolp->declp->luaparlists : "nil",
                                symbolp->callp->luaexplists);
    if (! _marpaESLIF_lua_recognizer_pop_contextb(marpaESLIFRecognizerp)) {
      rcb = 0;
    }
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_stream_t *marpaESLIF_streamp, marpaESLIF_symbol_t *symbolp, marpaESLIF_matcher_value_t *rcip, marpaESLIFValueResult_t *marpaESLIFValueResultp, int maxStartCompletionsi, size_t *lastSizeBeforeCompletionlp, int *numberOfStartCompletionsip, size_t *matchedLengthlp)
/*****************************************************************************/
/* This function can call for more data.                                     */
/* If the later fails, it returns -1 (fatal), 0 (normal error) or 1 (ok).    */
/* marpaESLIFValueResultp is assumed to always be != NULL.                   */
/*****************************************************************************/
{
  static const char                *funcs = "_marpaESLIFRecognizer_symbol_matcherb";
  short                             rcb;
  marpaESLIF_matcher_value_t        rci;
  size_t                            lastSizeBeforeCompletionl;
  int                               numberOfStartCompletionsi;
  marpaESLIFRecognizerIfCallback_t  ifCallbackp;
  marpaESLIFValueResultBool_t       marpaESLIFValueResultBool;
  short                             rcMatcherb;
  short                             lookaheadMatchb;
  size_t                            matchedLengthl;
  unsigned char                     uc;
  marpaESLIF_terminal_t            *terminalp;
  int                               utf82ordi;
  marpaESLIF_uint32_t               codepointi;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

 match_again:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Trying to match %s, eofb=%d, inputl=%ld", symbolp->descp->asciis, (int) marpaESLIF_streamp->eofb, marpaESLIF_streamp->inputl);
  switch (symbolp->type) {
  case MARPAESLIF_SYMBOL_TYPE_TERMINAL:
    terminalp = symbolp->u.terminalp;
    lastSizeBeforeCompletionl = 0;
#ifndef MARPAESLIF_NTRACE
    /* Paranoid test: a terminal can match only once and have consumed nothing before completion */
    if (maxStartCompletionsi > 1) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "maxStartCompletionsi=%d is not possible with a terminal", maxStartCompletionsi);
      rci = MARPAESLIF_MATCH_FAILURE;
      rcb = 1;
      goto fast_done;
    }
#endif
    /* Support of predicted failure ? */
    if (marpaESLIF_streamp->inputl > 0) {
      if (terminalp->byte2failureb) {
        uc = (unsigned char) marpaESLIF_streamp->inputs[0];
        if (terminalp->willfailasciib[uc]) {
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: ASCII mode: Predicted failure for byte 0x%02x (%c)", symbolp->descp->asciis, (int) uc, isprint(uc) ? (char) uc : ' ');
          rci = MARPAESLIF_MATCH_FAILURE;
          rcb = 1;
          goto fast_done;
        }
      }
      /* For UTF-8 we want to make sure we are at eof or there are at least 4 bytes */
      if (terminalp->utf2failureb) {
        if ((marpaESLIF_streamp->inputl >= 4) && marpaESLIF_streamp->utfb) {
          utf82ordi = _marpaESLIF_utf82ordi((PCRE2_SPTR8) marpaESLIF_streamp->inputs, &codepointi, (PCRE2_SPTR8) (marpaESLIF_streamp->inputs + marpaESLIF_streamp->inputl));
          if (MARPAESLIF_LIKELY(utf82ordi > 0)) {
            /* We support predicted UTF-8 failure only for codepoints < 256 */
            if (codepointi < 256) {
              if (terminalp->willfailutfb[codepointi]) {
                MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: UTF-8 mode: Predicted failure for codepoint %d", symbolp->descp->asciis, (int) codepointi);
                rci = MARPAESLIF_MATCH_FAILURE;
                rcb = 1;
                goto fast_done;
              }
            }
          }
        }
      }
    }
    /* A terminal matcher NEVER updates the stream : inputs, inputl and eof can be passed as is. */
    rcMatcherb = _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizerp,
                                                         marpaESLIF_streamp,
                                                         terminalp,
                                                         marpaESLIF_streamp->inputs,
                                                         marpaESLIF_streamp->inputl,
                                                         marpaESLIF_streamp->eofb,
                                                         &rci,
                                                         marpaESLIFValueResultp,
                                                         &matchedLengthl);
    if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
      goto fatal;
    }
    if (! rcMatcherb) {
      goto err;
    }

    switch (rci) {
    case MARPAESLIF_MATCH_AGAIN:
      /* We have to load more unless already at EOF */
      if (! marpaESLIF_streamp->eofb) {
        if (MARPAESLIF_LIKELY(__marpaESLIFRecognizer_readb(marpaESLIFRecognizerp))) {
          goto match_again;
        } else {
          /* We will return -1 */
          goto fatal;
        }
      }
      break;
    case MARPAESLIF_MATCH_OK:
      /* A terminal matcher completes once only per definition */
      numberOfStartCompletionsi = 1;
      break;
    default:
      break;
    }

    break;
 
  case MARPAESLIF_SYMBOL_TYPE_META:
    /* A meta matcher calls recursively other recognizers, reading new data, etc... : this will update current recognizer inputs, inputl and eof. */
    /* The result will be a parse tree value, at indice 0 of outputStackp */
    /* Special case of lookahead - only meta symbols can have this flag - then we do not mind about what matched - only if it matched. */
    if (! symbolp->lookaheadb) {
      /* Not a lookahead */
      rcMatcherb = _marpaESLIFRecognizer_meta_matcherb(marpaESLIFRecognizerp,
                                                       symbolp,
                                                       &rci,
                                                       marpaESLIFValueResultp,
                                                       NULL /* isExhaustedbp */,
                                                       maxStartCompletionsi,
                                                       &lastSizeBeforeCompletionl,
                                                       &numberOfStartCompletionsi,
                                                       &matchedLengthl);
      if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
        goto fatal;
      }
      if (! rcMatcherb) {
        goto err;
      }
      lookaheadMatchb = 0;
    } else if (symbolp->lookaheadb > 0) {
      /* Positive lookahead */
      rcMatcherb = _marpaESLIFRecognizer_meta_matcherb(marpaESLIFRecognizerp,
                                                       symbolp,
                                                       &rci,
                                                       NULL, /* marpaESLIFValueResultp */
                                                       NULL /* isExhaustedbp */,
                                                       maxStartCompletionsi,
                                                       &lastSizeBeforeCompletionl,
                                                       &numberOfStartCompletionsi,
                                                       NULL /* matchedLengthlp */);
      if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
        goto fatal;
      }
      if (! rcMatcherb) {
        goto err;
      }
      if (rci != MARPAESLIF_MATCH_OK) {
        goto err;
      }

      /* A lookahead match is always zero byte */
      lookaheadMatchb = 1;
      matchedLengthl = 0;

    } else {
      /* Negative lookahead */
      rcMatcherb = _marpaESLIFRecognizer_meta_matcherb(marpaESLIFRecognizerp,
                                                       symbolp,
                                                       &rci,
                                                       NULL, /* marpaESLIFValueResultp */
                                                       NULL /* isExhaustedbp */,
                                                       maxStartCompletionsi,
                                                       &lastSizeBeforeCompletionl,
                                                       &numberOfStartCompletionsi,
                                                       NULL /* matchedLengthlp */);
      if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
        goto fatal;
      }
      if (rcMatcherb) {
        goto err;
      }

      /* Invert rci */
      rci = MARPAESLIF_MATCH_OK;

      /* A lookahead match is always zero byte */
      lookaheadMatchb = 1;
      matchedLengthl = 0;
    }

    if (lookaheadMatchb) {
      /* Do like _marpaESLIFRecognizer_terminal_matcherb() when it matches */
      if (marpaESLIFRecognizerp->isLexemeb) {
	marpaESLIFValueResultp->contextp           = NULL;
	marpaESLIFValueResultp->representationp    = NULL;
	marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH;
	marpaESLIFValueResultp->u.o.p              = marpaESLIF_streamp->inputs - marpaESLIF_streamp->buffers;
	marpaESLIFValueResultp->u.o.sizel          = 0;
	MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Lexeme lookahead mode: returning OFFSET_AND_LENGTH {%ld,%ld}", (long) marpaESLIFValueResultp->u.o.p, (unsigned long) marpaESLIFValueResultp->u.o.sizel);
      } else {
	marpaESLIFValueResultp->contextp           = NULL;
	marpaESLIFValueResultp->representationp    = NULL;
	marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_ARRAY;
	marpaESLIFValueResultp->u.a.sizel          = 0;
	marpaESLIFValueResultp->u.a.p              = (char *) MARPAESLIF_EMPTY_STRING;
	marpaESLIFValueResultp->u.a.shallowb       = 1;
	marpaESLIFValueResultp->u.a.freeUserDatavp = NULL;
	marpaESLIFValueResultp->u.a.freeCallbackp  = NULL;
	MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Lexeme lookahead mode: returning ARRAY {%p,%ld}", marpaESLIFValueResultp->u.a.p, (unsigned long) marpaESLIFValueResultp->u.a.sizel);
      }
    }
    break;
  default:
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Unknown symbol type %d", symbolp->type);
    goto err;
  }
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "After %s try: eofb=%d, inputl=%ld", symbolp->descp->asciis, (int) marpaESLIF_streamp->eofb, marpaESLIF_streamp->inputl);

#ifndef MARPAESLIF_NTRACE
  MARPAESLIFRECOGNIZER_MATCH_TRACE(funcs, marpaESLIFRecognizerp, symbolp, rci, marpaESLIFValueResultp);
#endif

  if (rci == MARPAESLIF_MATCH_OK) {
    /* If symbol has an if-action, check it if we are the top-level recognizer */
    if ((symbolp->ifActionp != NULL) && MARPAESLIFRECOGNIZER_IS_TOP(marpaESLIFRecognizerp)) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_recognizerIfActionCallbackb(marpaESLIFRecognizerp, symbolp->descp->asciis, symbolp->ifActionp, &ifCallbackp))) {
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(! ifCallbackp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, marpaESLIFRecognizerp, marpaESLIFValueResultp, &marpaESLIFValueResultBool))) {
        goto err;
      }
      if (marpaESLIFValueResultBool == MARPAESLIFVALUERESULTBOOL_FALSE) {
        /* This symbol is rejected -; */
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Symbol %s is rejected by if-action", symbolp->descp->asciis);
        rci = MARPAESLIF_MATCH_FAILURE;
        rcb = 1;
        goto fast_done;
      }
    }
  }

 fast_done:
  if (rci == MARPAESLIF_MATCH_OK) {
    if (lastSizeBeforeCompletionlp != NULL) {
      *lastSizeBeforeCompletionlp = lastSizeBeforeCompletionl;
    }
    if (numberOfStartCompletionsip != NULL) {
      *numberOfStartCompletionsip = numberOfStartCompletionsi;
    }
    if (matchedLengthlp != NULL) {
      *matchedLengthlp = matchedLengthl;
    }
  }
  if (rcip != NULL) {
    *rcip = rci;
  }

  rcb = 1;
  goto done;

 fatal:
  rcb = -1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

#ifndef MARPAESLIF_NTRACE
/*****************************************************************************/
static void _marpaESLIF_tconvTraceCallback(void *userDatavp, const char *msgs)
/*****************************************************************************/
{
  static const char *funcs  = "_marpaESLIF_tconvTraceCallback";
  marpaESLIF_t *marpaESLIFp = (marpaESLIF_t *) userDatavp;

  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s", msgs);
}
#endif

/*****************************************************************************/
static inline char *_marpaESLIF_utf82printableascii_newp(marpaESLIF_t *marpaESLIFp, char *descs, size_t descl)
/*****************************************************************************/
{
  static const char      *funcs  = "_marpaESLIF_utf82printableascii_newp";
  size_t                  asciil;
  char                   *p;
  char                   *asciis;
  unsigned char           c;

  asciis = _marpaESLIF_charconvb(marpaESLIFp, "ASCII//TRANSLIT//IGNORE", (char *) MARPAESLIF_UTF8_STRING, descs, descl, &asciil, NULL /* fromEncodingsp */, NULL /* tconvpp */, 1 /* eofb */, NULL /* byteleftsp */, NULL /* byteleftlp */, NULL /* byteleftalloclp */, 1 /* tconvsilentb */, NULL /* defaultEncodings */, NULL /* fallbackEncodings */);
  if (asciis == NULL) {
    asciis = (char *) _marpaESLIF_utf82printableascii_defaultp;
    asciil = strlen(asciis);
  } else {
    /* We are doing this only on descriptions - which are always small amount of bytes  */
    /* (will the user ever write a description taking megabytes !?). Therefore if it ok */
    /* to remove by hand bom and realloc if necessary.                                  */

    /* Remove by hand any ASCII character not truely printable.      */
    /* Only the historical ASCII table [0-127] is a portable thingy. */
    p = asciis;
    while ((c = (unsigned char) *p) != '\0') {
      if ((c >= 128) || (! isprint(c & 0xFF))) {
        *p = ' ';
      }
      p++;
    }
  }

  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return \"%s\"", asciis); */
  return asciis;
}

/*****************************************************************************/
static inline void _marpaESLIF_utf82printableascii_freev(char *asciis)
/*****************************************************************************/
{
  if ((asciis != NULL) && (asciis != _marpaESLIF_utf82printableascii_defaultp)) {
    free(asciis);
  }
}

/*****************************************************************************/
static inline char *_marpaESLIF_charconvb(marpaESLIF_t *marpaESLIFp, char *toEncodings, char *fromEncodings, char *srcs, size_t srcl, size_t *dstlp, char **fromEncodingsp, tconv_t *tconvpp, short eofb, char **byteleftsp, size_t *byteleftlp, size_t *byteleftalloclp, short tconvsilentb, char *defaultEncodings, char *fallbackEncodings)
/*****************************************************************************/
/* The default is to work with the input as given in the arguments. This is the most efficient. */
/* Sometimes some bytes remained left over from a previous round. In this case, we have to prepend */
/* them to the area given in the parameters. Then we will work with a private area. */
/*****************************************************************************/
/* _marpaESLIF_charconvb is ALWAYS returning a non-NULL pointer in case of success (it allocates always one byte more, and put a NUL in it). */
/* Still, the number of converted bytes remain correct. */
/*****************************************************************************/
/* If caller provides byteleftsp != NULL he is RESPONSIBLE to also provide byteleftlp != NULL and byteleftalloclp != NULL */
{
  static const char *funcs       = "_marpaESLIF_charconvb";
  char              *outbuforigp = NULL;
  size_t             outbuforigl = 0;
  tconv_option_t     tconvOption = { NULL /* charsetp */, NULL /* convertp */, NULL /* traceCallbackp */, NULL /* traceUserDatavp */, fallbackEncodings /* fallbacks */ };
  tconv_t            tconvp      = NULL;
  char              *tmps;
  char              *inbuforigp;
  size_t             inleftorigl;
  char              *bytelefts;
  size_t             byteleftl;
  size_t             byteleftallocl;
  char              *inbufp;
  size_t             inleftl;
  char              *outbufp;
  size_t             outleftl;
  size_t             nconvl;
  size_t             tmpoutbuforigl;

  /* Is there a default encoding if caller gave none ? */
  if ((fromEncodings == NULL) && (defaultEncodings != NULL)) {
    fromEncodings = defaultEncodings;
  }

  if (byteleftsp != NULL) {
    bytelefts      = *byteleftsp;
    byteleftl      = *byteleftlp;
    byteleftallocl = *byteleftalloclp;

    if (byteleftl > 0) {
      /* By definition, then, byteleftsp is != NULL : this will be a realloc, eventually */
      if (byteleftallocl < (byteleftl + srcl)) {
	tmps = (char *) realloc(bytelefts, byteleftl + srcl);
	if (MARPAESLIF_UNLIKELY(tmps == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "realloc failure, %s", strerror(errno));
          goto err;
	}
	bytelefts = tmps;
	byteleftallocl = byteleftl + srcl;
      }
      memcpy(bytelefts + byteleftl, srcs, srcl);
      byteleftl += srcl;

      inbuforigp = bytelefts;
      inleftorigl = byteleftl;
    } else {
      /* No byte left: we work directly on user's buffer */
      inbuforigp  = srcs;
      inleftorigl = srcl;
    }
  } else {
    /* No byte left supported: we work directly on user's buffer */
    inbuforigp  = srcs;
    inleftorigl = srcl;
  }

#ifndef MARPAESLIF_NTRACE
  tconvOption.traceCallbackp  = _marpaESLIF_tconvTraceCallback;
  tconvOption.traceUserDatavp = marpaESLIFp;
#endif
  if (tconvpp != NULL) {
    tconvp = *tconvpp;
  }
  if (tconvp == NULL) {
    tconvp = tconv_open_ext(toEncodings, fromEncodings, &tconvOption);
    if (MARPAESLIF_UNLIKELY(tconvp == (tconv_t)-1)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "tconv_open failure, %s", strerror(errno));
      /* Well, I use NULL instead of -1 */
      tconvp = NULL;
      goto err;
    }
  }
#ifndef MARPAESLIF_NTRACE
  tconv_trace_on(tconvp);
#endif

  /* We start with an output buffer of the same size of input buffer.                  */
  /* Whatever the destination encoding, we always reserve one byte more to place a NUL */
  /* just in case. This NUL is absolutetly harmless but is usefull if one want to look */
  /* at the variables via a debugger -;.                                               */
  /* It is more than useful when the destination encoding is ASCII: string will be NUL */
  /* terminated by default.                                                            */
  outbuforigp = (char *) malloc(srcl + 1);
  if (MARPAESLIF_UNLIKELY(outbuforigp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }
  /* This setting is NOT necessary because *outbufp is always set to '\0' as well. But */
  /* I do this just to ease inspection in a debugger. */
  outbuforigp[srcl] = '\0';
  outbuforigl = srcl;

  /* We want to translate descriptions in trace or error cases - these are short things, and */
  /* it does not really harm if we redo the whole translation stuff in case of E2BIG:        */
  /* - in trace mode it is documented that performance is awful                              */
  /* - in error mode this call will happen once                                              */

  inbufp   = inbuforigp;
  inleftl  = inleftorigl;
  outbufp  = outbuforigp;
  outleftl = outbuforigl;
  
  while (1) {
  again:
    nconvl = tconv(tconvp, (inbufp != NULL) ? &inbufp : NULL, &inleftl, &outbufp, &outleftl);

    if (nconvl == (size_t) -1) {
      char  *tmps;
      size_t outleftdeltal;
      size_t outbufdeltal;

      switch (errno) {
      case EINVAL:
        /* Malformed multibyte character but eof of conversion buffer - this is not fatal unless we are ourself at eof! */
        if (MARPAESLIF_UNLIKELY(eofb)) {
          errno = EILSEQ;
	  if (! tconvsilentb) {
            char *traceFroms = tconv_fromcode(tconvp);
            char *traceTos = tconv_tocode(tconvp);
            if ((traceFroms != NULL) && (traceTos != NULL)) {
              MARPAESLIF_ERRORF(marpaESLIFp, "tconv %s -> %s failure, %s", traceFroms, traceTos, tconv_error(tconvp));
            } else if (traceFroms != NULL) {
              MARPAESLIF_ERRORF(marpaESLIFp, "tconv %s -> ? failure, %s", traceFroms, tconv_error(tconvp));
            } else if (traceTos != NULL) {
              MARPAESLIF_ERRORF(marpaESLIFp, "tconv ? -> %s failure, %s", traceTos, tconv_error(tconvp));
            } else {
              MARPAESLIF_ERRORF(marpaESLIFp, "tconv failure, %s", tconv_error(tconvp));
            }
	  }
          goto err;
        } else {
          goto end_of_loop;
        }
        break; /* Code never reach but this is ok */
      case E2BIG:
        /* Try to alloc more. outleftdeltal is the number of bytes added to output buffer */
        /* Default is to double allocate space, else use arbitrarily 1023 bytes (because of the +1 for the hiden NUL byte)*/
        outleftdeltal = (outbuforigl > 0) ? outbuforigl : 1023;
        tmpoutbuforigl = outbuforigl;
        outbuforigl += outleftdeltal;
        /* Will this ever happen ? */
        if (MARPAESLIF_UNLIKELY(outbuforigl < tmpoutbuforigl)) {
          MARPAESLIF_ERROR(marpaESLIFp, "size_t flip");
          goto err;
        }
        /* Make outbuforigl a mulitple of 1024 (-1 because of the +1 below) */
        /* outbuforigl = MARPAESLIF_CHUNKED_SIZE_UPPER(outbuforigl, 1024) - 1; */
        /* Remember current position in output buffer so that we can repostion after the realloc */
        outbufdeltal = outbufp - outbuforigp; /* Always >= 0 */
        /* Note the "+ 1" */
        tmps = realloc(outbuforigp, outbuforigl + 1); /* Still the +1 to put a NUL just to ease debug of UTF-8 but also its makes sure that ASCII string are ALWAYS NUL terminated */
        if (MARPAESLIF_UNLIKELY(tmps == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "realloc failure, %s", strerror(errno));
          goto err;
        }
        outbuforigp              = tmps;
        outbuforigp[outbuforigl] = '\0';
        outleftl                += outleftdeltal;
        outbufp                  = outbuforigp + outbufdeltal;
        goto again;
      default:
        /* Unsupported error code - this is fatal (includes EILSEQ of course) */
	if (! tconvsilentb) {
          char *traceFroms = tconv_fromcode(tconvp);
          char *traceTos = tconv_tocode(tconvp);
          if ((traceFroms != NULL) && (traceTos != NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFp, "tconv %s -> %s failure, %s", traceFroms, traceTos, tconv_error(tconvp));
          } else if (traceFroms != NULL) {
            MARPAESLIF_ERRORF(marpaESLIFp, "tconv %s -> ? failure, %s", traceFroms, tconv_error(tconvp));
          } else if (traceTos != NULL) {
            MARPAESLIF_ERRORF(marpaESLIFp, "tconv ? -> %s failure, %s", traceTos, tconv_error(tconvp));
          } else {
            MARPAESLIF_ERRORF(marpaESLIFp, "tconv failure, %s", tconv_error(tconvp));
          }
	}
	goto err;
      }
    }

    if (inbufp == NULL) {
      /* This was the last round */
      break;
    }

    if (inleftl <= 0) {
      /* Nothing left in input buffer. */
      if (tconvpp == NULL) {
        /* Caller does not want to know about tconvp: we flush */
        inbufp = NULL;
      } else {
        /* Caller wants to remember. He is responsible to call for flush */
        break;
      }
    }
  }

 end_of_loop:
  /* Remember that we ALWAYS allocate one byte more. This mean that outbufp points exactly at this extra byte */
  *outbufp = '\0';

  if (fromEncodingsp != NULL) {
    if (fromEncodings != NULL) {
      if (fromEncodings == MARPAESLIF_UTF8_STRING) {
        /* Internal constant used to avoid unnecessary strdup() call */
        *fromEncodingsp = (char *) MARPAESLIF_UTF8_STRING;
      } else {
        if (MARPAESLIF_UNLIKELY((*fromEncodingsp = strdup(fromEncodings)) == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
          goto err;
        }
      }
    } else {
      /* Get the guess from tconv */
      if (MARPAESLIF_UNLIKELY((*fromEncodingsp = tconv_fromcode(tconvp)) == NULL)) {
        /* Should never happen */
	MARPAESLIF_ERROR(marpaESLIFp, "tconv returned a NULL origin encoding");
        errno = EINVAL;
	goto err;
      }
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Encoding guessed to %s", *fromEncodingsp);
      /* We do not mind if we loose the original - it is inside tconv that will be freed */
      if (MARPAESLIF_UNLIKELY((*fromEncodingsp = strdup(*fromEncodingsp)) == NULL)) {
	MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
	goto err;
      }
    }
  }

  if (byteleftsp != NULL) {
    /* User said we want to keep track of remaining bytes */
    if (byteleftl > 0) {
      /* And we already started with at least one remaining byte: */
      /* the workbuffer was bytelefts, its allocated size does not change, */
      /* the remaining bytes in it in inleftl. */
      byteleftl = inleftl;
      if (byteleftl > 0) {
        /* We want to move unconsumed bytes at the beginning */
        /* so that next round will see them. */
	size_t consumedl = inleftorigl - inleftl;
        memmove(bytelefts, bytelefts + consumedl, byteleftl);
      }
    } else {
      /* And there was nothing to pick from previous round */
      if (inleftl > 0) {
	/* But there is from current round */
	size_t consumedl = inleftorigl - inleftl;
	if (bytelefts == NULL) {
	  /* And this is the first time this happens */
	  bytelefts = (char *) malloc(inleftl);
	  if (MARPAESLIF_UNLIKELY(bytelefts == NULL)) {
	    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
	    goto err;
	  }
	  memcpy(bytelefts, inbuforigp + consumedl, inleftl);
	  byteleftl = inleftl;
	  byteleftallocl = inleftl;
	} else {
	  /* And this has already happened in a round older than previous round */
	  if (byteleftallocl < inleftl) {
	    tmps = (char *) realloc(bytelefts, inleftl);
	    if (MARPAESLIF_UNLIKELY(tmps == NULL)) {
	      MARPAESLIF_ERRORF(marpaESLIFp, "realloc failure, %s", strerror(errno));
	      goto err;
	    }
	    bytelefts = tmps;
	    byteleftallocl = inleftl;
	  }
	  memcpy(bytelefts, inbuforigp + consumedl, inleftl);
	  byteleftl = inleftl;
	}
      }
    }
  }

  if (dstlp != NULL) {
    *dstlp = outbufp - outbuforigp;
  }
  goto done;

 err:
  /* If errno is EILSEQ then input pointer should be at the last successful converted location */
  if ((tconvp != NULL) && (errno == EILSEQ) && (inbuforigp != NULL) && (inleftorigl > 0) && (! tconvsilentb)) {
    char                   *fromCodes = tconv_fromcode(tconvp);
    size_t                  consumedl = inleftorigl - inleftl;
    /* We have to fake a recognizer - this is how the MARPAESLIFRECOGNIZER_HEXDUMPV() macros works */
    /* Take care, I had stack overflow because of these variables that are on the stack... */
    marpaESLIFRecognizer_t *marpaESLIFRecognizerp;

    /* Particularly dangerous: the MARPAESLIFRECOGNIZER_HEXDUMPV has to use NOTHING ELSE but marpaESLIFRecognizerp->marpaESLIFp (and this is the case -;) */
    marpaESLIFRecognizerp = (marpaESLIFRecognizer_t *)malloc(sizeof(marpaESLIFRecognizer_t));
    if (marpaESLIFRecognizerp != NULL) {

	marpaESLIFRecognizerp->marpaESLIFp = marpaESLIFp;

	/* If there is some information before, show it */
	if (consumedl > 0) {
	  char  *dumps;
	  size_t dumpl;

	  if (consumedl > 128) {
	    dumps = inbufp - 128;
	    dumpl = 128;
	  } else {
	    dumps = inbuforigp;
	    dumpl = consumedl;
	  }
	  MARPAESLIFRECOGNIZER_HEXDUMPV(funcs,
                                        marpaESLIFRecognizerp,
                                        (fromCodes != NULL) ? fromCodes : "", /* In theory, it is impossible to have fromCodes == NULL here */
                                        " data before the failure",
                                        dumps,
                                        dumpl,
                                        0, /* traceb */
                                        0, /* noticeb */
                                        0, /* linel */
                                        0 /* columnl */);
	}
	MARPAESLIF_ERROR(marpaESLIFp, "<<<<<< CHARACTER FAILURE HERE: >>>>>>");
	/* If there is some information after, show it */
	if (inleftl > 0) {
	  char  *dumps;
	  size_t dumpl;

	  dumps = inbuforigp + consumedl;
	  dumpl = inleftl > 128 ? 128 : inleftl;
	  MARPAESLIFRECOGNIZER_HEXDUMPV(funcs,
                                        marpaESLIFRecognizerp,
                                        (fromCodes != NULL) ? fromCodes : "", /* In theory, it is impossible to have fromCodes == NULL here */
                                        " data after the failure",
                                        dumps,
                                        dumpl,
                                        0, /* traceb */
                                        0, /* noticeb */
                                        0, /* linel */
                                        0 /* columnl */);
	}

	free(marpaESLIFRecognizerp);
    }
  }
  /* If the caller did not have a tconvp yet, we do not want to return this one that has just failed */
  if ((tconvpp != NULL) && (*tconvpp == NULL) && (tconvp != NULL)) {
    if (tconv_close(tconvp) != 0) {
      MARPAESLIF_ERRORF(marpaESLIFp, "tconv_close failure, %s", strerror(errno));
    }
    tconvp = NULL;
  }
  if (outbuforigp != NULL) {
    free(outbuforigp);
  }
  outbuforigp = NULL;

 done:
  if (tconvpp != NULL) {
    *tconvpp = tconvp;
  } else {
    if (tconvp != NULL) {
      if (tconv_close(tconvp) != 0) {
        MARPAESLIF_ERRORF(marpaESLIFp, "tconv_close failure, %s", strerror(errno));
      }
    }
  }
  if (byteleftsp != NULL) {
    /* Note that in case of an error we do not mind if *byteleftlp is NOT correct: the processing will stop anwyay */
    *byteleftsp      = bytelefts;
    *byteleftlp      = byteleftl;
    *byteleftalloclp = byteleftallocl;
  }

  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", outbuforigp); */
  return outbuforigp;
}

/*****************************************************************************/
marpaESLIFGrammar_t *marpaESLIFGrammar_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammarOption_t *marpaESLIFGrammarOptionp)
/*****************************************************************************/
{
  marpaESLIFGrammar_t *marpaESLIFGrammarp;

  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  /* Grammar from the external: we want to remember the UTF-8 version of it */
  marpaESLIFGrammarp = _marpaESLIFGrammar_newp(marpaESLIFp, marpaESLIFGrammarOptionp, NULL /* Lsharep */, 0 /* bootstrapb */, 1 /* rememberGrammarUtf8b */, NULL /* forcedStartSymbols */, -1 /* forcedStartSymbolLeveli */, NULL /* marpaESLIFGrammar_bootstrapp */);
  goto done;

 err:
  marpaESLIFGrammarp = NULL;

 done:
  return marpaESLIFGrammarp;
}

/*****************************************************************************/
static inline short _marpaESLIFGrammar_bootstrap_transferb(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp)
/*****************************************************************************/
/* Transfer the bootstrap part into the non-bootstrap section.               */
/*****************************************************************************/
{
  static const char              *funcs                             = "_marpaESLIFGrammar_bootstrap_transferb";
  marpaESLIFGrammar_bootstrap_t  *marpaESLIFGrammar_bootstrapp      = marpaESLIFGrammarp->marpaESLIFGrammar_bootstrapp;
  marpaESLIFGrammar_bootstrap_t  *marpaESLIFGrammar_bootstrapClonep = NULL;
  genericStack_t                 *grammarBootstrapCloneStackp;
  genericStack_t                 *grammarStackp;
  int                             grammari;
  marpaESLIF_grammar_bootstrap_t *grammarBootstrapClonep;
  marpaESLIF_grammar_t           *grammarp;
  int                             symboli;
  marpaESLIF_symbol_t            *symbolp;
  int                             rulei;
  marpaESLIF_rule_t              *rulep;
  short                           rcb;

  /* There is not a big difference between a marpaESLIFGrammar_bootstrap_t and marpaESLIFGrammar_t. What really changes */
  /* the inner stacks that are of types marpaESLIF_grammar_bootstrap_t and marpaESLIF_grammar_t, respectively.          */
  /* These inner stacks, though, contain also stacks that are of the common types marpaESLIF_symbol_t and               */
  /* marpaESLIF_rule_t. So it is enough to clone the bootstrap version and transfer what it needed ;)                   */
  marpaESLIFGrammar_bootstrapClonep = _marpaESLIFGrammar_bootstrap_clonep(marpaESLIFp, marpaESLIFGrammar_bootstrapp);
  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammar_bootstrapClonep == NULL)) {
    goto err;
  }

  /* Transfer data - we must take care of what is on the heap. */
  marpaESLIFGrammarp->warningIsErrorb                           = marpaESLIFGrammar_bootstrapClonep->warningIsErrorb;
  marpaESLIFGrammarp->warningIsIgnoredb                         = marpaESLIFGrammar_bootstrapClonep->warningIsIgnoredb;
  marpaESLIFGrammarp->autorankb                                 = marpaESLIFGrammar_bootstrapClonep->autorankb;
  marpaESLIFGrammarp->luabytep                                  = NULL;
  marpaESLIFGrammarp->luabytel                                  = 0;
  marpaESLIFGrammarp->luabytep                                  = marpaESLIFGrammar_bootstrapClonep->luabytep;
  marpaESLIFGrammar_bootstrapClonep->luabytep = NULL; /* has been transfered */
  marpaESLIFGrammarp->luabytel                                  = marpaESLIFGrammar_bootstrapClonep->luabytel;
  marpaESLIFGrammarp->internalRuleCounti                        = marpaESLIFGrammar_bootstrapClonep->internalRuleCounti;
  marpaESLIFGrammarp->hasPseudoTerminalb                        = marpaESLIFGrammar_bootstrapClonep->hasPseudoTerminalb;
  marpaESLIFGrammarp->hasEofPseudoTerminalb                     = marpaESLIFGrammar_bootstrapClonep->hasEofPseudoTerminalb;
  marpaESLIFGrammarp->hasEolPseudoTerminalb                     = marpaESLIFGrammar_bootstrapClonep->hasEolPseudoTerminalb;
  marpaESLIFGrammarp->hasSolPseudoTerminalb                     = marpaESLIFGrammar_bootstrapClonep->hasSolPseudoTerminalb;
  marpaESLIFGrammarp->hasEmptyPseudoTerminalb                   = marpaESLIFGrammar_bootstrapClonep->hasEmptyPseudoTerminalb;
  marpaESLIFGrammarp->hasLookaheadMetab                         = marpaESLIFGrammar_bootstrapClonep->hasLookaheadMetab;

  if ((marpaESLIFGrammar_bootstrapClonep->luabytep != NULL) && (marpaESLIFGrammar_bootstrapClonep->luabytel > 0)) {
    marpaESLIFGrammarp->luabytep = (char *) malloc(marpaESLIFGrammar_bootstrapClonep->luabytel + 1);
    if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp->luabytep == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    memcpy(marpaESLIFGrammarp->luabytep, marpaESLIFGrammar_bootstrapClonep->luabytep, marpaESLIFGrammar_bootstrapClonep->luabytel);
    marpaESLIFGrammarp->luabytel = marpaESLIFGrammar_bootstrapClonep->luabytel;
    marpaESLIFGrammarp->luabytep[marpaESLIFGrammarp->luabytel] = '\0';
  }

  grammarBootstrapCloneStackp = marpaESLIFGrammar_bootstrapClonep->grammarBootstrapStackp;
  if (grammarBootstrapCloneStackp != NULL) {

    marpaESLIFGrammarp->grammarStackp = &(marpaESLIFGrammarp->_grammarStack);
    GENERICSTACK_INIT_SIZED(marpaESLIFGrammarp->grammarStackp, GENERICSTACK_USED(grammarBootstrapCloneStackp));
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFGrammarp->grammarStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFGrammarp->grammarStackp initialization failure, %s", strerror(errno));
      marpaESLIFGrammarp->grammarStackp = NULL;
      goto err;
    }

    grammarStackp = marpaESLIFGrammarp->grammarStackp;

    for (grammari = 0; grammari < GENERICSTACK_USED(grammarBootstrapCloneStackp); grammari++) {
      if (GENERICSTACK_IS_PTR(grammarBootstrapCloneStackp, grammari)) {
        /* There is no fundamental difference between marpaESLIF_grammar_bootstrap_t and marpaESLIF_grammar_t. */
        /* In particular inner symbol and rule stacks are of the normal types marpaESLIF_symbol_t and          */
        /* marpaESLIF_rule_t types, respectively. So we just call for bootstrap clone and transfer the stacks. */
        grammarBootstrapClonep = (marpaESLIF_grammar_bootstrap_t *) GENERICSTACK_GET_PTR(grammarBootstrapCloneStackp, grammari);
        grammarp = (marpaESLIF_grammar_t *) malloc(sizeof(marpaESLIF_grammar_t));
        if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
          goto err;
        }
        if (! _marpaESLIF_grammar_initb(marpaESLIFp, grammarp, -1 /* leveli */, NULL /* marpaESLIFGrammarp */)) {
	  goto err;
	}

        /* At this point, it if fails we will have memory leaks */
        grammarp->marpaESLIFGrammarp        = marpaESLIFGrammarp;
	grammarp->Lsharep                   = (marpaESLIFGrammarp != NULL) ? marpaESLIFGrammarp->Lsharep : NULL;
        grammarp->marpaWrapperGrammarStartp = grammarBootstrapClonep->marpaWrapperGrammarStartp; grammarBootstrapClonep->marpaWrapperGrammarStartp = NULL;
        grammarp->nbupdatei                 = grammarBootstrapClonep->nbupdatei;
        grammarp->leveli                    = grammarBootstrapClonep->leveli;
        grammarp->latmb                     = grammarBootstrapClonep->latmb;
        grammarp->descp                     = grammarBootstrapClonep->descp;                     grammarBootstrapClonep->descp = NULL;
        grammarp->descautob                 = grammarBootstrapClonep->descautob;
        grammarp->discardIsFallbackb        = grammarBootstrapClonep->discardIsFallbackb;
        grammarp->defaultRuleActionp        = grammarBootstrapClonep->defaultRuleActionp;        grammarBootstrapClonep->defaultRuleActionp = NULL;
        grammarp->defaultSymbolActionp      = grammarBootstrapClonep->defaultSymbolActionp;      grammarBootstrapClonep->defaultSymbolActionp = NULL;
        grammarp->defaultEventActionp       = grammarBootstrapClonep->defaultEventActionp;       grammarBootstrapClonep->defaultEventActionp = NULL;
        grammarp->defaultRegexActionp       = grammarBootstrapClonep->defaultRegexActionp;       grammarBootstrapClonep->defaultRegexActionp = NULL;
        grammarp->defaultEncodings          = grammarBootstrapClonep->defaultEncodings;          grammarBootstrapClonep->defaultEncodings = NULL;
        grammarp->fallbackEncodings         = grammarBootstrapClonep->fallbackEncodings;         grammarBootstrapClonep->fallbackEncodings = NULL;
        /* Symbols transfer */
        for (symboli = 0; symboli < GENERICSTACK_USED(grammarBootstrapClonep->symbolStackp); symboli++) {
          MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, grammarBootstrapClonep->symbolStackp, symboli);
          GENERICSTACK_SET_PTR(grammarBootstrapClonep->symbolStackp, NULL /* symbolp */, symboli);
          GENERICSTACK_SET_PTR(grammarp->symbolStackp, symbolp, symboli);
        }
        GENERICSTACK_USED(grammarBootstrapClonep->symbolStackp) = 0; /* No need to scan this stack when freeing it */

        /* Rules transfer */
        for (rulei = 0; rulei < GENERICSTACK_USED(grammarBootstrapClonep->ruleStackp); rulei++) {
          MARPAESLIF_INTERNAL_GET_RULE_FROM_STACK(marpaESLIFp, rulep, grammarBootstrapClonep->ruleStackp, rulei);
          GENERICSTACK_SET_PTR(grammarBootstrapClonep->ruleStackp, NULL /* rulep */, rulei);
          GENERICSTACK_SET_PTR(grammarp->ruleStackp, rulep, rulei);
        }

	GENERICSTACK_SET_PTR(grammarStackp, grammarp, grammari);
      }
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  _marpaESLIFGrammar_bootstrap_freev(marpaESLIFGrammar_bootstrapClonep);
  return rcb;
}

/*****************************************************************************/
static inline marpaESLIFGrammar_bootstrap_t *_marpaESLIFGrammar_bootstrap_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammarOrigp)
/*****************************************************************************/
{
  static const char                *funcs                      = "_marpaESLIFGrammar_bootstrap_clonep";
  marpaESLIFGrammar_bootstrap_t    *marpaESLIFGrammarp         = NULL;
  genericStack_t                   *grammarBootstrapStackOrigp;
  genericStack_t                   *grammarBootstrapStackp;
  int                               grammari;
  marpaESLIF_grammar_bootstrap_t   *grammarOrigp;
  marpaESLIF_grammar_bootstrap_t   *grammarp;
  marpaESLIF_grammar_bootstrap_t   *grammarDeltap;
  int                               symboli;
  marpaESLIF_symbol_t              *symbolOrigp;
  marpaESLIF_symbol_t              *symbolp;
  genericStack_t                   *symbolStackp;
  genericStack_t                   *symbolStackOrigp;

  marpaESLIFGrammarp = (marpaESLIFGrammar_bootstrap_t *) malloc(sizeof(marpaESLIFGrammar_bootstrap_t));
  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  marpaESLIFGrammarp->grammarBootstrapStackp                    = NULL;
  marpaESLIFGrammarp->warningIsErrorb                           = marpaESLIFGrammarOrigp->warningIsErrorb;
  marpaESLIFGrammarp->warningIsIgnoredb                         = marpaESLIFGrammarOrigp->warningIsIgnoredb;
  marpaESLIFGrammarp->autorankb                                 = marpaESLIFGrammarOrigp->autorankb;
  marpaESLIFGrammarp->luabytep                                  = NULL;
  marpaESLIFGrammarp->luabytel                                  = 0;
  marpaESLIFGrammarp->internalRuleCounti                        = marpaESLIFGrammarOrigp->internalRuleCounti;
  marpaESLIFGrammarp->hasPseudoTerminalb                        = marpaESLIFGrammarOrigp->hasPseudoTerminalb;
  marpaESLIFGrammarp->hasEofPseudoTerminalb                     = marpaESLIFGrammarOrigp->hasEofPseudoTerminalb;
  marpaESLIFGrammarp->hasEolPseudoTerminalb                     = marpaESLIFGrammarOrigp->hasEolPseudoTerminalb;
  marpaESLIFGrammarp->hasSolPseudoTerminalb                     = marpaESLIFGrammarOrigp->hasSolPseudoTerminalb;
  marpaESLIFGrammarp->hasEmptyPseudoTerminalb                   = marpaESLIFGrammarOrigp->hasEmptyPseudoTerminalb;
  marpaESLIFGrammarp->hasLookaheadMetab                         = marpaESLIFGrammarOrigp->hasLookaheadMetab;

  if ((marpaESLIFGrammarOrigp->luabytep != NULL) && (marpaESLIFGrammarOrigp->luabytel > 0)) {
    marpaESLIFGrammarp->luabytel = marpaESLIFGrammarOrigp->luabytel;
    marpaESLIFGrammarp->luabytep = (char *) malloc(marpaESLIFGrammarp->luabytel + 1);
    if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp->luabytep == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    memcpy(marpaESLIFGrammarp->luabytep, marpaESLIFGrammarOrigp->luabytep, marpaESLIFGrammarp->luabytel);
    marpaESLIFGrammarp->luabytep[marpaESLIFGrammarp->luabytel] = '\0';
  }

  grammarBootstrapStackOrigp = marpaESLIFGrammarOrigp->grammarBootstrapStackp;
  if (grammarBootstrapStackOrigp != NULL) {

    marpaESLIFGrammarp->grammarBootstrapStackp = &(marpaESLIFGrammarp->_grammarBootstrapStack);
    GENERICSTACK_INIT(marpaESLIFGrammarp->grammarBootstrapStackp);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFGrammarp->grammarBootstrapStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFGrammarp->grammarBootstrapStackp initialization failure, %s", strerror(errno));
      marpaESLIFGrammarp->grammarBootstrapStackp = NULL;
      goto err;
    }

    grammarBootstrapStackp = marpaESLIFGrammarp->grammarBootstrapStackp;

    for (grammari = 0; grammari < GENERICSTACK_USED(grammarBootstrapStackOrigp); grammari++) {
      if (GENERICSTACK_IS_PTR(grammarBootstrapStackOrigp, grammari)) {
        grammarOrigp = (marpaESLIF_grammar_bootstrap_t *) GENERICSTACK_GET_PTR(grammarBootstrapStackOrigp, grammari);
        grammarp = _marpaESLIF_grammar_bootstrap_clonep(marpaESLIFp, marpaESLIFGrammarp, grammarOrigp);
        if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
          goto err;
        }
        GENERICSTACK_SET_PTR(grammarBootstrapStackp, grammarp, grammari);
        if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(grammarBootstrapStackp))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "grammarBootstrapStackp set failure, %s", strerror(errno));
          goto err;
        }
      }
    }
    /* There is a diffulty with forced lookup symbols: they can be resolved in the clone only at the price of a second stage */
    for (grammari = 0; grammari < GENERICSTACK_USED(grammarBootstrapStackp); grammari++) {
      if (GENERICSTACK_IS_PTR(grammarBootstrapStackp, grammari)) {

        grammarOrigp = (marpaESLIF_grammar_bootstrap_t *) GENERICSTACK_GET_PTR(grammarBootstrapStackOrigp, grammari);
        grammarp = (marpaESLIF_grammar_bootstrap_t *) GENERICSTACK_GET_PTR(grammarBootstrapStackp, grammari);

	symbolStackOrigp = grammarOrigp->symbolStackp;
	symbolStackp = grammarp->symbolStackp;

	for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackOrigp); symboli++) {
	  MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolOrigp, symbolStackOrigp, symboli);
	  if (symbolOrigp->lookupSymbolp != NULL) {
	    MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp, symbolStackp, symboli);

	    if (! GENERICSTACK_IS_PTR(grammarBootstrapStackp, grammari + symbolOrigp->lookupLevelDeltai)) {
	      MARPAESLIF_ERRORF(marpaESLIFp, "No bootstrap grammar at level %d+%d=%d", grammari, symbolOrigp->lookupLevelDeltai, grammari + symbolOrigp->lookupLevelDeltai);
	      goto err;
	    }
	    grammarDeltap = (marpaESLIF_grammar_bootstrap_t *) GENERICSTACK_GET_PTR(grammarBootstrapStackp, grammari + symbolOrigp->lookupLevelDeltai);

	    symbolp->lookupLevelDeltai = symbolOrigp->lookupLevelDeltai;
	    MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIFp, symbolp->lookupSymbolp, grammarDeltap->symbolStackp, symbolOrigp->lookupSymbolp->idi);
	  }
	}
      }
    }
  }

  goto done;

 err:
  /* We do not want to free it, if it was injected: parent should take care of that */
  _marpaESLIFGrammar_bootstrap_freev(marpaESLIFGrammarp);
  marpaESLIFGrammarp = NULL;

 done:
  return marpaESLIFGrammarp;
}

/*****************************************************************************/
static inline marpaESLIFGrammar_bootstrap_t *_marpaESLIFGrammar_bootstrap_newp(marpaESLIF_t *marpaESLIFp)
/*****************************************************************************/
{
  static const char                *funcs                      = "_marpaESLIFGrammar_bootstrap_newp";
  marpaESLIFGrammar_bootstrap_t    *marpaESLIFGrammarp         = NULL;

  marpaESLIFGrammarp = (marpaESLIFGrammar_bootstrap_t *) malloc(sizeof(marpaESLIFGrammar_bootstrap_t));
  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  marpaESLIFGrammarp->grammarBootstrapStackp                    = NULL;
  marpaESLIFGrammarp->warningIsErrorb                           = 0;
  marpaESLIFGrammarp->warningIsIgnoredb                         = 0;
  marpaESLIFGrammarp->autorankb                                 = 0;
  marpaESLIFGrammarp->luabytep                                  = NULL;
  marpaESLIFGrammarp->luabytel                                  = 0;
  marpaESLIFGrammarp->internalRuleCounti                        = 0;
  marpaESLIFGrammarp->hasPseudoTerminalb                        = 0;
  marpaESLIFGrammarp->hasEofPseudoTerminalb                     = 0;
  marpaESLIFGrammarp->hasEolPseudoTerminalb                     = 0;
  marpaESLIFGrammarp->hasSolPseudoTerminalb                     = 0;
  marpaESLIFGrammarp->hasEmptyPseudoTerminalb                   = 0;
  marpaESLIFGrammarp->hasLookaheadMetab                         = 0;

  goto done;

 err:
  /* We do not want to free it, if it was injected: parent should take care of that */
  _marpaESLIFGrammar_bootstrap_freev(marpaESLIFGrammarp);
  marpaESLIFGrammarp = NULL;

 done:
  return marpaESLIFGrammarp;
}

/*****************************************************************************/
static inline marpaESLIFGrammar_t *_marpaESLIFGrammar_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammarOption_t *marpaESLIFGrammarOptionp, marpaESLIFGrammar_Lshare_t *Lsharep, short bootstrapb, short rememberGrammarUtf8b, char *forcedStartSymbols, int forcedStartSymbolLeveli, marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammar_bootstrapOrigp)
/*****************************************************************************/
{
  static const char                *funcs                       = "_marpaESLIFGrammar_newp";
  marpaESLIFRecognizerOption_t      marpaESLIFRecognizerOption  = marpaESLIFRecognizerOption_default_template;
  marpaESLIFValueOption_t           marpaESLIFValueOption       = marpaESLIFValueOption_default_template;
  marpaESLIFGrammar_t              *marpaESLIFGrammarp          = NULL;
  marpaESLIFGrammar_bootstrap_t    *marpaESLIFGrammar_bootstrapp;
  marpaESLIF_readerContext_t        marpaESLIF_readerContext;
  int                               grammari;
  marpaESLIF_grammar_t             *grammarp;
  genericStack_t                   *symbolStackp;
  int                               symboli;
  marpaESLIF_symbol_t              *symbolp;
  marpaESLIF_meta_t                *metap;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarOptionp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "marpaESLIFGrammarOptionp must be set");
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarOptionp->bytep == NULL)) {
    /* Only bootstrap can do that */
    if (! bootstrapb) {
      MARPAESLIF_ERRORF(marpaESLIFp, funcs, "Null source pointer");
      goto err;
    }
  }

  marpaESLIFGrammarp = (marpaESLIFGrammar_t *) malloc(sizeof(marpaESLIFGrammar_t));
  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  marpaESLIFGrammarp->marpaESLIFp                               = marpaESLIFp;
  marpaESLIFGrammarp->marpaESLIFGrammarOption                   = *marpaESLIFGrammarOptionp;
  marpaESLIFGrammarp->grammarStackp                             = NULL;
  marpaESLIFGrammarp->grammarp                                  = NULL;
  marpaESLIFGrammarp->warningIsErrorb                           = 0;
  marpaESLIFGrammarp->warningIsIgnoredb                         = 0;
  marpaESLIFGrammarp->autorankb                                 = 0;
  marpaESLIFGrammarp->luabytep                                  = NULL;
  marpaESLIFGrammarp->luabytel                                  = 0;
  marpaESLIFGrammarp->luaprecompiledp                           = NULL;
  marpaESLIFGrammarp->luaprecompiledl                           = 0;
  marpaESLIFGrammarp->luadescp                                  = NULL;
  marpaESLIFGrammarp->internalRuleCounti                        = 0;
  marpaESLIFGrammarp->hasPseudoTerminalb                        = 0;
  marpaESLIFGrammarp->hasEofPseudoTerminalb                     = 0;
  marpaESLIFGrammarp->hasEolPseudoTerminalb                     = 0;
  marpaESLIFGrammarp->hasSolPseudoTerminalb                     = 0;
  marpaESLIFGrammarp->hasEmptyPseudoTerminalb                   = 0;
  marpaESLIFGrammarp->lexemeGrammarHashp                        = NULL;
  marpaESLIFGrammarp->hasLookaheadMetab                         = 0;
  marpaESLIFGrammarp->jsonStringp                               = NULL;
  marpaESLIFGrammarp->jsonConstantOrNumberp                     = NULL;
  marpaESLIFGrammarp->_Lshare.L                                 = NULL;
  marpaESLIFGrammarp->_Lshare.marpaESLIFRecognizerUnsharedTopp  = NULL;
  marpaESLIFGrammarp->_Lshare.marpaESLIFRecognizerLastInjectedp = NULL;
  marpaESLIFGrammarp->_Lshare.marpaESLIFValueLastInjectedp      = NULL;
  marpaESLIFGrammarp->Lsharep                                   = (Lsharep != NULL) ? Lsharep : &(marpaESLIFGrammarp->_Lshare);
  marpaESLIFGrammarp->marpaESLIFGrammar_bootstrapp              = NULL;

  /* bootstrap is special - it just need the structure */
  if (bootstrapb) {
    goto done;
  }

  /* Do we have a parent bootstrap ? This can happen only when we process a generator action */
  marpaESLIFGrammar_bootstrapp = marpaESLIFGrammarp->marpaESLIFGrammar_bootstrapp =
    (marpaESLIFGrammar_bootstrapOrigp == NULL)
    ? _marpaESLIFGrammar_bootstrap_newp(marpaESLIFp)
    : _marpaESLIFGrammar_bootstrap_clonep(marpaESLIFp, marpaESLIFGrammar_bootstrapOrigp);
  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp->marpaESLIFGrammar_bootstrapp == NULL)) {
    goto err;
  }
  
  /* Our internal grammar reader callback */
  marpaESLIF_readerContext.marpaESLIFp              = marpaESLIFp;
  marpaESLIF_readerContext.marpaESLIFGrammarOptionp = marpaESLIFGrammarOptionp;

  /* Overwrite things not setted in the template, or with which we want a change */
  marpaESLIFRecognizerOption.userDatavp        = (void *) &marpaESLIF_readerContext;
  marpaESLIFRecognizerOption.readerCallbackp   = _marpaESLIFReader_grammarReader;
  marpaESLIFRecognizerOption.disableThresholdb = 1; /* No threshold warning when parsing a grammar */
  marpaESLIFRecognizerOption.newlineb          = 1; /* Grammars are short - we can count line/columns numbers */
  marpaESLIFRecognizerOption.trackb            = 0; /* Track absolute position - recognizer is never accessible at this stage */

  marpaESLIFValueOption.userDatavp            = (void *) marpaESLIFGrammar_bootstrapp; /* Result bootstrap grammar is here */
  marpaESLIFValueOption.ruleActionResolverp   = _marpaESLIF_bootstrap_ruleActionResolver;
  marpaESLIFValueOption.symbolActionResolverp = NULL; /* We use ::transfer */

  /* Parser will automatically create marpaESLIFValuep and assign an internal recognizer to its userDatavp */
  /* The value of our internal parser is in marpaESLIFGrammarBootstrapp */
  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFp->marpaESLIFGrammarp, 0 /* leveli */, NULL /* descp */);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFGrammar_parseb(marpaESLIFp,
                                                      grammarp,
                                                      &marpaESLIFRecognizerOption,
                                                      &marpaESLIFValueOption,
                                                      0, /* discardb */
                                                      1, /* noEventb - no effect anyway since our internal grammar have no event indeed -; */
                                                      0, /* silentb */
                                                      NULL, /* marpaESLIFRecognizerParentp */
                                                      NULL, /* isExhaustedbp */
                                                      NULL, /* marpaESLIFValueResultp */
                                                      0, /* maxStartCompletionsi */
                                                      NULL, /* lastSizeBeforeCompletionlp */
                                                      NULL /* numberOfStartCompletionsip */,
                                                      0, /* verboseb */
                                                      NULL, /* matchedLengthlp */
                                                      0 /* isLexemeb */))) {
    goto err;
  }

  /* The result is directly stored in the context - convert it to non-bootstrap structures */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFGrammar_bootstrap_transferb(marpaESLIFp, marpaESLIFGrammarp))) {
    goto err;
  }

  /* Validate the grammar */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFGrammar_validateb(marpaESLIFGrammarp, 0 /* ignoreLazyb */, forcedStartSymbols, forcedStartSymbolLeveli))) {
    goto err;
  }
  /* Put in current grammar the first from the grammar stack */
  for (grammari = 0; grammari < GENERICSTACK_USED(marpaESLIFGrammarp->grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(marpaESLIFGrammarp->grammarStackp, grammari)) {
      /* Sparse array -; */
      continue;
    }
    marpaESLIFGrammarp->grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(marpaESLIFGrammarp->grammarStackp, grammari);
    break;
  }

  /* Initialize external lexeme hash */
  marpaESLIFGrammarp->lexemeGrammarHashp = &(marpaESLIFGrammarp->_lexemeGrammarHash);
  GENERICHASH_INIT_ALL(marpaESLIFGrammarp->lexemeGrammarHashp,
                       _marpaESLIF_string_hash_callbacki,
                       _marpaESLIF_string_cmp_callbackb,
                       NULL, /* keyCopyFunctionp */
                       _marpaESLIF_string_free_callbackv,
                       NULL, /* valCopyFunctionp */
                       _lexemeGrammarHash_free_callbackv,
                       MARPAESLIF_HASH_SIZE,
                       0 /* wantedSubSize */);
  if (MARPAESLIF_UNLIKELY(GENERICHASH_ERROR(marpaESLIFGrammarp->lexemeGrammarHashp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "lexemeGrammarHashp init failure, %s", strerror(errno));
    marpaESLIFGrammarp->lexemeGrammarHashp = NULL;
    goto err;
  }

  /* Success. We have to take care of one thing: the new grammar maintains a pointer to its parent's ESLIF */
  marpaESLIFGrammarp->marpaESLIFp = marpaESLIFp;
  /* This applies to any argument of type marpaESLIFGrammar_t in the grammar */
  for (grammari = 0; grammari < GENERICSTACK_USED(marpaESLIFGrammarp->grammarStackp); grammari++) {
    if (! GENERICSTACK_IS_PTR(marpaESLIFGrammarp->grammarStackp, grammari)) {
      /* Sparse array -; */
      continue;
    }
    grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(marpaESLIFGrammarp->grammarStackp, grammari);
    symbolStackp = grammarp->symbolStackp;
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFp, symbolp, grammarp, symboli);
      if (symbolp->type != MARPAESLIF_SYMBOL_TYPE_META) {
	continue;
      }
      metap = symbolp->u.metap;
      if (metap->marpaESLIFGrammarLexemeClonep != NULL) {
	metap->marpaESLIFGrammarLexemeClonep->marpaESLIFp = marpaESLIFp;
      }
    }
  }

  goto done;

 err:
  /* We do not want to free it, if it was injected: parent should take care of that */
  _marpaESLIFGrammar_freev(marpaESLIFGrammarp, 0 /* onStackb */);
  marpaESLIFGrammarp = NULL;

 done:
  return marpaESLIFGrammarp;
}

/*****************************************************************************/
marpaESLIF_t *marpaESLIFGrammar_eslifp(marpaESLIFGrammar_t *marpaESLIFGrammarp)
/*****************************************************************************/
{
  marpaESLIF_t *marpaESLIFp;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  marpaESLIFp = marpaESLIFGrammarp->marpaESLIFp;
  goto done;

 err:
  marpaESLIFp = NULL;

 done:
  return marpaESLIFp;
}

/*****************************************************************************/
marpaESLIFGrammarOption_t *marpaESLIFGrammar_optionp(marpaESLIFGrammar_t *marpaESLIFGrammarp)
/*****************************************************************************/
{
  marpaESLIFGrammarOption_t *marpaESLIFGrammarOptionp;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  marpaESLIFGrammarOptionp = &(marpaESLIFGrammarp->marpaESLIFGrammarOption);
  goto done;

 err:
  marpaESLIFGrammarOptionp = NULL;

 done:
  return marpaESLIFGrammarOptionp;
}

/*****************************************************************************/
short marpaESLIFGrammar_grammar_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int *levelip, marpaESLIFString_t **descpp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;

  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_grammar_by_levelb(marpaESLIFGrammarp, grammarp->leveli, NULL /* descp */, levelip, descpp);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_grammar_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int leveli, marpaESLIFString_t *descp, int *levelip, marpaESLIFString_t **descpp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (levelip != NULL) {
    *levelip = grammarp->leveli;
  }
  if (descpp != NULL) {
    *descpp = grammarp->descp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_rulearray_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int **ruleipp, size_t *rulelp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;

  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_rulearray_by_levelb(marpaESLIFGrammarp, ruleipp, rulelp, grammarp->leveli, NULL /* descp */);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_rulearray_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int **ruleipp, size_t *rulelp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (ruleipp != NULL) {
    *ruleipp = grammarp->ruleip;
  }
  if (rulelp != NULL) {
    *rulelp = grammarp->nrulel;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_symbolarray_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int **symbolipp, size_t *symbollp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;

  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_symbolarray_by_levelb(marpaESLIFGrammarp, symbolipp, symbollp, grammarp->leveli, NULL /* descp */);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_symbolarray_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int **symbolipp, size_t *symbollp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (symbolipp != NULL) {
    *symbolipp = grammarp->symbolip;
  }
  if (symbollp != NULL) {
    *symbollp = grammarp->nsymboll;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_grammarproperty_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFGrammarProperty_t *grammarPropertyp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;

  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_grammarproperty_by_levelb(marpaESLIFGrammarp, grammarPropertyp, grammarp->leveli, NULL);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_grammarproperty_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFGrammarProperty_t *grammarPropertyp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  genericStack_t       *grammarStackp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }
  grammarStackp = marpaESLIFGrammarp->grammarStackp;
 
  if (grammarPropertyp != NULL) {
    grammarPropertyp->leveli                  = grammarp->leveli;
    grammarPropertyp->maxLeveli               = GENERICSTACK_USED(grammarStackp) - 1; /* Per def it is > 0 here */
    grammarPropertyp->descp                   = grammarp->descp;
    grammarPropertyp->latmb                   = grammarp->latmb;
    grammarPropertyp->discardIsFallbackb      = grammarp->discardIsFallbackb;
    grammarPropertyp->defaultSymbolActionp    = grammarp->defaultSymbolActionp;
    grammarPropertyp->defaultRuleActionp      = grammarp->defaultRuleActionp;
    grammarPropertyp->defaultEventActionp     = grammarp->defaultEventActionp;
    grammarPropertyp->defaultRegexActionp     = grammarp->defaultRegexActionp;
    grammarPropertyp->starti                  = grammarp->starti;
    grammarPropertyp->discardi                = grammarp->discardi;
    grammarPropertyp->nrulel                  = grammarp->nrulel;
    grammarPropertyp->ruleip                  = grammarp->ruleip;
    grammarPropertyp->nsymboll                = grammarp->nsymboll;
    grammarPropertyp->symbolip                = grammarp->symbolip;
    grammarPropertyp->defaultEncodings        = grammarp->defaultEncodings;
    grammarPropertyp->fallbackEncodings       = grammarp->fallbackEncodings;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_ruleproperty_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int rulei, marpaESLIFRuleProperty_t *rulePropertyp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_ruleproperty_by_levelb(marpaESLIFGrammarp, rulei, rulePropertyp, grammarp->leveli, NULL /* descp */);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_ruleproperty_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int rulei, marpaESLIFRuleProperty_t *rulePropertyp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  marpaESLIF_rule_t    *rulep;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rulep = _marpaESLIF_rule_findp(marpaESLIFGrammarp->marpaESLIFp, grammarp, rulei);
  if (MARPAESLIF_UNLIKELY(rulep == NULL)) {
    errno = EINVAL;
    goto err;
  }
 
  if (rulePropertyp != NULL) {
    rulePropertyp->idi            = rulep->idi;
    rulePropertyp->descp          = rulep->descp;
    rulePropertyp->asciishows     = rulep->asciishows;
    rulePropertyp->lhsi           = rulep->lhsp->idi;    /* rulep->lhsp is never NULL */
    rulePropertyp->separatori     = (rulep->separatorp != NULL) ? rulep->separatorp->idi : -1;
    rulePropertyp->nrhsl          = rulep->nrhsl;
    rulePropertyp->rhsip          = rulep->rhsip;  /* Can be NULL if nullable */
    rulePropertyp->skipbp         = rulep->skipbp;  /* Can be NULL if nullable or a sequence */
    rulePropertyp->exceptioni     = (rulep->exceptionp != NULL) ? rulep->exceptionp->idi : -1;
    rulePropertyp->actionp        = rulep->actionp; /* Can be NULL */
    rulePropertyp->discardEvents  = rulep->discardEvents; /* Can be NULL */
    rulePropertyp->discardEventb  = rulep->discardEventb;
    rulePropertyp->ranki          = rulep->ranki;
    rulePropertyp->nullRanksHighb = rulep->nullRanksHighb;
    rulePropertyp->sequenceb      = rulep->sequenceb;
    rulePropertyp->properb        = rulep->properb;
    rulePropertyp->minimumi       = rulep->minimumi;

    /* I could have copied rulep->propertyBitSet directly, though I believe the code is more maintanable */
    /* and extensible doing that bit per bit. */
    rulePropertyp->propertyBitSet = 0;
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_ACCESSIBLE) == MARPAWRAPPER_RULE_IS_ACCESSIBLE) { rulePropertyp->propertyBitSet |= MARPAESLIF_RULE_IS_ACCESSIBLE; }
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_NULLABLE)   == MARPAWRAPPER_RULE_IS_NULLABLE  ) { rulePropertyp->propertyBitSet |= MARPAESLIF_RULE_IS_NULLABLE; }
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_NULLING)    == MARPAWRAPPER_RULE_IS_NULLING   ) { rulePropertyp->propertyBitSet |= MARPAESLIF_RULE_IS_NULLING; }
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_LOOP)       == MARPAWRAPPER_RULE_IS_LOOP      ) { rulePropertyp->propertyBitSet |= MARPAESLIF_RULE_IS_LOOP; }
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_PRODUCTIVE) == MARPAWRAPPER_RULE_IS_PRODUCTIVE) { rulePropertyp->propertyBitSet |= MARPAESLIF_RULE_IS_PRODUCTIVE; }
    rulePropertyp->hideseparatorb = rulep->hideseparatorb;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_ruledisplayform_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int rulei, char **ruledisplaysp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_ruledisplayform_by_levelb(marpaESLIFGrammarp, rulei, ruledisplaysp, grammarp->leveli, NULL /* descp */);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_ruledisplayform_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int rulei, char **ruledisplaysp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  marpaESLIF_rule_t    *rulep;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rulep = _marpaESLIF_rule_findp(marpaESLIFGrammarp->marpaESLIFp, grammarp, rulei);
  if (MARPAESLIF_UNLIKELY(rulep == NULL)) {
    errno = EINVAL;
    goto err;
  }
 
  if (ruledisplaysp != NULL) {
    *ruledisplaysp = rulep->descp->asciis;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_grammarshowform_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, char **grammarshowsp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_grammarshowform_by_levelb(marpaESLIFGrammarp, grammarshowsp, grammarp->leveli, NULL /* descp */);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_grammarshowform_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, char **grammarshowsp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;
  size_t                asciishowl;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }
 
  if (grammarshowsp != NULL) {
    /* Grammar show is delayed until requested because it have a cost -; */
    if (grammarp->asciishows == NULL) {
      _marpaESLIF_grammar_createshowv(marpaESLIFGrammarp, grammarp, NULL /* asciishows */, &asciishowl);
      grammarp->asciishows = (char *) malloc(asciishowl);
      if (MARPAESLIF_UNLIKELY(grammarp->asciishows == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFGrammarp->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      /* It is guaranteed that asciishowl is >= 1 - c.f. _marpaESLIF_grammar_createshowv() */
      grammarp->asciishows[0] = '\0';
      _marpaESLIF_grammar_createshowv(marpaESLIFGrammarp, grammarp, grammarp->asciishows, NULL);
    }
    *grammarshowsp = grammarp->asciishows;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_grammarshowscriptb(marpaESLIFGrammar_t *marpaESLIFGrammarp, char **grammarscriptsp)
/*****************************************************************************/
{
  char *grammarscripts;
  short rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }
  
  if ((marpaESLIFGrammarp->luadescp == NULL) && (marpaESLIFGrammarp->luabytep != NULL) && (marpaESLIFGrammarp->luabytel > 0)) {
    marpaESLIFGrammarp->luadescp = _marpaESLIF_string_newp(marpaESLIFGrammarp->marpaESLIFp, (char *) MARPAESLIF_UTF8_STRING /* Came from the grammar, we know it is UTF-8 */, marpaESLIFGrammarp->luabytep, marpaESLIFGrammarp->luabytel);
    if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp->luadescp == NULL)) {
      goto err;
    }
    grammarscripts = marpaESLIFGrammarp->luadescp->asciis;
  } else {
    grammarscripts = (char *) MARPAESLIF_EMPTY_STRING;
  }

  if (grammarscriptsp != NULL) {
    *grammarscriptsp = grammarscripts;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_ruleshowform_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int rulei, char **ruleshowsp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_ruleshowform_by_levelb(marpaESLIFGrammarp, rulei, ruleshowsp, grammarp->leveli, NULL /* descp */);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_ruleshowform_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int rulei, char **ruleshowsp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  marpaESLIF_rule_t    *rulep;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rulep = _marpaESLIF_rule_findp(marpaESLIFGrammarp->marpaESLIFp, grammarp, rulei);
  if (MARPAESLIF_UNLIKELY(rulep == NULL)) {
    errno = EINVAL;
    goto err;
  }
 
  if (ruleshowsp != NULL) {
    *ruleshowsp = rulep->asciishows;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_symboldisplayform_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int symboli, char **symboldisplaysp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_symboldisplayform_by_levelb(marpaESLIFGrammarp, symboli, symboldisplaysp, grammarp->leveli, NULL /* descp */);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_symboldisplayform_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int symboli, char **symboldisplaysp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  marpaESLIF_symbol_t  *symbolp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL) || MARPAESLIF_UNLIKELY(symboli < 0)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  symbolp = _marpaESLIF_symbol_findp(marpaESLIFGrammarp->marpaESLIFp, grammarp, NULL /* asciis */, symboli, NULL /* symbolip */, 0 /* silentb */, 0 /* onlyLhsb - NOT USED */, 0 /* onlyRhsb - NOT USED */, MARPAESLIF_SYMBOL_TYPE_NA /* NOT USED */);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    errno = EINVAL;
    goto err;
  }
 
  if (symboldisplaysp != NULL) {
    *symboldisplaysp = symbolp->descp->asciis;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_symbolproperty_currentb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int symboli, marpaESLIFSymbolProperty_t *marpaESLIFSymbolPropertyp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = marpaESLIFGrammarp->grammarp;

  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  rcb = marpaESLIFGrammar_symbolproperty_by_levelb(marpaESLIFGrammarp, symboli, marpaESLIFSymbolPropertyp, grammarp->leveli, NULL /* descp */);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_symbolproperty_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, int symboli, marpaESLIFSymbolProperty_t *marpaESLIFSymbolPropertyp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t       *grammarp;
  marpaESLIF_symbol_t        *symbolp;
  marpaESLIFSymbolProperty_t  marpaESLIFSymbolProperty;
  short                       rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL) || MARPAESLIF_UNLIKELY(symboli < 0)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  symbolp = _marpaESLIF_symbol_findp(marpaESLIFGrammarp->marpaESLIFp, grammarp, NULL /* asciis */, symboli, NULL /* symbolip */, 0 /* silentb */, 0 /* onlyLhsb - NOT USED */, 0 /* onlyRhsb - NOT USED */, MARPAESLIF_SYMBOL_TYPE_NA /* NOT USED */);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  switch (symbolp->type) {
  case MARPAESLIF_SYMBOL_TYPE_TERMINAL:
    marpaESLIFSymbolProperty.type = MARPAESLIF_SYMBOLTYPE_TERMINAL;
    break;
  case MARPAESLIF_SYMBOL_TYPE_META:
    marpaESLIFSymbolProperty.type = MARPAESLIF_SYMBOLTYPE_META;
    break;
  default:
    MARPAESLIF_ERRORF(marpaESLIFGrammarp->marpaESLIFp, "Unsupported symbol type %d", symbolp->type);
    goto err;
  }
  marpaESLIFSymbolProperty.startb               = symbolp->startb;
  marpaESLIFSymbolProperty.discardb             = symbolp->discardb;
  marpaESLIFSymbolProperty.discardRhsb          = symbolp->discardRhsb;
  marpaESLIFSymbolProperty.lhsb                 = symbolp->lhsb;
  marpaESLIFSymbolProperty.topb                 = symbolp->topb;
  marpaESLIFSymbolProperty.idi                  = symbolp->idi;
  marpaESLIFSymbolProperty.descp                = symbolp->descp;
  marpaESLIFSymbolProperty.eventBefores         = symbolp->eventBefores;
  marpaESLIFSymbolProperty.eventBeforeb         = symbolp->eventBeforeb;
  marpaESLIFSymbolProperty.eventAfters          = symbolp->eventAfters;
  marpaESLIFSymbolProperty.eventAfterb          = symbolp->eventAfterb;
  marpaESLIFSymbolProperty.eventPredicteds      = symbolp->eventPredicteds;
  marpaESLIFSymbolProperty.eventPredictedb      = symbolp->eventPredictedb;
  marpaESLIFSymbolProperty.eventNulleds         = symbolp->eventNulleds;
  marpaESLIFSymbolProperty.eventNulledb         = symbolp->eventNulledb;
  marpaESLIFSymbolProperty.eventCompleteds      = symbolp->eventCompleteds;
  marpaESLIFSymbolProperty.eventCompletedb      = symbolp->eventCompletedb;
  marpaESLIFSymbolProperty.discardEvents        = symbolp->discardEvents;
  marpaESLIFSymbolProperty.discardEventb        = symbolp->discardEventb;
  marpaESLIFSymbolProperty.lookupResolvedLeveli = symbolp->lookupResolvedLeveli;
  marpaESLIFSymbolProperty.priorityi            = symbolp->priorityi;
  marpaESLIFSymbolProperty.nullableActionp      = symbolp->nullableActionp;
  marpaESLIFSymbolProperty.symbolActionp        = symbolp->symbolActionp;
  marpaESLIFSymbolProperty.ifActionp            = symbolp->ifActionp;
  marpaESLIFSymbolProperty.generatorActionp     = symbolp->generatorActionp;
  marpaESLIFSymbolProperty.verboseb             = symbolp->verboseb;
  /* I could have copied symbolp->propertyBitSet directly, though I believe the code is more maintanable */
  /* and extensible doing that bit per bit. */
  marpaESLIFSymbolProperty.propertyBitSet = 0;
  if ((symbolp->propertyBitSet & MARPAESLIF_SYMBOL_IS_ACCESSIBLE) == MARPAESLIF_SYMBOL_IS_ACCESSIBLE) { marpaESLIFSymbolProperty.propertyBitSet |= MARPAESLIF_SYMBOL_IS_ACCESSIBLE; }
  if ((symbolp->propertyBitSet & MARPAESLIF_SYMBOL_IS_NULLABLE)   == MARPAESLIF_SYMBOL_IS_NULLABLE  ) { marpaESLIFSymbolProperty.propertyBitSet |= MARPAESLIF_SYMBOL_IS_NULLABLE; }
  if ((symbolp->propertyBitSet & MARPAESLIF_SYMBOL_IS_NULLING)    == MARPAESLIF_SYMBOL_IS_NULLING   ) { marpaESLIFSymbolProperty.propertyBitSet |= MARPAESLIF_SYMBOL_IS_NULLING; }
  if ((symbolp->propertyBitSet & MARPAESLIF_SYMBOL_IS_PRODUCTIVE) == MARPAESLIF_SYMBOL_IS_PRODUCTIVE) { marpaESLIFSymbolProperty.propertyBitSet |= MARPAESLIF_SYMBOL_IS_PRODUCTIVE; }
  if ((symbolp->propertyBitSet & MARPAESLIF_SYMBOL_IS_START)      == MARPAESLIF_SYMBOL_IS_START)      { marpaESLIFSymbolProperty.propertyBitSet |= MARPAESLIF_SYMBOL_IS_START; }
  if ((symbolp->propertyBitSet & MARPAESLIF_SYMBOL_IS_TERMINAL)   == MARPAESLIF_SYMBOL_IS_TERMINAL)   { marpaESLIFSymbolProperty.propertyBitSet |= MARPAESLIF_SYMBOL_IS_TERMINAL; }
  marpaESLIFSymbolProperty.eventBitSet = 0;
  if ((symbolp->eventBitSet & MARPAESLIF_SYMBOL_EVENT_COMPLETION) == MARPAESLIF_SYMBOL_EVENT_COMPLETION) { marpaESLIFSymbolProperty.eventBitSet |= MARPAESLIF_SYMBOL_EVENT_COMPLETION; }
  if ((symbolp->eventBitSet & MARPAESLIF_SYMBOL_EVENT_NULLED) == MARPAESLIF_SYMBOL_EVENT_NULLED)         { marpaESLIFSymbolProperty.eventBitSet |= MARPAESLIF_SYMBOL_EVENT_NULLED; }
  if ((symbolp->eventBitSet & MARPAESLIF_SYMBOL_EVENT_PREDICTION) == MARPAESLIF_SYMBOL_EVENT_PREDICTION) { marpaESLIFSymbolProperty.eventBitSet |= MARPAESLIF_SYMBOL_EVENT_PREDICTION; }

  if (marpaESLIFSymbolPropertyp != NULL) {
    *marpaESLIFSymbolPropertyp = marpaESLIFSymbolProperty;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline marpaESLIFRecognizer_t *_marpaESLIFRecognizer_newp(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp, short discardb, short noEventb, short silentb)
/*****************************************************************************/
{
  return __marpaESLIFRecognizer_newp(marpaESLIFp,
                                     grammarp,
                                     marpaESLIFRecognizerOptionp,
                                     discardb,
                                     noEventb,
                                     silentb,
                                     NULL, /* marpaESLIFRecognizerParentp */
                                     0, /* fakeb */
                                     0 /* maxStartCompletionsi */,
                                     0, /* utfb */
                                     0 /* isLexemeb */);
}

/*****************************************************************************/
marpaESLIFRecognizer_t *marpaESLIFRecognizer_newp(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    return NULL;
  }

  return _marpaESLIFRecognizer_newp(marpaESLIFGrammarp->marpaESLIFp, marpaESLIFGrammarp->grammarp, marpaESLIFRecognizerOptionp, 0 /* discardb */, 0 /* noEventb */, 0 /* silentb */);
}

/*****************************************************************************/
short marpaESLIFRecognizer_shareb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFRecognizer_t *marpaESLIFRecognizerSharedp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_shareb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == marpaESLIFRecognizerSharedp)) {
    errno = EINVAL;
    goto err;
  }

  if (! _marpaESLIFRecognizer_shareb(marpaESLIFRecognizerp, marpaESLIFRecognizerSharedp)) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_peekb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFRecognizer_t *marpaESLIFRecognizerPeekedp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_peekb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    goto err;
  }

  rcb = _marpaESLIFRecognizer_peekb(marpaESLIFRecognizerp, marpaESLIFRecognizerPeekedp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
marpaESLIF_t *marpaESLIFRecognizer_eslifp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_eslifp";
  marpaESLIF_t      *marpaESLIFp;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    marpaESLIFp = NULL;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIFp = marpaESLIFRecognizerp->marpaESLIFp;
  goto done;

 err:
  marpaESLIFp = NULL;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %p", marpaESLIFp);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return marpaESLIFp;
}

/*****************************************************************************/
short marpaESLIFRecognizer_scanb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short initialEventsb, short *continuebp, short *isExhaustedbp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_scanb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_scanb(marpaESLIFRecognizerp, initialEventsb, continuebp, isExhaustedbp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short _marpaESLIFRecognizer_resumeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t deltaLengthl, short *continuebp, short *isExhaustedbp)
/*****************************************************************************/
{
  return __marpaESLIFRecognizer_resumeb(marpaESLIFRecognizerp, deltaLengthl, 0 /* initialEventsb */, continuebp, isExhaustedbp);
}

/*****************************************************************************/
short marpaESLIFRecognizer_resumeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t deltaLengthl, short *continuebp, short *isExhaustedbp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_resumeb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  /* This is tricky, for log-analysis, we want resume to look as if the caller did not called us    */
  /* e.g. as if we were always in the classic no-event parse() mode. But in the parse() mode, there */
  /* is one callstack more:                                                                         */
  /* parse() -> _scan() -> _resume() -> _resume_oneb()                                              */
  /* If we are here, without incrementing twice the callstack, we would have:                       */
  /* resume() -> _resume() -> _resume_oneb()                                                        */

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_resumeb(marpaESLIFRecognizerp, deltaLengthl, continuebp, isExhaustedbp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short __marpaESLIFRecognizer_resumeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t deltaLengthl, short initialEventsb, short *canContinuebp, short *isExhaustedbp)
/*****************************************************************************/
{
  static const char                    *funcs                   = "__marpaESLIFRecognizer_resumeb";
  marpaESLIF_stream_t                  *marpaESLIF_streamp      = marpaESLIFRecognizerp->marpaESLIF_streamp;
  marpaESLIF_grammar_t                 *grammarp                = marpaESLIFRecognizerp->grammarp;
  genericStack_t                       *alternativeStackSymbolp = marpaESLIFRecognizerp->alternativeStackSymbolp;
  marpaESLIFRecognizerEventCallback_t   eventCallbackp;
  short                                 canContinueb;
  short                                 isExhaustedb;
  short                                 rcb;
  marpaESLIFValueResultBool_t           marpaESLIFValueResultBool;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Checks */
  if (! marpaESLIFRecognizerp->scanb) {
    /* We allow scan/resume to not have been called only if the recognizer is not pristine */
    if (marpaESLIFRecognizerp->pristineb) {
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Scan must be called first");
      goto err;
    }
  }

  if (MARPAESLIF_UNLIKELY(! grammarp->latmb)) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Grammar No %d (%s) must be in LATM mode", grammarp->leveli, grammarp->descp->asciis);
    goto err;
  }

  /* Top level resume is looping on _marpaESLIFRecognizer_resume_oneb() until:
     - failure
     - event
  */

  /* Eventually read until the delta offset is available */
  if (deltaLengthl > 0) {
    while (deltaLengthl > marpaESLIF_streamp->inputl) {
      if (MARPAESLIF_LIKELY(! marpaESLIF_streamp->eofb)) {
        if (MARPAESLIF_UNLIKELY(! __marpaESLIFRecognizer_readb(marpaESLIFRecognizerp))) {
          goto err;
        }
      } else {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Resume delta offset %ld must be <= current remaining bytes in recognizer buffer, currently %ld", (unsigned long) deltaLengthl, (unsigned long) marpaESLIF_streamp->inputl);
        goto err;
      }
    }
    /* If there is newline in the skipped data, we should account for it for debug/trace purposes... */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_matchPostProcessingb(marpaESLIFRecognizerp, deltaLengthl))) {
      goto err;
    }
  }

  do {
    rcb = _marpaESLIFRecognizer_resume_oneb(marpaESLIFRecognizerp, grammarp, alternativeStackSymbolp, marpaESLIF_streamp, initialEventsb, &canContinueb, &isExhaustedb);
    if (MARPAESLIF_UNLIKELY(! rcb)) {
      goto err;
    }
    /* Makes sure initialEvents is true once only - testing initialEventsb is not necessary. */
    initialEventsb = 0;

    if (marpaESLIFRecognizerp->eventArrayl > 0) {
      /* If grammar has an event-action, check it */
      if (grammarp->defaultEventActionp != NULL) {
        /* Do as if user would have called marpaESLIFRecognizer_eventb */
        if (MARPAESLIF_UNLIKELY(! marpaESLIFRecognizer_eventb(marpaESLIFRecognizerp, NULL /* eventArraylp */, NULL /* eventArraypp */))) {
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_recognizerEventActionCallbackb(marpaESLIFRecognizerp, grammarp->defaultEventActionp, &eventCallbackp))) {
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(! eventCallbackp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, marpaESLIFRecognizerp, marpaESLIFRecognizerp->eventArrayp, marpaESLIFRecognizerp->eventArrayl, &marpaESLIFValueResultBool))) {
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultBool == MARPAESLIFVALUERESULTBOOL_FALSE)) {
          /* The event callback failed */
          MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Event callback failure");
          goto err;
        }
      }
      break;
    }
  } while (canContinueb);

  if (canContinuebp != NULL) {
    *canContinuebp = canContinueb;
  }
  if (isExhaustedbp != NULL) {
    *isExhaustedbp = isExhaustedb;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_alternativeStack_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, genericStack_t *alternativeStackSymbolp)
/*****************************************************************************/
{
  static const char        *funcs           = "_marpaESLIFRecognizer_alternativeStack_freev";
  int                       i;
  marpaESLIF_alternative_t *alternativep;

  if (alternativeStackSymbolp != NULL) {

    MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

    for (i = 0; i < GENERICSTACK_USED(alternativeStackSymbolp); i++) {
      if (GENERICSTACK_IS_PTR(alternativeStackSymbolp, i)) {
        alternativep = (marpaESLIF_alternative_t *) GENERICSTACK_GET_PTR(alternativeStackSymbolp, i);
        if (alternativep != NULL) {
          _marpaESLIFRecognizer_internalStack_i_setb(marpaESLIFRecognizerp,
						     NULL, /* valueResultStackp */
						     -1, /* indicei */
						     (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef,
						     0, /* forgetb */
						     &(alternativep->marpaESLIFValueResult));
          free(alternativep);
        }
      }
    }

    GENERICSTACK_RESET(alternativeStackSymbolp); /* Take care, alternativeStackSymbolp is a pointer to a static stack in recognizer's structure */

    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "return");
    MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  }
}

/*****************************************************************************/
static inline marpaESLIF_alternative_t *_marpaESLIFRecognizer_alternativeStack_getp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, genericStack_t *alternativeStackSymbolp, int indicei)
/*****************************************************************************/
/* This method is called ONLY by _marpaESLIFRecognizer_resume_oneb().        */
/*****************************************************************************/
{
  static const char        *funcs = "_marpaESLIFRecognizer_alternativeStack_getp";
  marpaESLIF_alternative_t *rcp; /* It is guaranteed that p is set whatever happens - see below */
  short                     rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start, indicei=%d", indicei);

  if (GENERICSTACK_IS_PTR(alternativeStackSymbolp, indicei)) {
    rcp = (marpaESLIF_alternative_t *) GENERICSTACK_GET_PTR(alternativeStackSymbolp, indicei);
    _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, &(rcp->marpaESLIFValueResult), 1 /* deepb */);
  } else {
    rcp = (marpaESLIF_alternative_t *) malloc(sizeof(marpaESLIF_alternative_t));
    if (MARPAESLIF_UNLIKELY(rcp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    GENERICSTACK_SET_PTR(alternativeStackSymbolp, rcp, indicei);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(alternativeStackSymbolp))) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "alternativeStackSymbolp set failure, %s", strerror(errno));
      goto err;
    }
  }

  if (marpaESLIFRecognizerp->marpaESLIFp->NULLisZeroBytesb && marpaESLIFRecognizerp->marpaESLIFp->ZeroIntegerisZeroBytesb) {
    /* It is not a hasard that marpaESLIFValueResultUndef is defined only with 0 or NULL ;) */
    memset((void *) rcp, 0, sizeof(marpaESLIF_alternative_t));
  } else {
    rcp->symbolp               = NULL;
    rcp->marpaESLIFValueResult = marpaESLIFValueResultUndef;
    rcp->grammarLengthi        = 0;
    rcp->usedb                 = 0;
    rcp->matchedLengthl        = 0;
  }

  goto done;

 err:
  if (rcp != NULL) {
    free(rcp);
  }
  rcp = NULL;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %p", rcp);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcp;
}

/*****************************************************************************/
static inline short __marpaESLIFRecognizer_isZeroLengthLexemeExpectedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isZeroLengthLexemeExpectedbp)
/*****************************************************************************/
{
  static const char        *funcs                        = "__marpaESLIFRecognizer_isZeroLengthLexemeExpectedb";
  marpaESLIF_t             *marpaESLIFp                  = marpaESLIFRecognizerp->marpaESLIFp;
  short                     isZeroLengthLexemeExpectedb  = 0;
  marpaESLIFRecognizer_t   *marpaESLIFRecognizerMetap    = NULL;
  short                     contextb                     = 0;
  marpaESLIF_grammar_t     *subGrammarp;
  size_t                    nTerminall;
  int                      *symbolIdArrayp;
  marpaESLIF_symbol_t     **symbolArraypp;
  size_t                    symboll;
  marpaESLIF_symbol_t      *symbolp;
  short                     rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Ask for expected TERMINALS */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_expectedTerminalsb(marpaESLIFRecognizerp, &nTerminall, &symbolIdArrayp, &symbolArraypp))) {
    goto err;
  }

  for (symboll = 0; symboll < nTerminall; symboll++) {
    symbolp = symbolArraypp[symboll];

    switch (symbolp->type) {
    case MARPAESLIF_SYMBOL_TYPE_TERMINAL:
      if (MARPAESLIF_IS_PSEUDO_TERMINAL(symbolp)) {
        isZeroLengthLexemeExpectedb = 1;
      }
      break;
    case MARPAESLIF_SYMBOL_TYPE_META:
      if (MARPAESLIF_IS_META_LOOKAHEAD(symbolp)) {
        isZeroLengthLexemeExpectedb = 1;
      } else {
        if (symbolp->parameterizedRhsb) {
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                      funcs,
                                      "Pushing generator context for symbol %s%s%s: %s<->%s",
                                      symbolp->descp->asciis,
                                      symbolp->callp->luaexplistcb ? "-->" : "->",
                                      symbolp->callp->luaexplists,
                                      symbolp->declp != NULL ? symbolp->declp->luaparlists : "nil",
                                      symbolp->callp->luaexplists);
          if (! _marpaESLIF_lua_recognizer_push_contextb(marpaESLIFRecognizerp, symbolp)) {
            goto err;
          }
          contextb = 1;
        }

        subGrammarp = _marpaESLIFRecognizer_meta_subGrammarp(marpaESLIFRecognizerp, symbolp);
        if (MARPAESLIF_UNLIKELY(subGrammarp == NULL)) {
          goto err;
        }

        marpaESLIFRecognizerMetap = __marpaESLIFRecognizer_newp(marpaESLIFp,
                                                                subGrammarp,
                                                                NULL, /* marpaESLIFRecognizerOptionp */
                                                                0, /* discardb */
                                                                1, /* noEventb */
                                                                1, /* silentb */
                                                                marpaESLIFRecognizerp, /* marpaESLIFRecognizerParentp */
                                                                0, /* fakeb */
                                                                0, /* maxStartCompletionsi */
                                                                0, /* utfb - not used because inherited from parent*/
                                                                1 /* isLexemeb */);
        if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerMetap == NULL)) {
          goto err;
        }
        
        /* Call ourself recursively - this should be changed to a stack free thingy... */
        if (MARPAESLIF_UNLIKELY(! __marpaESLIFRecognizer_isZeroLengthLexemeExpectedb(marpaESLIFRecognizerMetap, &isZeroLengthLexemeExpectedb))) {
          goto err;
        }

        /* Pop context if we pushed one */
        if (contextb) {
          contextb = 0;
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                      funcs,
                                      "Popping context for symbol %s%s%s: %s<->%s",
                                      symbolp->descp->asciis,
                                      symbolp->callp->luaexplistcb ? "-->" : "->",
                                      symbolp->callp->luaexplists,
                                      symbolp->declp != NULL ? symbolp->declp->luaparlists : "nil",
                                      symbolp->callp->luaexplists);
          if (! _marpaESLIF_lua_recognizer_pop_contextb(marpaESLIFRecognizerp)) {
            goto err;
          }
        }

        _marpaESLIFRecognizer_freev(marpaESLIFRecognizerMetap, 1 /* forceb */);
        marpaESLIFRecognizerMetap = NULL;
      }
      break;
    default:
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Unknown symbol type %d", symbolp->type);
      goto err;
    }

    if (isZeroLengthLexemeExpectedb) {
      break;
    }
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "isZeroLengthLexemeExpectedb=%d", (int) isZeroLengthLexemeExpectedb);
  /* Dangerous to comment that, but we know what we do: this is an internal call, we guarantee that isZeroLengthLexemeExpectedbp is never NULL */
  /* if (isZeroLengthLexemeExpectedbp != NULL) */
  *isZeroLengthLexemeExpectedbp = isZeroLengthLexemeExpectedb;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  if (marpaESLIFRecognizerMetap != NULL) {
    _marpaESLIFRecognizer_freev(marpaESLIFRecognizerMetap, 1 /* forceb */);
  }
  if (contextb) {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                funcs,
                                "Popping context for symbol %s%s%s: %s<->%s",
                                symbolp->descp->asciis,
                                symbolp->callp->luaexplistcb ? "-->" : "->",
                                symbolp->callp->luaexplists,
                                symbolp->declp != NULL ? symbolp->declp->luaparlists : "nil",
                                symbolp->callp->luaexplists);
    if (! _marpaESLIF_lua_recognizer_pop_contextb(marpaESLIFRecognizerp)) {
      rcb = 0;
    }
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_isZeroLengthLexemeExpectedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isZeroLengthLexemeExpectedbp)
/*****************************************************************************/
{
  static const char   *funcs              = "_marpaESLIFRecognizer_isZeroLengthLexemeExpectedb";
  marpaESLIFGrammar_t *marpaESLIFGrammarp = marpaESLIFRecognizerp->grammarp->marpaESLIFGrammarp;
  short                rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* No-op if we know there is no pseudo terminal in the whole grammar */
  if (! (marpaESLIFGrammarp->hasPseudoTerminalb || marpaESLIFGrammarp->hasLookaheadMetab)) {
    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "No pseudo terminal nor lookahead meta anywhere in the grammar");
    /* Dangerous to comment that, but we know what we do: this is an internal call, we guarantee that isZeroLengthLexemeExpectedbp is never NULL */
    /* if (isZeroLengthLexemeExpectedbp != NULL) */
    *isZeroLengthLexemeExpectedbp = 0;
    rcb = 1;
  } else {
    rcb = __marpaESLIFRecognizer_isZeroLengthLexemeExpectedb(marpaESLIFRecognizerp, isZeroLengthLexemeExpectedbp);
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_isDiscardExpectedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isDiscardExpectedbp, size_t *fastDiscardlp, marpaESLIF_symbol_t **fastDiscardSymbolpp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
/* This method allows to prevent a cyle on :discard, this is important       */
/* because a cycle is consuming: this is a whole new parse.                  */
/* It is executed in the context of the current recognizer: when this method */
/* is called it means that the caller wants to discard if possible.          */
/* If the discard is possible and can be executed in the context of the      */
/* caller, this method will take care or that.                               */
/*                                                                           */
/* By construction isDiscardExpectedbp and fastDiscardlp are never NULL.     */
/*****************************************************************************/
{
  static const char          *funcs                               = "_marpaESLIFRecognizer_isDiscardExpectedb";
  short                       isDiscardExpectedb                  = 0;
  short                       fastDiscardb                        = 0;
  size_t                      fastDiscardl                        = 0;
  marpaESLIF_symbol_t        *fastDiscardSymbolp                  = NULL;
  marpaESLIFRecognizer_t     *marpaESLIFRecognizerParentPreviousp = marpaESLIFRecognizerp->marpaESLIFRecognizerParentp;
  marpaESLIF_stream_t        *marpaESLIF_streamp;
  marpaESLIF_grammar_t       *grammarp;
  size_t                      nTerminalPristinel;
  marpaESLIF_symbol_t       **terminalArrayPristinepp;
  size_t                      symboll;
  marpaESLIF_symbol_t        *symbolp;
  marpaESLIF_matcher_value_t  rci;
  marpaESLIFValueResult_t     marpaESLIFValueResult;
  size_t                      discardl;
  short                       rcMatcherb;
  short                       lastMatchedPriorityInitializedb;
  int                         lastMatchedMinPriorityi;
  short                       rcb;
  size_t                      matchedLengthl;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (! marpaESLIFRecognizerp->discardOnOffb) {
    /* :discard is disabled */
    goto fast_done;
  }

  grammarp           = marpaESLIFRecognizerp->grammarp;
  fastDiscardb       = grammarp->fastDiscardb;

  if (grammarp->discardi < 0) {
    /* There is no :discard in the current grammar */
    goto fast_done;
  }

  /* We now simulate what would do _marpaESLIFRecognizer_resume_oneb() at the very beginning. */
  /* We do not forget to also simulate that we should be a child recognizer.                  */
  marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  marpaESLIFRecognizerp->marpaESLIFRecognizerParentp = &invalidFakeMarpaESLIFRecognizer;

  nTerminalPristinel              = grammarp->nTerminalDiscardPristinel;
  terminalArrayPristinepp         = grammarp->terminalArrayDiscardPristinepp;
  lastMatchedPriorityInitializedb = 0;

  for (symboll = 0; symboll < nTerminalPristinel; symboll++) {
    symbolp = terminalArrayPristinepp[symboll];
    if (lastMatchedPriorityInitializedb && (symbolp->priorityi < lastMatchedMinPriorityi)) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                  funcs,
                                  "Skipping other alternatives: current symbol priority is %d < min priority %d",
                                  symbolp->priorityi,
                                  lastMatchedMinPriorityi);
      break;
    }

    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Trying discard terminal: %s", symbolp->descp->asciis);
    rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp,
                                                       marpaESLIF_streamp,
                                                       symbolp,
                                                       &rci,
                                                       &marpaESLIFValueResult,
                                                       0, /* maxStartCompletionsi */
                                                       NULL, /* lastSizeBeforeCompletionlp */
                                                       NULL, /* numberOfStartCompletionsip */
                                                       &matchedLengthl);
    if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
      marpaESLIFRecognizerp->marpaESLIFRecognizerParentp = marpaESLIFRecognizerParentPreviousp;
      goto err;
    }
    if (! rcMatcherb) {
      continue;
    }
    if (rci == MARPAESLIF_MATCH_OK) {
      discardl = matchedLengthl;
      if (marpaESLIFValueResultp != NULL) {
        *marpaESLIFValueResultp = marpaESLIFValueResult;
      } else {
	_marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, &marpaESLIFValueResult, 1 /* deepb */);
      }

      if (! lastMatchedPriorityInitializedb) {
        lastMatchedMinPriorityi = symbolp->priorityi;
        lastMatchedPriorityInitializedb = 1;
      }

      isDiscardExpectedb = 1;
      if (fastDiscardb) {
        /* Continue the loop to see if another terminal matched longer */
        if (discardl > fastDiscardl) {
          fastDiscardl = discardl;
          fastDiscardSymbolp = symbolp;
        }
      } else {
        /* :discard will trigger a call to a sub recognizer. We just wanted to know if it */
        /* worth to do it.                                                                */
        break;
      }
    }   
  }

  marpaESLIFRecognizerp->marpaESLIFRecognizerParentp = marpaESLIFRecognizerParentPreviousp;

 fast_done:
  *isDiscardExpectedbp = isDiscardExpectedb;
  *fastDiscardlp       = fastDiscardl;
  *fastDiscardSymbolpp = fastDiscardSymbolp;
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline size_t _marpaESLIFRecognizer_expectedSymbols_yieldb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short pristineb, size_t *iteratorlp, size_t nTerminall, marpaESLIF_symbol_t **symbolArraypp, marpaESLIF_symbol_t **symbolpp)
/*****************************************************************************/
{
  static const char   *funcs     = "_marpaESLIFRecognizer_expectedTerminals_yieldb";
  size_t               iteratorl = *iteratorlp;
  marpaESLIF_symbol_t *candidatep;
  marpaESLIF_symbol_t *symbolp;
  short                isExpectedb;
  short                rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start, pristineb=%d, iteratorl=%ld, nTerminall=%ld, symbolArraypp=%p", (int) pristineb, (unsigned long) iteratorl, (unsigned long) nTerminall, symbolArraypp);

  if (iteratorl < nTerminall) {
    if (pristineb) {
      /* Pristine: candidates were already filtered with marpaWrapperRecognizer_isExpectedb */
      symbolp = symbolArraypp[iteratorl++];
    } else {
      /* Not pristine: candidates has to pass marpaWrapperRecognizer_isExpectedb */
      symbolp = NULL;
      for (; iteratorl < nTerminall; iteratorl++) {
        candidatep = symbolArraypp[iteratorl];
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "check if expected: iteratorl=%ld, nTerminall=%ld, candidate symbol No %d <%s>, priority=%d", (unsigned long) iteratorl, (unsigned long) nTerminall, candidatep->idi, candidatep->descp->asciis, candidatep->priorityi);
        if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_isExpectedb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, candidatep->idi, &isExpectedb))) {
          goto err;
        }
        if (isExpectedb) {
          symbolp = candidatep;
          iteratorl++;
          break;
        }
      }
    }
  } else {
    symbolp = NULL;
  }

  *symbolpp = symbolp;
  *iteratorlp = iteratorl;
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
#ifndef MARPAESLIF_NTRACE
  if (rcb) {
    if (symbolp != NULL) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d (Symbol No %d <%s>)", (int) rcb, symbolp->idi, symbolp->descp->asciis);
    } else {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d (*symbolpp == NULL)", (int) rcb);
    }
  } else {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  }
#endif
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_resume_oneb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, genericStack_t *alternativeStackSymbolp, marpaESLIF_stream_t *marpaESLIF_streamp, short initialEventsb, short *canContinuebp, short *isExhaustedbp)
/*****************************************************************************/
/* This method is called very very often, therefore any optimization here is welcome. */
/*****************************************************************************/
{
  static const char               *funcs             = "_marpaESLIFRecognizer_resume_oneb";
  int                             *isExpectedArraybp = marpaESLIFRecognizerp->isExpectedArraybp;
  short                            pristineb;
  short                            onlyPredictedLexemesb;
  size_t                           nTerminall;
  marpaESLIF_symbol_t            **symbolpp;
  short                            lastMatchedPriorityInitializedb;
  int                              lastMatchedMinPriorityi;
  size_t                           maxMatchedl;
  int                              alternativeStackSymboli;
  int                              alternativei;
  marpaESLIF_symbol_t             *symbolp;
  marpaESLIF_symbol_t             *exceptionp;
  marpaESLIF_matcher_value_t       rci;
  marpaESLIF_matcher_value_t       exceptionRci;
  short                            rcb;
  size_t                           sizel;
  marpaESLIFValueResult_t         *marpaESLIFValueResultp;
  marpaESLIFValueResult_t          exceptionMarpaESLIFValueResult;
  marpaESLIF_alternative_t        *alternativep;
  int                              numberOfStartCompletionsi;
  int                              numberOfExceptionCompletionsi;
  size_t                           lastSizeBeforeCompletionl;
  int                              symbolMaxStartCompletionsi;
  int                              exceptionMaxStartCompletionsi;
  short                            rcMatcherb;
  short                            canContinueb;
  short                            isExhaustedb;
  size_t                           offsetl;
  size_t                           discardl;
  short                            isPseudoTerminalMatchb;
  short                            isLookupMetaMatchb;
  size_t                           iteratorl;
  size_t                           nAcceptedCandidatel;
  marpaESLIF_symbol_t             *candidatep;
  short                            asciipredictionb;
  short                            utfpredictionb;
  unsigned char                    uc;
  size_t                           matchedLengthl;
  size_t                           exceptionMatchedLengthl;
  int                              utf82ordi;
  marpaESLIF_uint32_t              codepointi;
  short                            singleAsciiCharacterPredictedSuccessb;
  short                            singleUtfCharacterPredictedSuccessb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start, maxStartCompletionsi=%d", marpaESLIFRecognizerp->maxStartCompletionsi);

  /* Initializations */
  MARPAESLIFRECOGNIZER_RESUMECOUNTER_INC(marpaESLIFRecognizerp); /* Increment internal counter for tracing */
  marpaESLIFRecognizerp->completedb = 0;

  /* We always start by resetting and collecting current events */
  _marpaESLIFRecognizer_clear_all_eventsb(marpaESLIFRecognizerp);

  if (! initialEventsb) {
    onlyPredictedLexemesb = 0;
  } else {
    /* We break immediately if there are events and the initialEventsb is set. This can happen once */
    /* only in the whole lifetime of a recognizer. */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_push_grammar_eventsb(marpaESLIFRecognizerp))) {
      goto err;
    }
    /* Ask for predicted lexemes */
    onlyPredictedLexemesb = 1;
  }

  /* Try to match */
 retry:
  iteratorl                       = 0;
  nAcceptedCandidatel             = 0;
  isPseudoTerminalMatchb          = 0;
  isLookupMetaMatchb              = 0;
  alternativeStackSymboli         = 0;
  maxMatchedl                     = 0;
  lastMatchedPriorityInitializedb = 0;
  pristineb                       = marpaESLIFRecognizerp->pristineb;
  if (pristineb) {
    /* Precomputed pristine case */
    symbolpp                        = marpaESLIFRecognizerp->terminalArrayPristinepp;
    nTerminall                      = marpaESLIFRecognizerp->nTerminalPristinel;
  } else {
    /* Next loop will have to check using isExpectedArraybp */
    symbolpp                        = grammarp->symbolArraypp;
    nTerminall                      = grammarp->nTerminall;
  }

  if (marpaESLIF_streamp->inputl > 0) {
    /* ASCII prediction can always happen */
    asciipredictionb = 1;
    uc = (unsigned char) marpaESLIF_streamp->inputs[0];
    /* For UTF-8 we want to make sure we are at eof or there are at least 4 bytes */
    if ((marpaESLIF_streamp->eofb || (marpaESLIF_streamp->inputl >= 4)) && marpaESLIF_streamp->utfb) {
      utf82ordi = _marpaESLIF_utf82ordi((PCRE2_SPTR8) marpaESLIF_streamp->inputs, &codepointi, (PCRE2_SPTR8) (marpaESLIF_streamp->inputs + marpaESLIF_streamp->inputl));
      if (MARPAESLIF_LIKELY(utf82ordi > 0)) {
        /* We support predicted UTF-8 failure only for codepoints < 256 */
        if (codepointi < 256) {
          utfpredictionb = 1;
        } else {
          utfpredictionb = 0;
        }
      } else {
        /* Strange */
        utfpredictionb = 0;
      }
    } else {
      utfpredictionb = 0;
    }
  } else {
    asciipredictionb = 0;
    utfpredictionb   = 0;
  }

  while (1) {
    symbolp = NULL;
    while (iteratorl++ < nTerminall) {
      candidatep = *symbolpp++;

      /* To avoid expensive calls to memcpy and so on, this method is working directly on recognizer's lexeme stack. */

      if (! pristineb) {
        if (! isExpectedArraybp[candidatep->idi]) {
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Symbol No %d <%s> is not expected", candidatep->idi, candidatep->descp->asciis);
          continue;
        }
      }

      /* Remember the number of accepted candidates */
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Symbol No %d <%s> is expected", candidatep->idi, candidatep->descp->asciis);
      ++nAcceptedCandidatel;

      /* From now on we are sure that are only looking at predicted terminals */

      /* Out prioritized ? Exit the loop on candidates, because the list of candidates is sorted by priority descending */
      if (lastMatchedPriorityInitializedb && (candidatep->priorityi < lastMatchedMinPriorityi)) {
	MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
				    funcs,
				    "Skipping other alternatives that all have priority < min priority %d",
				    lastMatchedMinPriorityi);
	symbolp = NULL;
	break;
      }

      /* Predicted failure or success ? */
      if (MARPAESLIF_IS_TERMINAL(candidatep)) {
        /* Can we do ASCII prediction ? */
        if (asciipredictionb) {
          /* Does the terminal support ASCII failure prediction ? If yes, by definition, this will be either an anchored string or and anchored character class. */
          if (candidatep->u.terminalp->byte2failureb) {
            /* Apply ASCII failure prediction */
            if (candidatep->u.terminalp->willfailasciib[uc]) {
              MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Symbol No %d <%s> is predicted to fail (ASCII character %c 0x%02x)", candidatep->idi, candidatep->descp->asciis, isprint(uc) ? (char) uc : ' ', (unsigned int) uc);
              continue;
            } else {
              /* If the terminal is a character class or a string of length 1 then by definition it matches */
              if (candidatep->u.terminalp->regex.characterClassb || ((candidatep->u.terminalp->type == MARPAESLIF_TERMINAL_TYPE_STRING) && (candidatep->u.terminalp->patternl == 1))) {
                MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Symbol No %d <%s> is predicted to succeed (ASCII character %c 0x%02x)", candidatep->idi, candidatep->descp->asciis, isprint(uc) ? (char) uc : ' ', (unsigned int) uc);
                singleAsciiCharacterPredictedSuccessb = 1;
              } else {
                singleAsciiCharacterPredictedSuccessb = 0;
              }
            }
          } else {
            singleAsciiCharacterPredictedSuccessb = 0;
          }
        } else {
          singleAsciiCharacterPredictedSuccessb = 0;
        }

        /* Can we do UTF-8 prediction ? */
        if (utfpredictionb) {
          /* Does the terminal support UTF-8 failure prediction ? */
          if (candidatep->u.terminalp->utf2failureb) {
            /* Apply UTF-8 failure prediction ? If yes, by definition, this will be either an anchored string or and anchored character class. */
            if (candidatep->u.terminalp->willfailutfb[codepointi]) {
              MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Symbol No %d <%s> is predicted to fail (UTF-8 character U+%04d)", candidatep->idi, candidatep->descp->asciis, (unsigned int) codepointi);
              continue;
            } else {
              /* If the codepoint is < 256 and if the terminal is a character class or a string of the same number of bytes as for codepointi by definition it matches */
              if ((codepointi < 256) &&
                  (candidatep->u.terminalp->regex.characterClassb || ((candidatep->u.terminalp->type == MARPAESLIF_TERMINAL_TYPE_STRING) && (candidatep->u.terminalp->patternl == utf8_2_bytes_max_arrayp[codepointi].lengthl)))) {
                MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Symbol No %d <%s> is predicted to succeed (UTF-8 character U+%04d)", candidatep->idi, candidatep->descp->asciis, (unsigned int) codepointi);
                singleUtfCharacterPredictedSuccessb = 1;
              } else {
                singleUtfCharacterPredictedSuccessb = 0;
              }
            }
          } else {
            singleUtfCharacterPredictedSuccessb = 0;
          }
        } else {
          singleUtfCharacterPredictedSuccessb = 0;
        }
      } else {
        singleAsciiCharacterPredictedSuccessb = 0;
        singleUtfCharacterPredictedSuccessb = 0;
      }

      /* We want to check if symbolp matches */
      symbolp = candidatep;
      break;
    }

    if (symbolp == NULL) {
      /* No more candidate */
      break;
    }

    if (onlyPredictedLexemesb) {
      /* Skip this symbol if it is not a predicted lexeme... */
      if (symbolp->eventBefores == NULL) {
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                    funcs,
                                    "Skipping symbol No %d <%s> : no before event",
                                    symbolp->idi,
                                    symbolp->descp->asciis);
        continue;
      }
      /* ... or if the prediction event is off */
      if (! marpaESLIFRecognizerp->beforeEventStatebp[symbolp->idi]) {
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                    funcs,
                                    "Skipping symbol No %d <%s> : before event is off",
                                    symbolp->idi,
                                    symbolp->descp->asciis);
        continue;
      }
    }

    /* Get next alternative placeholder */
    alternativep = _marpaESLIFRecognizer_alternativeStack_getp(marpaESLIFRecognizerp, alternativeStackSymbolp, alternativeStackSymboli);
    if (MARPAESLIF_UNLIKELY(alternativep == NULL)) {
      goto err;
    }

    /* Remember where we store current value */
    marpaESLIFValueResultp = &(alternativep->marpaESLIFValueResult);

    /* There is a case when we know a symbol can be skipped: */
    /* It is a string literal that:                          */
    /* - do not have a higher priority, and                  */
    /* - requires less bytes that what is already matched    */
    exceptionp = symbolp->exceptionp;
    if (exceptionp == NULL) {
      /* No need to track anything - we want to have both the result in term of matched length and the true valuation when the symbol is parameterized. */
      if (singleAsciiCharacterPredictedSuccessb) {

        numberOfStartCompletionsi = 1; /* A terminal match always has only one start completion */
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcher_setb(marpaESLIFRecognizerp,
                                                                              marpaESLIF_streamp,
                                                                              marpaESLIF_streamp->eofb ? 0 : 1, /* allocb */
                                                                              MARPAESLIF_MATCH_OK, /* rci */
                                                                              &rci,
                                                                              marpaESLIFValueResultp,
                                                                              marpaESLIF_streamp->inputs, /* matchedp */
                                                                              1, /* matchedLengthl */
                                                                              &matchedLengthl,
                                                                              0, /* substitutionb */
                                                                              NULL, /* outputbufferpp */
                                                                              0 /* outputbufferl */))) {
          goto err;
        }

      } else if (singleUtfCharacterPredictedSuccessb) {

        numberOfStartCompletionsi = 1; /* A terminal match always has only one start completion */
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcher_setb(marpaESLIFRecognizerp,
                                                                              marpaESLIF_streamp,
                                                                              marpaESLIF_streamp->eofb ? 0 : 1, /* allocb */
                                                                              MARPAESLIF_MATCH_OK, /* rci */
                                                                              &rci,
                                                                              marpaESLIFValueResultp,
                                                                              marpaESLIF_streamp->inputs, /* matchedp */
                                                                              utf8_2_bytes_max_arrayp[codepointi].lengthl, /* matchedLengthl */
                                                                              &matchedLengthl,
                                                                              0, /* substitutionb */
                                                                              NULL, /* outputbufferpp */
                                                                              0 /* outputbufferl */))) {
          goto err;
        }

      } else {

        rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp, marpaESLIF_streamp, symbolp, &rci, marpaESLIFValueResultp, 0 /* maxStartCompletionsi */, NULL /* lastSizeBeforeCompletionlp */, &numberOfStartCompletionsi, &matchedLengthl);
        if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
          goto err;
        }
        if (! rcMatcherb) {
          continue;
        }
      }

    } else {
      /* Exception rules are always true lexemes or terminals, that are not allowed to be parameterized */
      rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp, marpaESLIF_streamp, symbolp, &rci, marpaESLIFValueResultp, -1 /* maxStartCompletionsi */, NULL /* lastSizeBeforeCompletionlp */, &numberOfStartCompletionsi, &matchedLengthl);
      if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
        goto err;
      }
      if (! rcMatcherb) {
        continue;
      }

      symbolMaxStartCompletionsi    = numberOfStartCompletionsi;
      exceptionMaxStartCompletionsi = -1;
    exception_again:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Symbol match on %ld bytes using %d completions", (unsigned long) matchedLengthl, numberOfStartCompletionsi);
      /* Take care: this may move the stream */
      offsetl = matchedLengthl;

      rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp, marpaESLIF_streamp, exceptionp, &exceptionRci, &exceptionMarpaESLIFValueResult, exceptionMaxStartCompletionsi, &lastSizeBeforeCompletionl, &numberOfExceptionCompletionsi, &exceptionMatchedLengthl);
      if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
        goto err;
      }

      /* We take current marpaESLIFValueResult and look if it matches exception. */
      if (rcMatcherb) {
        if (exceptionRci == MARPAESLIF_MATCH_OK) {
          /* In any case we do not mind about the exception value itself, just the size */
          _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, &exceptionMarpaESLIFValueResult, 1 /* deepb */);
          if (exceptionMatchedLengthl == matchedLengthl) {
            /* The matched value, taken as if it was a separate input, is matching the exception */
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes", (unsigned long) exceptionMatchedLengthl);
            _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, marpaESLIFValueResultp, 1 /* deepb */);

            /* We have to rollback on the number of completions until symbol size is <= lastSizeBeforeCompletionl */
            if (lastSizeBeforeCompletionl <= 0) {
              MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes: no room is left for symbol match", (unsigned long) exceptionMatchedLengthl);
              rci = MARPAESLIF_MATCH_FAILURE;
            } else {
              MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes: asking for less symbol completions until its size is <= %ld", (unsigned long) exceptionMatchedLengthl, (unsigned long) lastSizeBeforeCompletionl);
	      if (symbolMaxStartCompletionsi <= 1) {
		MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes and symbol cannot match on a smaller input", (unsigned long) exceptionMatchedLengthl);
		rci = MARPAESLIF_MATCH_FAILURE;
	      } else {
		while (--symbolMaxStartCompletionsi > 0) {
		  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes: asking for %d symbol start completions", (unsigned long) exceptionMatchedLengthl, symbolMaxStartCompletionsi);
		  rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp, marpaESLIF_streamp, symbolp, &rci, marpaESLIFValueResultp, symbolMaxStartCompletionsi, NULL /* lastSizeBeforeCompletionlp */, NULL /* numberOfStartCompletionsi */, &matchedLengthl);
		  if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
		    goto err;
		  }
		  if (! rcMatcherb) {
		    /* This should never happen since we already had completions before */
		    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes: symbol match failure when asking for %d start completions !?", (unsigned long) exceptionMatchedLengthl, symbolMaxStartCompletionsi);
		    break;
		  }
		  if (rci != MARPAESLIF_MATCH_OK) {
		    /* Ditto */
		    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes: symbol match did not return MARPAESLIF_MATCH_OK when asking for %d start completions !?", (unsigned long) exceptionMatchedLengthl, symbolMaxStartCompletionsi);
		    break;
		  }
		  if (matchedLengthl > lastSizeBeforeCompletionl) {
		    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes: asking for %d symbol start completions ok but with size %ld > %ld", (unsigned long) exceptionMatchedLengthl, symbolMaxStartCompletionsi, (unsigned long) matchedLengthl, (unsigned long) lastSizeBeforeCompletionl);
                    _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, marpaESLIFValueResultp, 1 /* deepb */);
		  } else {
		    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes: asking for %d symbol start completions ok with size %ld <= %ld", (unsigned long) exceptionMatchedLengthl, symbolMaxStartCompletionsi, (unsigned long) matchedLengthl, (unsigned long) lastSizeBeforeCompletionl);
		    exceptionMaxStartCompletionsi = numberOfExceptionCompletionsi - 1;
		    goto exception_again;
		  }
		}
	      }
	    }
          } else {
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Exception match on %ld bytes != symbol match on %ld bytes", (unsigned long) exceptionMatchedLengthl, (unsigned long) matchedLengthl);
          }
        }
      }
    }
    
    switch (rci) {
    case MARPAESLIF_MATCH_FAILURE:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                  funcs,
                                  "Symbol No %d <%s> has MARPAESLIF_MATCH_FAILURE",
                                  symbolp->idi,
                                  symbolp->descp->asciis);
      break;
    case MARPAESLIF_MATCH_OK:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                  funcs,
                                  "Symbol No %d <%s> has MARPAESLIF_MATCH_OK",
                                  symbolp->idi,
                                  symbolp->descp->asciis);
      if (! lastMatchedPriorityInitializedb) {
        lastMatchedMinPriorityi = symbolp->priorityi;
        lastMatchedPriorityInitializedb = 1;
      }

      /* Assign alternative */
      alternativep->symbolp               = symbolp;
      /* alternativep->marpaESLIFValueResult = marpaESLIFValueResult; */ /* Current result placeholder */
      alternativep->grammarLengthi        = 1; /* Scan mode is in the token-stream model */
      alternativep->usedb                 = 1;
      alternativep->matchedLengthl        = matchedLengthl;

      /* Remember at least one alternative is ok */
      alternativeStackSymboli++;

      /* Remember max matched length */
      if (matchedLengthl > maxMatchedl) {
        maxMatchedl = matchedLengthl;
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Setted maxMatchedl to %ld", (unsigned long) maxMatchedl);
      }

      /* Remember if we matched a pseudo terminal */
      if (! isPseudoTerminalMatchb) {
        isPseudoTerminalMatchb = MARPAESLIF_IS_PSEUDO_TERMINAL(symbolp);
      }

      /* Remember if we matched a lookup (which can never be a terminal) */
      if (! isLookupMetaMatchb) {
        isLookupMetaMatchb = MARPAESLIF_IS_META_LOOKAHEAD(symbolp);
      }

      break;
    default:
      /* The case MARPAESLIF_MATCH_AGAIN is handled in the terminal section of _marpaESLIFRecognizer_symbol_matcherb() */
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Unsupported matcher return code %d", rci);
      goto err;
    }
  }

  /* If we were in the initialEvents mode and there is already something in the event array, get out of the method immediately. */
  if (initialEventsb) {
    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp,
                               funcs,
                               "Checking initialEventsb");
    if (marpaESLIFRecognizerp->eventArrayl > 0) {
      rcb = 1;
      goto done;
    } else {
      MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp,
                                 funcs,
                                 "Setting onlyPredictedLexemesb and initialEventsb to off and retry");
      /* No initial event at all. This mean no predicted symbol neither. So we stop aking for only predicted lexemes. */
      onlyPredictedLexemesb = 0;
      /* And switch of this unique flag */
      initialEventsb = 0;
      /* ... and restart the loop */
      goto retry;
    }
  }

  if (alternativeStackSymboli <= 0) {
    /* Either there was truely no symbol, either no symbol matched. */
    if (nAcceptedCandidatel > 0) {
      /* There was at least one symbol candidate, but nothing matched */
      if (! __marpaESLIFRecognizer_discardb(marpaESLIFRecognizerp, 0 /* minl */, &discardl, 0 /* appendEventb */)) {
        goto err;
      }
      if (discardl > 0) {
        /* If there is an event, get out of this method */
        if (marpaESLIFRecognizerp->eventArrayl > 0) {
          rcb = 1;
          goto done;
        } else {
          goto retry;
        }
      }
    } else {
      /* No symbol expected: this is an error unless:
         - discard mode and completion is reached, or
         - grammar is exhausted and exhaustion support is on
         (Note that exception mode setted support of exhaustion mode)
         These two cases cannot happen when initialEventsb is true:
         - discard mode cannot be set
         - grammar cannot be exhausted (we at the very early start)
      */
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizerp, &isExhaustedb))) {
        goto err;
      }
#ifndef MARPAESLIF_NTRACE
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "marpaESLIFRecognizerp->discardb=%d, marpaESLIFRecognizerp->completedb=%d, marpaESLIFRecognizerOption.exhaustedb=%d, isExhaustedb=%d", marpaESLIFRecognizerp->discardb, marpaESLIFRecognizerp->completedb, marpaESLIFRecognizerp->marpaESLIFRecognizerOption.exhaustedb, isExhaustedb);
#endif
      if (MARPAESLIF_LIKELY((marpaESLIFRecognizerp->discardb && marpaESLIFRecognizerp->completedb)
                            ||
                            (marpaESLIFRecognizerp->marpaESLIFRecognizerOption.exhaustedb && isExhaustedb))) {
        rcb = 1;
        goto done;
      } else {
        goto err;
      }
    }

    /* Discard failure - this is an error unless lexemes were read and:
       - exhaustion is on, or
       - eof flag is true and all the data is consumed
    */
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                funcs,
                                "No alternative, current state is: haveLexemeb=%d, marpaESLIFRecognizerOption.exhaustedb=%d, eofb=%d, inputl=%ld",
                                (int) marpaESLIFRecognizerp->haveLexemeb,
                                (int) marpaESLIFRecognizerp->marpaESLIFRecognizerOption.exhaustedb,
                                (int) marpaESLIF_streamp->eofb,
                                (unsigned long) marpaESLIF_streamp->inputl);

    if (MARPAESLIF_LIKELY(marpaESLIFRecognizerp->haveLexemeb)) {
      if (marpaESLIFRecognizerp->marpaESLIFRecognizerOption.exhaustedb) {
        /* Is grammar already showing up exhaustion ? */
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizerp, &isExhaustedb))) {
          goto err;
        }
        if (! isExhaustedb) {
          /* We force an exhaustion event if last progress reached start completion */
          if (marpaESLIFRecognizerp->atStartCompletionb) {
            marpaESLIFRecognizerp->forceExhaustedb = 1;
            isExhaustedb = 1;
          }
        }
        if (isExhaustedb) {
          marpaESLIFRecognizerp->cannotcontinueb = 1;
          rcb = 1;
          goto done;
        }
      }
      if (marpaESLIF_streamp->eofb && (marpaESLIF_streamp->inputl <= 0)) {
        /* End of the stream */
        marpaESLIFRecognizerp->cannotcontinueb = 1;
        rcb = 1;
        goto done;
      }
      goto err;
    } else {
      goto err;
    }
  }

  for (alternativei = 0; alternativei < alternativeStackSymboli; alternativei++) {
    alternativep = (marpaESLIF_alternative_t *) GENERICSTACK_GET_PTR(alternativeStackSymbolp, alternativei);
    sizel        = alternativep->matchedLengthl;
    /* We skip alternatives that are not long enough unless when symbol is a lookahead */
    if (MARPAESLIF_IS_META_LOOKAHEAD(alternativep->symbolp)) {
      continue;
    }
    if (sizel < maxMatchedl) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp,
                                  funcs,
                                  "Alternative %s is skipped (length %ld < max length %ld)",
                                  alternativep->symbolp->descp->asciis,
                                  (unsigned long) sizel,
                                  (unsigned long) maxMatchedl);
      /* No need to set it to NULL, we use the alternativep->usedb flag */
      alternativep->usedb = 0;
    }
  }

  /* It is a non-sense to have lexemes of length maxMatchedl and a discard rule that would be greater.  */
  /* In this case, :discard have precedence. The exception is a match on a pseudo-terminal, or on a     */
  /* lookup, that is valid despite the fact the it matched zero byte.                                   */
  /* This check is always off when discard is set as fallback.                                          */
  if (! grammarp->discardIsFallbackb) {
    if (! (isPseudoTerminalMatchb || isLookupMetaMatchb)) {
      if (! __marpaESLIFRecognizer_discardb(marpaESLIFRecognizerp, maxMatchedl /* minl */, &discardl, 0 /* appendEventb */)) {
        goto err;
      }
      if (discardl > 0) {
        /* If there is an event, get out of this method */
        if (marpaESLIFRecognizerp->eventArrayl > 0) {
          rcb = 1;
          goto done;
        } else {
          goto retry;
        }
      }
    }
  }

  /* Here we have all the alternatives the recognizer got - remember that this recognizer have seen at least one lexeme in its whole life */
  marpaESLIFRecognizerp->haveLexemeb = 1;

  /* Determine if we have pause before events - only for the top-level recognizer */
  for (alternativei = 0; alternativei < alternativeStackSymboli; alternativei++) {
    alternativep = (marpaESLIF_alternative_t *) GENERICSTACK_GET_PTR(alternativeStackSymbolp, alternativei);
    if (! alternativep->usedb) {
      /* Skipped */
      continue;
    }

    symbolp = alternativep->symbolp;
    if ((symbolp->eventBefores != NULL) && marpaESLIFRecognizerp->beforeEventStatebp[symbolp->idi]) {
      /* Only scanner can set eventBefores, then alternativep->matchedLengthl is set ;) */
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_set_pauseb(marpaESLIFRecognizerp, grammarp, symbolp, marpaESLIF_streamp->inputs, alternativep->matchedLengthl))) {
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_push_eventb(marpaESLIFRecognizerp, MARPAESLIF_EVENTTYPE_BEFORE, symbolp, symbolp->eventBefores, NULL /* discardp */, 0 /* discardl */, symbolp->eventBeforee))) {
        goto err;
      }
    }
  }
  if (marpaESLIFRecognizerp->eventArrayl > 0) {
    rcb = 1;
    goto done;
  }

  /* And push alternatives */
  for (alternativei = 0; alternativei < alternativeStackSymboli; alternativei++) {
    alternativep = (marpaESLIF_alternative_t *) GENERICSTACK_GET_PTR(alternativeStackSymbolp, alternativei);
    if (! alternativep->usedb) {
      /* Skipped */
      continue;
    }

    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_fast_alternativeb(marpaESLIFRecognizerp, alternativep))) {
      goto err;
    }
  }

  /* Commit unless we are in the terminal lookup only mode - this will increment inputs and decrement inputl */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_alternative_completeb(marpaESLIFRecognizerp, maxMatchedl))) {
#ifndef MARPAESLIF_NTRACE
    marpaESLIFRecognizer_progressLogb(marpaESLIFRecognizerp, -1, -1, GENERICLOGGER_LOGLEVEL_TRACE);
#endif
    goto err;
  }

  /* Is there a limit on start symbol completions ? Note that the call _marpaESLIFRecognizer_alternative_completeb triggered the call to _marpaESLIFRecognizer_checkStartCompletionb() */
  if (marpaESLIFRecognizerp->maxStartCompletionsi != 0) {
    if (marpaESLIFRecognizerp->atStartCompletionb) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "lastSizeBeforeCompletionl %ld -> %ld", (unsigned long) marpaESLIFRecognizerp->lastSizeBeforeCompletionl, (unsigned long) marpaESLIFRecognizerp->lastSizel);
      marpaESLIFRecognizerp->lastSizeBeforeCompletionl = marpaESLIFRecognizerp->lastSizel;
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Number of start completions is %d", marpaESLIFRecognizerp->numberOfStartCompletionsi);
      if (marpaESLIFRecognizerp->maxStartCompletionsi > 0) {
        if (marpaESLIFRecognizerp->numberOfStartCompletionsi >= marpaESLIFRecognizerp->maxStartCompletionsi) {
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Maximum number of start completions is %d and reached", marpaESLIFRecognizerp->maxStartCompletionsi);
        } else {
          /* If grammar is exhausted and we did not reach wanted number of completions, then it is a failure */
          if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizerp, &isExhaustedb))) {
            goto err;
          }
          if (isExhaustedb) {
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Maximum number of start completions is %d and current number is %d, but parse is exhausted", marpaESLIFRecognizerp->maxStartCompletionsi, marpaESLIFRecognizerp->numberOfStartCompletionsi);
            rcb = 0;
            goto done;
          }
        }
      }
    }
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isCanContinueb(marpaESLIFRecognizerp, &canContinueb, NULL /* eofbp */, &isExhaustedb))) {
    rcb = 0; /* and NOT goto err */
  }
#ifndef MARPAESLIF_NTRACE
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "rcb = %d (canContinueb=%d, isExhausted=%d)", (int) rcb, (int) canContinueb, (int) isExhaustedb);
#endif
    /* In discard mode, if successful, per definition we have fetched the events. An eventual completion event will be our parent's discard event */
    /* If there is a completion it is unique per def because discard mode is always launched with ambiguity turned off. */
  if (rcb && marpaESLIFRecognizerp->discardb && (! canContinueb) && (marpaESLIFRecognizerp->lastCompletionEvents != NULL) && (marpaESLIFRecognizerp->lastCompletionSymbolp != NULL)) {
    /* In theory it is not possible to not have a parent recognizer here */
    if (MARPAESLIFRECOGNIZER_IS_CHILD(marpaESLIFRecognizerp)) {
      marpaESLIFRecognizerp->marpaESLIFRecognizerParentp->discardEvents  = marpaESLIFRecognizerp->lastCompletionEvents;
      marpaESLIFRecognizerp->marpaESLIFRecognizerParentp->discardSymbolp = marpaESLIFRecognizerp->lastCompletionSymbolp;
      marpaESLIFRecognizerp->marpaESLIFRecognizerParentp->discardEvente  = marpaESLIFRecognizerp->lastCompletionEvente;
    }
  }

  /* Generate error information if requested */
  if ((! rcb) && (! marpaESLIFRecognizerp->silentb)) {
    _marpaESLIFRecognizer_errorv(marpaESLIFRecognizerp);
  }

  /* if (canContinuebp != NULL) { */
    *canContinuebp = canContinueb; /* We know it is never NULL */
  /* } */
  /* if (isExhaustedbp != NULL) { */
    *isExhaustedbp = isExhaustedb; /* We know it is never NULL */
  /* } */
  
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d (canContinueb=%d, isExhaustedb=%d)", (int) rcb, (int) canContinueb, (int) isExhaustedb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_isStartCompleteb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isStartCompletebp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_isStartCompleteb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_checkStartCompletionb(marpaESLIFRecognizerp, 0 /* lengthl */))) {
    goto err;
  }

  if (isStartCompletebp != NULL) {
    *isStartCompletebp = marpaESLIFRecognizerp->atStartCompletionb;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_checkStartCompletionb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t lengthl)
/*****************************************************************************/
{
  static const char                *funcs                   = "_marpaESLIFRecognizer_checkStartCompletionb";
  marpaESLIF_t                     *marpaESLIFp             = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIF_grammar_t             *grammarp                = marpaESLIFRecognizerp->grammarp;
  genericStack_t                   *ruleStackp              = grammarp->ruleStackp;
  marpaWrapperRecognizer_t         *marpaWrapperRecognizerp = marpaESLIFRecognizerp->marpaWrapperRecognizerp;
  /* If marpaESLIFRecognizerp->discardb is set and we are here, per def grammarp->discardi is set to a valid symbol number */
  short                             starti                  = marpaESLIFRecognizerp->discardb ? grammarp->discardi : grammarp->starti;
  int                              *isExpectedArraybp       = marpaESLIFRecognizerp->isExpectedArraybp;
  marpaESLIF_rule_t                *rulep;
  short                             atStartCompletionb;
  short                             rcb;
  marpaWrapperRecognizerProgress_t *progressp;
  size_t                            nProgressl;
  size_t                            progressl;
  int                               rulei;
  int                               positioni;
  size_t                            startCompletionPrevl;
  size_t                            startCompletionl;
  size_t                            cumulCompletionPrevl;
  size_t                            cumulCompletionl;
  size_t                            numberOfStartCompletionsi;
  size_t                            numberOfStartCompletionsPrevi;
  int                               symboli;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_progressb(marpaWrapperRecognizerp, -1, -1, &nProgressl, &progressp))) {
    goto err;
  }

  /* We take advantage of get current progress to also get the prediction */
  atStartCompletionb = 0;
  if (marpaESLIFp->ZeroIntegerisZeroBytesb) {
    /* Use memset to reset isExpectedArraybp */
    memset((void *) isExpectedArraybp, 0, marpaESLIFRecognizerp->isExpectedArraybl);
  } else {
    for (symboli = 0; symboli < GENERICSTACK_USED(grammarp->symbolStackp); symboli++) {
      isExpectedArraybp[symboli] = 0;
    }
  }

  for (progressl = 0; progressl < nProgressl; progressl++) {
    rulei     = progressp[progressl].rulei;
    positioni = progressp[progressl].positioni;

    MARPAESLIF_GRAMMAR_INTERNAL_GET_RULE(marpaESLIFp, rulep, grammarp, rulei);
    if (positioni != -1) {
      /* This is not a completed rule: get the symbol at positioni if there is one */
      if (rulep->nrhsl > 0) {
        /* We do not really mind if this is grammar terminal or not, all we want */
        /* to know is if its expected */
        symboli = rulep->rhsip[positioni];
        isExpectedArraybp[symboli] = 1;
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Rule No %d : Position %d : Symbol No %d (%s) is predicted", rulei, positioni, symboli, rulep->rhspp[positioni]->descp->asciis);
      }
    } else {
      /* Rule completion */

      if (rulep->sequenceb) {
        /* This is a sequence */
        if (rulep->separatorp != NULL) {
          /* And there is a separator between every occurence */
          symboli = rulep->separatorp->idi;
          isExpectedArraybp[symboli] = 1;
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Rule No %d : Position %d : Separator Symbol No %d (%s) is predicted", rulei, positioni, symboli, rulep->separatorp->descp->asciis);
        } else {
          /* And there is no separator. By definition the rule has a single RHS. */
          symboli = rulep->rhsip[0];
          isExpectedArraybp[symboli] = 1;
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Rule No %d : Position %d : Sequence Symbol No %d (%s) is predicted", rulei, positioni, symboli, rulep->rhspp[0]->descp->asciis);
        }
      }

      if (rulep->lhsp->idi == starti) {
#ifndef MARPAESLIF_NTRACE
        if (marpaESLIFRecognizerp->discardb) {
          MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Discard symbol completion detected");
        } else {
          MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Start symbol completion detected");
        }
#endif
        atStartCompletionb = 1;
      }
    }
  }

  if ((marpaESLIFRecognizerp->atStartCompletionb = atStartCompletionb)) {
    /* Count the number of start completions */
    numberOfStartCompletionsPrevi = numberOfStartCompletionsi = marpaESLIFRecognizerp->numberOfStartCompletionsi;
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "numberOfStartCompletionsi = %d => ++numberOfStartCompletionsi = %d", numberOfStartCompletionsi, numberOfStartCompletionsi+1);
    if (MARPAESLIF_UNLIKELY(++numberOfStartCompletionsi < numberOfStartCompletionsPrevi)) {
      /* Paranoid case */
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "int turnaround when computing numberOfStartCompletionsi");
      goto err;
    }
    marpaESLIFRecognizerp->numberOfStartCompletionsi = numberOfStartCompletionsi;

    /* Add cumulative bytes since then */
    startCompletionPrevl = startCompletionl = marpaESLIFRecognizerp->startCompletionl;
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "startCompletionl = %ld => startCompletionl+cumulCompletionl = %ld + %ld = %ld", (unsigned long) startCompletionl, (unsigned long) startCompletionl, (unsigned long) marpaESLIFRecognizerp->cumulCompletionl, (unsigned long) (startCompletionl + marpaESLIFRecognizerp->cumulCompletionl));
    if (MARPAESLIF_UNLIKELY((startCompletionl += marpaESLIFRecognizerp->cumulCompletionl) < startCompletionPrevl)) {
      /* Paranoid case */
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "size_t turnaround when computing startCompletionl");
      goto err;
    }

    /* Add current number of bytes */
    startCompletionPrevl = startCompletionl;
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "startCompletionl = %ld => startCompletionl+lengthl = %ld + %ld = %ld", (unsigned long) startCompletionl, (unsigned long) startCompletionl, (unsigned long) lengthl, (unsigned long) (startCompletionl + lengthl));
    if (MARPAESLIF_UNLIKELY((startCompletionl += lengthl) < startCompletionPrevl)) {
      /* Paranoid case */
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "size_t turnaround when computing startCompletionl");
      goto err;
    }
    marpaESLIFRecognizerp->startCompletionl = startCompletionl;
    marpaESLIFRecognizerp->cumulCompletionl = 0;
  } else {
    /* Add current number of bytes */
    cumulCompletionPrevl = cumulCompletionl = marpaESLIFRecognizerp->cumulCompletionl;
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "cumulCompletionl = %ld => cumulCompletionl+lengthl = %ld + %ld = %ld", (unsigned long) cumulCompletionl, (unsigned long) cumulCompletionl, (unsigned long) lengthl, (unsigned long) (cumulCompletionl + lengthl));
    if (MARPAESLIF_UNLIKELY((cumulCompletionl += lengthl) < cumulCompletionPrevl)) {
      /* Paranoid case */
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "size_t turnaround when computing startCompletionl");
      goto err;
    }
    marpaESLIFRecognizerp->cumulCompletionl = cumulCompletionl;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_fast_alternativeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_alternative_t *alternativep)
/*****************************************************************************/
{
  static const char    *funcs         = "_marpaESLIFRecognizer_fast_alternativeb";
  genericStack_t       *lexemeStackp  = marpaESLIFRecognizerp->lexemeStackp;
  size_t                lastSizel;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_lexemeStack_i_setb(marpaESLIFRecognizerp, GENERICSTACK_USED(lexemeStackp), &(alternativep->marpaESLIFValueResult)))) {
    goto err;
  }
  /* alternative is now in the lexemeStack - remember that */
  MARPAESLIF_MAKE_MARPAESLIFVALUERESULT_SHALLOW(alternativep->marpaESLIFValueResult);

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_alternative_and_valueb(marpaESLIFRecognizerp, alternativep, GENERICSTACK_USED(lexemeStackp) - 1))) {
    goto err;
  }

  if (marpaESLIFRecognizerp->pristineb) {
    /* Remember that this recognizer is not pristine anymore */
    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Remembering that recognizer is not pristine");
    marpaESLIFRecognizerp->pristineb = 0;
  } else {
    /* Increment lastSizeBeforeCompletionl */
    lastSizel = marpaESLIFRecognizerp->lastSizel;
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "lastSizel %ld -> %ld", (unsigned long) lastSizel, (unsigned long) (lastSizel + marpaESLIFRecognizerp->previousMaxMatchedl));
    if (MARPAESLIF_UNLIKELY((marpaESLIFRecognizerp->lastSizel += marpaESLIFRecognizerp->previousMaxMatchedl) < lastSizel)) {
      /* Paranoid case */
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "size_t turnaround when computing lastSizel");
      goto err;
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_alternativeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFAlternative_t *marpaESLIFAlternativep)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_alternativeb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFAlternativep == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Alternative is NULL");
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFAlternativep->names == NULL)) {
    /* Context from the external world must be set */
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s must be called with a names != NULL", funcs);
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFAlternativep->value.contextp == NULL)) {
    /* Context from the external world must be set */
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s must be called with a context != NULL", funcs);
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFAlternativep->grammarLengthl <= 0)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "grammarLengthl cannot be <= 0");
    goto err;
  }

  rcb = _marpaESLIFRecognizer_alternativeb(marpaESLIFRecognizerp, marpaESLIFAlternativep);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_alternative_and_valueb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_alternative_t *alternativep, int valuei)
/*****************************************************************************/
{
  static const char   *funcs                           = "_marpaESLIFRecognizer_alternative_and_valueb";
  genericStack_t      *commitedAlternativeStackSymbolp = marpaESLIFRecognizerp->commitedAlternativeStackSymbolp;
  marpaESLIF_symbol_t *symbolp                         = alternativep->symbolp;
  short                rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

#ifndef MARPAESLIF_NTRACE
  if (symbolp->type == MARPAESLIF_SYMBOL_TYPE_TERMINAL) {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Committing terminal alternative %s at input stack %d", symbolp->descp->asciis, valuei);
  } else {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Committing meta alternative <%s> at input stack %d", symbolp->descp->asciis, valuei);
  }
#endif

  if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_alternativeb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, symbolp->idi, valuei, alternativep->grammarLengthi))) {
    if (! marpaESLIFRecognizerp->silentb) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Failed to commit alternative %s", symbolp->descp->asciis);
      _marpaESLIFRecognizer_errorv(marpaESLIFRecognizerp);
    }
    goto err;
  }

  GENERICSTACK_PUSH_PTR(commitedAlternativeStackSymbolp, symbolp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(commitedAlternativeStackSymbolp))) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "commitedAlternativeStackSymbolp push failure, %s", strerror(errno));
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_isEofb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *eofbp)
/*****************************************************************************/
{
  /* This method never fails */
  static const char *funcs = "_marpaESLIFRecognizer_isEofb";

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "isEofb=%d", (int) marpaESLIFRecognizerp->marpaESLIF_streamp->eofb);
  if (eofbp != NULL) {
    *eofbp = marpaESLIFRecognizerp->marpaESLIF_streamp->eofb;
  }

  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "return 1");
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);

  return 1;
}

/*****************************************************************************/
short marpaESLIFRecognizer_isEofb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *eofbp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_isEofb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_isEofb(marpaESLIFRecognizerp, eofbp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_alternative_completeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t lengthl)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_alternative_completeb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_alternative_completeb(marpaESLIFRecognizerp, lengthl);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_alternative_completeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t lengthl)
/*****************************************************************************/
{
  static const char                *funcs                           = "_marpaESLIFRecognizer_alternative_completeb";
  marpaESLIF_grammar_t             *grammarp                        = marpaESLIFRecognizerp->grammarp;
  genericStack_t                   *commitedAlternativeStackSymbolp = marpaESLIFRecognizerp->commitedAlternativeStackSymbolp;
  marpaESLIF_stream_t              *marpaESLIF_streamp              = marpaESLIFRecognizerp->marpaESLIF_streamp;
  char                             *inputs                          = marpaESLIF_streamp->inputs;
  genericStack_t                   *set2InputStackp;
  int                               commitedAlternativei;
  marpaESLIF_symbol_t              *symbolp;
  short                             rcb;
  int                               latestEarleySetIdi;
  GENERICSTACKITEMTYPE2TYPE_ARRAY   array;
  char                             *currentOffsetp;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* The user may give a length bigger than what we have */
  while (lengthl > marpaESLIF_streamp->inputl) {
    if (MARPAESLIF_LIKELY(! marpaESLIF_streamp->eofb)) {
      if (MARPAESLIF_UNLIKELY(! __marpaESLIFRecognizer_readb(marpaESLIFRecognizerp))) {
        goto err;
      }
      /* We are caching inputs for performance, but this is dangerous because */
      /* _marpaESLIFRecognizer_read() can change it */
      inputs = marpaESLIF_streamp->inputs;
    } else {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Completion length is %ld but must be <= %ld (number of remaining bytes in the recognizer internal buffer)", (unsigned long) lengthl, (unsigned long) marpaESLIF_streamp->inputl);
      goto err;
    }
  }

#ifndef MARPAESLIF_NTRACE
  /* This should never happen in production */
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_USED(commitedAlternativeStackSymbolp) <= 0)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "commitedAlternativeStackSymbolp is empty");
    goto err;
  }
#endif

  /* set latest earleme set id mapping if trackb is true */
  if (marpaESLIFRecognizerp->marpaESLIFRecognizerOption.trackb) {
    /* Get latest earleme set id */
    if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_latestb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, &latestEarleySetIdi))) {
      goto err;
    }

    /* Map latest earley set to an offset and a length to start of input */
    currentOffsetp  = (char *) (inputs - marpaESLIF_streamp->buffers);
    currentOffsetp += (size_t) marpaESLIF_streamp->globalOffsetp;

    GENERICSTACK_ARRAY_PTR(array)    = currentOffsetp;
    GENERICSTACK_ARRAY_LENGTH(array) = lengthl;

    set2InputStackp = marpaESLIFRecognizerp->set2InputStackp;
    GENERICSTACK_SET_ARRAY(set2InputStackp, array, latestEarleySetIdi);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(set2InputStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "set2InputStackp set failure, %s", strerror(errno));
      goto err;
    }
  }

  if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_completeb(marpaESLIFRecognizerp->marpaWrapperRecognizerp))) {
    /* Regardless of failure or success, events should always be fetched as per the doc */
    _marpaESLIFRecognizer_clear_all_eventsb(marpaESLIFRecognizerp);
    _marpaESLIFRecognizer_push_grammar_eventsb(marpaESLIFRecognizerp);
    goto err;
  }

  /* New line processing, increase of startCompletionl, of internal position, etc... */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_matchPostProcessingb(marpaESLIFRecognizerp, lengthl))) {
    goto err;
  }

  /* Push grammar and eventual pause after events */
  _marpaESLIFRecognizer_clear_all_eventsb(marpaESLIFRecognizerp);
  /* It is important to push our events before, because of our internal events, in particular :discard[on/off/switch] */
  for (commitedAlternativei = 0; commitedAlternativei < GENERICSTACK_USED(commitedAlternativeStackSymbolp); commitedAlternativei++) {
    symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_GET_PTR(commitedAlternativeStackSymbolp, commitedAlternativei);
    if ((symbolp->eventAfters != NULL) && marpaESLIFRecognizerp->afterEventStatebp[symbolp->idi]) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_set_pauseb(marpaESLIFRecognizerp, grammarp, symbolp, inputs, lengthl))) {
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_push_eventb(marpaESLIFRecognizerp, MARPAESLIF_EVENTTYPE_AFTER, symbolp, symbolp->eventAfters, NULL /* discardp */, 0 /* discardl */, symbolp->eventAftere))) {
        goto err;
      }
    }
  }
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_push_grammar_eventsb(marpaESLIFRecognizerp))) {
    goto err;
  }

  /* We can reset commited alternatives */
  GENERICSTACK_USED(commitedAlternativeStackSymbolp) = 0;

  /* Reset any internal flag that prevent continuation */
  marpaESLIFRecognizerp->cannotcontinueb = 0;

  /* Remember the length */
  marpaESLIFRecognizerp->previousMaxMatchedl = lengthl;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short __marpaESLIFRecognizer_name_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, short *matchbp)
/*****************************************************************************/
{
  static const char          *funcs                 = "__marpaESLIFRecognizer_name_tryb";
  marpaESLIFValueResult_t     marpaESLIFValueResult = marpaESLIFValueResultUndef;
  short                       matchb;
  short                       rcb;
  marpaESLIF_matcher_value_t  rci;
  size_t                      matchedLengthl;
  short                       rcMatcherb;

  rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp,
                                                     marpaESLIFRecognizerp->marpaESLIF_streamp,
                                                     symbolp,
                                                     &rci,
                                                     &marpaESLIFValueResult,
                                                     0, /* maxStartCompletionsi */
                                                     NULL, /* lastSizeBeforeCompletionlp */
                                                     NULL, /* numberOfStartCompletionsip */
                                                     &matchedLengthl);
  if (MARPAESLIF_UNLIKELY(rcMatcherb < 0)) {
    goto err;
  }
  if (rcMatcherb) {
    matchb = (rci == MARPAESLIF_MATCH_OK);
  } else {
    matchb = 0;
  }

  if (matchb) {
    /* Remember the data */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_set_tryb(marpaESLIFRecognizerp, grammarp, symbolp, marpaESLIFRecognizerp->marpaESLIF_streamp->inputs, matchedLengthl))) {
      goto err;
    }
  }
  
  if (matchbp != NULL) {
    *matchbp = matchb;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, &marpaESLIFValueResult);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_discard_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, short *matchbp)
/*****************************************************************************/
{
  static const char           *funcs = "_marpaESLIFRecognizer_discard_tryb";
  short                        rcb;
  short                        matchb;
  size_t                       matchedLengthl;

  /* It is important to select marpaESLIFRecognizerp->noEventb because only this grammar can be cached */
  /* nevertheles even if the sub-grammar MAY generate an event, end-user will not see it because we    */
  /* will never propagate it. This is why the two following lines have to remain commented: they have  */
  /* a meaning only for the true recognizer (c.f. method resume_oneb) */
  /*
  marpaESLIFRecognizerp->discardEvents  = NULL;
  marpaESLIFRecognizerp->discardSymbolp = NULL;
  marpaESLIFRecognizerp->discardEvente  = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  */
  matchb = _marpaESLIFGrammar_parseb(marpaESLIFRecognizerp->marpaESLIFp,
                                     grammarp,
                                     &(marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard),
                                     &(marpaESLIFRecognizerp->marpaESLIFValueOptionDiscard),
                                     1, /* discardb */
                                     marpaESLIFRecognizerp->noEventb, /* This will select marpaWrapperGrammarDiscardNoEventp or marpaWrapperGrammarDiscardp */
                                     1, /* silentb */
                                     marpaESLIFRecognizerp, /* marpaESLIFRecognizerParentp */
                                     NULL, /* isExhaustedbp */
                                     NULL, /* marpaESLIFValueResultp */
                                     0, /* maxStartCompletionsi */
                                     NULL, /* lastSizeBeforeCompletionlp */
                                     NULL /* numberOfStartCompletionsip */,
                                     0, /* verboseb */
                                     &matchedLengthl,
                                     1 /* No need for a malloc: discard looks like a lexeme */);
  if (matchb) {
    /* Remember the data, NULL or not - per def a lexeme coming our from the recognizer is always an array -; */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_set_tryb(marpaESLIFRecognizerp, grammarp, symbolp, marpaESLIFRecognizerp->marpaESLIF_streamp->inputs, matchedLengthl))) {
      goto err;
    }
  }
  
  if (matchbp != NULL) {
    *matchbp = matchb;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_alternative_readb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFAlternative_t *marpaESLIFAlternativep, size_t lengthl)
/*****************************************************************************/
{
  return
    _marpaESLIFRecognizer_alternativeb(marpaESLIFRecognizerp, marpaESLIFAlternativep) &&
    _marpaESLIFRecognizer_alternative_completeb(marpaESLIFRecognizerp, lengthl);
}

/*****************************************************************************/
short marpaESLIFRecognizer_alternative_readb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFAlternative_t *marpaESLIFAlternativep, size_t lengthl)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_alternative_readb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFAlternativep == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Alternative is NULL");
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFAlternativep->names == NULL)) {
    /* Context from the external world must be set */
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s must be called with a names != NULL", funcs);
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFAlternativep->value.contextp == NULL)) {
    /* Context from the external world must be set */
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s must be called with a context != NULL", funcs);
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFAlternativep->grammarLengthl <= 0)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "grammarLengthl cannot be <= 0");
    goto err;
  }

  rcb = _marpaESLIFRecognizer_alternative_readb(marpaESLIFRecognizerp, marpaESLIFAlternativep, lengthl);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short _marpaESLIFRecognizer_name_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, short *matchbp)
/*****************************************************************************/
{
  static const char       *funcs = "_marpaESLIFRecognizer_name_tryb";
  marpaESLIF_t            *marpaESLIFp;
  marpaESLIF_grammar_t    *grammarp;
  marpaESLIF_symbol_t     *symbolp;
  short                    rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIFp        = marpaESLIFRecognizerp->marpaESLIFp;
  grammarp           = marpaESLIFRecognizerp->grammarp;

  /* This must be an RHS */
  symbolp = _marpaESLIF_symbol_findp(marpaESLIFp, grammarp, names, -1, NULL /* symbolip */, 1 /* silentb */, 0 /* onlyLhsb */, 1 /* onlyRhsb */, MARPAESLIF_SYMBOL_TYPE_NA);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Failed to find symbol <%s> used only as an RHS", names);
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(! __marpaESLIFRecognizer_name_tryb(marpaESLIFRecognizerp, grammarp, symbolp, matchbp))) {
    goto err;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_name_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, short *matchbp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_name_tryb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(names == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Name is NULL");
    errno = EINVAL;
    goto err;
  }

  rcb = _marpaESLIFRecognizer_name_tryb(marpaESLIFRecognizerp, names, matchbp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_discardb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *discardlp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_discardb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_discardb(marpaESLIFRecognizerp, discardlp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_discardb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *discardlp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_discardb";
  size_t             discardl;
  short              rcb;

  if (! __marpaESLIFRecognizer_discardb(marpaESLIFRecognizerp, 0 /* minl */, &discardl, 0 /* appendEventb */)) {
    goto err;
  }

  if (discardlp != NULL) {
    *discardlp = discardl;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_discard_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *matchbp)
/*****************************************************************************/
{
  static const char       *funcs = "marpaESLIFRecognizer_discard_tryb";
  marpaESLIF_t            *marpaESLIFp;
  marpaESLIF_grammar_t    *grammarp;
  short                    rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIFp        = marpaESLIFRecognizerp->marpaESLIFp;
  grammarp           = marpaESLIFRecognizerp->grammarp;

  if (MARPAESLIF_UNLIKELY(grammarp->discardp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Grammar has no <:discard>");
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_discard_tryb(marpaESLIFRecognizerp, grammarp, grammarp->discardp, matchbp))) {
    goto err;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_event_onoffb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *symbols, marpaESLIFEventType_t eventSeti, short onoffb)
/*****************************************************************************/
{
  static const char    *funcs           = "marpaESLIFRecognizer_event_onoffb";
  static const int      nativeEventSeti = MARPAESLIF_EVENTTYPE_COMPLETED|MARPAESLIF_EVENTTYPE_NULLED|MARPAESLIF_EVENTTYPE_PREDICTED;
  marpaESLIF_t         *marpaESLIFp;
  marpaESLIF_grammar_t *grammarp;
  marpaESLIF_symbol_t  *symbolp;
  int                   seti;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIFp        = marpaESLIFRecognizerp->marpaESLIFp;
  grammarp           = marpaESLIFRecognizerp->grammarp;

  if (MARPAESLIF_UNLIKELY(symbols == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Symbol name is NULL");
    goto err;
  }

  symbolp = _marpaESLIF_symbol_findp(marpaESLIFp, grammarp, symbols, -1, NULL /* symbolip */, 0 /* silentb */, 0 /* onlyLhsb */, 0 /* onlyRhsb */, MARPAESLIF_SYMBOL_TYPE_META);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Failed to find symbol <%s>", symbols);
    goto err;
  }

  /* We are more than events than native marpa, split them */
  
  /* Of course, this part of marpaESLIFEventType_t is strictly equivalent to marpaWrapperGrammarEventType_t -; */
  seti = eventSeti;
  seti &= nativeEventSeti;
  if (seti != MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE) {
    if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_event_onoffb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, symbolp->idi, (marpaWrapperGrammarEventType_t) eventSeti, (int) onoffb))) {
      goto err;
    }
  }

  /* Comes our specific parts: lexeme before, lexeme after, exhaustion and discard */
  if ((eventSeti & MARPAESLIF_EVENTTYPE_BEFORE) == MARPAESLIF_EVENTTYPE_BEFORE) {
    marpaESLIFRecognizerp->beforeEventStatebp[symbolp->idi] = onoffb;
  }
  if ((eventSeti & MARPAESLIF_EVENTTYPE_AFTER) == MARPAESLIF_EVENTTYPE_AFTER) {
    marpaESLIFRecognizerp->afterEventStatebp[symbolp->idi] = onoffb;
  }
  if ((eventSeti & MARPAESLIF_EVENTTYPE_DISCARD) == MARPAESLIF_EVENTTYPE_DISCARD) {
    marpaESLIFRecognizerp->discardEventStatebp[symbolp->idi] = onoffb;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_name_expectedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *nNamelp, char ***namesArraypp)
/*****************************************************************************/
{
  static const char    *funcs = "marpaESLIFRecognizer_name_expectedb";
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_name_expectedb(marpaESLIFRecognizerp, nNamelp, namesArraypp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
void marpaESLIFGrammar_freev(marpaESLIFGrammar_t *marpaESLIFGrammarp)
/*****************************************************************************/
{
  _marpaESLIFGrammar_freev(marpaESLIFGrammarp, 0 /* onStackb */);
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_symbolData_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_symbol_data_t **symbolDatapp)
/*****************************************************************************/
{
  static const char        *funcs       = "_marpaESLIFRecognizer_symbolData_freev";
  genericStack_t           *symbolStackp;
  marpaESLIF_grammar_t     *grammarp;
  int                       symboli;
  marpaESLIF_symbol_data_t *symbolDatap;

  if (symbolDatapp != NULL) {
    grammarp     = marpaESLIFRecognizerp->grammarp;
    symbolStackp = grammarp->symbolStackp;

    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      symbolDatap = symbolDatapp[symboli];
      if (symbolDatap != NULL) {
        if (symbolDatap->bytes != NULL) {
          free(symbolDatap->bytes);
        }
        free(symbolDatap);
      }
    }
    free(symbolDatapp);
  }
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_lastPause_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  _marpaESLIFRecognizer_symbolData_freev(marpaESLIFRecognizerp, marpaESLIFRecognizerp->lastPausepp);
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_lastTry_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  _marpaESLIFRecognizer_symbolData_freev(marpaESLIFRecognizerp, marpaESLIFRecognizerp->lastTrypp);
}

/*****************************************************************************/
void marpaESLIFRecognizer_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  if (marpaESLIFRecognizerp != NULL) {
    _marpaESLIFRecognizer_freev(marpaESLIFRecognizerp, 0 /* forceb */);
  }
}

/*****************************************************************************/
short marpaESLIFGrammar_parseb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp, marpaESLIFValueOption_t *marpaESLIFValueOptionp, short *isExhaustedbp)
/*****************************************************************************/
{
  return marpaESLIFGrammar_parse_by_levelb(marpaESLIFGrammarp, marpaESLIFRecognizerOptionp, marpaESLIFValueOptionp, isExhaustedbp, 0 /* leveli */, NULL /* descp */);
}

/*****************************************************************************/
short marpaESLIFGrammar_parse_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp, marpaESLIFValueOption_t *marpaESLIFValueOptionp, short *isExhaustedbp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammarp;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFGrammar_parseb(marpaESLIFGrammarp->marpaESLIFp,
                                                      grammarp,
                                                      marpaESLIFRecognizerOptionp,
                                                      marpaESLIFValueOptionp,
                                                      0, /* discardb */
                                                      1, /* noEventb - this will make the recognizer use marpaWrapperGrammarStartNoEventp */
                                                      0, /* silentb */
                                                      NULL, /* marpaESLIFRecognizerParentp */
                                                      isExhaustedbp,
                                                      NULL, /* marpaESLIFValueResultp */
                                                      0, /* maxStartCompletionsi */
                                                      NULL, /* lastSizeBeforeCompletionlp */
                                                      NULL /* numberOfStartCompletionsip */,
                                                      0, /* verboseb */
                                                      NULL, /* matchedLengthlp */
                                                      0 /* isLexemeb */))) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIFReader_grammarReader(void *userDatavp, char **inputsp, size_t *inputlp, short *eofbp, short *characterStreambp, char **encodingsp, size_t *encodinglp, marpaESLIFReaderDispose_t *disposeCallbackpp)
/*****************************************************************************/
{
  static const char          *funcs                     = "marpaESLIFReader_grammarReader";
  marpaESLIF_readerContext_t *marpaESLIF_readerContextp = (marpaESLIF_readerContext_t *) userDatavp;
#ifndef MARPAESLIF_NTRACE
  marpaESLIF_t               *marpaESLIFp               = marpaESLIF_readerContextp->marpaESLIFp;
#endif

  *inputsp              = (char *) marpaESLIF_readerContextp->marpaESLIFGrammarOptionp->bytep;
  *inputlp              = marpaESLIF_readerContextp->marpaESLIFGrammarOptionp->bytel;
  *eofbp                = 1;
  *characterStreambp    = 1; /* We say this is a stream of characters */
  *encodingsp           = marpaESLIF_readerContextp->marpaESLIFGrammarOptionp->encodings;
  *encodinglp           = marpaESLIF_readerContextp->marpaESLIFGrammarOptionp->encodingl;
  *disposeCallbackpp    = NULL;

#ifndef MARPAESLIF_NTRACE
  MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return 1 (*inputsp=%p, *inputlp=%ld, *eofbp=%d, *characterStreambp=%d)", *inputsp, (unsigned long) *inputlp, (int) *eofbp, (int) *characterStreambp);
#endif

  return 1;
}

/*****************************************************************************/
static inline marpaESLIF_grammar_bootstrap_t *_marpaESLIF_grammar_bootstrap_findp(marpaESLIF_t *marpaESLIFp, genericStack_t *grammarStackp, int leveli, marpaESLIF_string_t *descp)
/*****************************************************************************/
{
  static const char              *funcs = "_marpaESLIF_grammar_bootstrap_findp";
  marpaESLIF_string_t            *utf8p = NULL;
  marpaESLIF_grammar_bootstrap_t *rcp  = NULL;
  marpaESLIF_grammar_bootstrap_t *grammarp;
  int                             i;

  if (descp != NULL) {
    /* Search by description has precedence */
    if ((utf8p = _marpaESLIF_string2utf8p(marpaESLIFp, descp, 0 /* tconvsilentb */)) != NULL) {
      for (i = 0; i < GENERICSTACK_USED(grammarStackp); i++) {
        if (! GENERICSTACK_IS_PTR(grammarStackp, i)) {
          /* Sparse array */
          continue;
        }
        grammarp = (marpaESLIF_grammar_bootstrap_t *) GENERICSTACK_GET_PTR(grammarStackp, i);
        if (_marpaESLIF_string_eqb(grammarp->descp, descp)) {
          rcp = grammarp;
          break;
        }
      }
    }
  } else if (leveli >= 0) {
    if (GENERICSTACK_IS_PTR(grammarStackp, leveli)) {
      rcp = (marpaESLIF_grammar_bootstrap_t *) GENERICSTACK_GET_PTR(grammarStackp, leveli);
    }
  }

  if ((utf8p != NULL) && (utf8p != descp)) {
    _marpaESLIF_string_freev(utf8p, 0 /* onStackb */);
  }

  return rcp;
}

/*****************************************************************************/
static inline marpaESLIF_grammar_t *_marpaESLIF_grammar_findp(marpaESLIF_t *marpaESLIFp, genericStack_t *grammarStackp, int leveli, marpaESLIF_string_t *descp)
/*****************************************************************************/
{
  static const char    *funcs         = "_marpaESLIF_grammar_findp";
  marpaESLIF_string_t  *utf8p         = NULL;
  marpaESLIF_grammar_t *rcp           = NULL;
  marpaESLIF_grammar_t *grammarp;
  int                   i;

  if (descp != NULL) {
    /* Search by description has precedence */
    if ((utf8p = _marpaESLIF_string2utf8p(marpaESLIFp, descp, 0 /* tconvsilentb */)) != NULL) {
      for (i = 0; i < GENERICSTACK_USED(grammarStackp); i++) {
        if (! GENERICSTACK_IS_PTR(grammarStackp, i)) {
          /* Sparse array */
          continue;
        }
        grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, i);
        if (_marpaESLIF_string_eqb(grammarp->descp, descp)) {
          rcp = grammarp;
          break;
        }
      }
    }
  } else if (leveli >= 0) {
    if (GENERICSTACK_IS_PTR(grammarStackp, leveli)) {
      rcp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, leveli);
    }
  }

  if ((utf8p != NULL) && (utf8p != descp)) {
    _marpaESLIF_string_freev(utf8p, 0 /* onStackb */);
  }

  return rcp;
}
 
/*****************************************************************************/
static inline marpaESLIF_grammar_t *_marpaESLIFGrammar_grammar_findp(marpaESLIFGrammar_t *marpaESLIFGrammarp, int leveli, marpaESLIF_string_t *descp)
/*****************************************************************************/
{
  static const char    *funcs         = "_marpaESLIFGrammar_grammar_findp";
  genericStack_t       *grammarStackp = marpaESLIFGrammarp->grammarStackp;
  marpaESLIF_string_t  *utf8p         = NULL;
  marpaESLIF_grammar_t *rcp           = NULL;
  marpaESLIF_grammar_t *grammarp;
  int                   i;

  if (descp != NULL) {
    /* Search by description has precedence */
    if ((utf8p = _marpaESLIF_string2utf8p(marpaESLIFGrammarp->marpaESLIFp, descp, 0 /* tconvsilentb */)) != NULL) {
      for (i = 0; i < GENERICSTACK_USED(grammarStackp); i++) {
        if (! GENERICSTACK_IS_PTR(grammarStackp, i)) {
          /* Sparse array */
          continue;
        }
        grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, i);
        if (_marpaESLIF_string_eqb(grammarp->descp, descp)) {
          rcp = grammarp;
          break;
        }
      }
    }
  } else if (leveli >= 0) {
    if (GENERICSTACK_IS_PTR(grammarStackp, leveli)) {
      rcp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, leveli);
    }
  }

  if ((utf8p != NULL) && (utf8p != descp)) {
    _marpaESLIF_string_freev(utf8p, 0 /* onStackb */);
  }

  return rcp;
}
 
/*****************************************************************************/
static inline marpaESLIF_rule_t *_marpaESLIF_rule_findp(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, int rulei)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIF_rule_findp";
  marpaESLIF_rule_t *rulep;

  if (MARPAESLIF_UNLIKELY(rulei < 0)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Invalid rule ID %d", rulei);
    goto err;
  }

  MARPAESLIF_GRAMMAR_INTERNAL_GET_RULE(marpaESLIFp, rulep, grammarp, rulei);
  goto done;

 err:
  rulep = NULL;

 done:
  return rulep;
}

/*****************************************************************************/
static inline marpaESLIF_symbol_t *_marpaESLIF_symbol_findp(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, char *asciis, int symboli, int *symbolip, short silentb, short onlyLhsb, short onlyRhsb, marpaESLIF_symbol_type_t type)
/*****************************************************************************/
{
  static const char    *funcs        = "_marpaESLIF_symbol_findp";
  genericStack_t       *symbolStackp = grammarp->symbolStackp;
  marpaESLIF_symbol_t  *rcp;
  marpaESLIF_symbol_t  *symbolp;
  int                   i;

  /* Give precedence to symbol by name - which is possible only for meta symbols */
  if (asciis != NULL) {
    rcp = NULL;
    for (i = 0; i < GENERICSTACK_USED(symbolStackp); i++) {
      MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFp, symbolp, grammarp, i);
      /* First the fastest tests */
      switch (type) {
      case MARPAESLIF_SYMBOL_TYPE_NA:
        break;
      case MARPAESLIF_SYMBOL_TYPE_TERMINAL:
      case MARPAESLIF_SYMBOL_TYPE_META:
        if (symbolp->type != type) {
          continue;
        }
        break;
      default:
        if (! silentb) {
          MARPAESLIF_ERRORF(marpaESLIFp, "Unknown symbol type %d", type);
        }
        goto err;
      }
      if ((symbolp->lhsb && onlyRhsb) || ((! symbolp->lhsb) && onlyLhsb)) {
        continue;
      }
      /* Then the strcmp test */
      if (strcmp(asciis, symbolp->descp->asciis) != 0) {
        continue;
      }
      rcp = symbolp;
      break;
    }
    if (MARPAESLIF_UNLIKELY(rcp == NULL)) {
      if (! silentb) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Unknown symbol <%s>", asciis);
      }
      goto err;
    }
  } else if (symboli >= 0) {
    if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_PTR(symbolStackp, symboli))) {
      if (! silentb) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Unknown symbol ID %d", symboli);
      }
      goto err;
    }
    symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_GET_PTR(symbolStackp, symboli);
    if ((symbolp->lhsb && onlyRhsb) || ((! symbolp->lhsb) && onlyLhsb)) {
      if (! silentb) {
        MARPAESLIF_ERRORF(marpaESLIFp, "Invalid symbol ID %d", symboli);
      }
      goto err;
    }
    rcp = symbolp;
  } else {
    if (! silentb) {
      MARPAESLIF_ERRORF(marpaESLIFp, "Invalid symbol ID %d", symboli);
    }
    goto err;
  }

  /* Here rcp is != NULL per def */
  if (symbolip != NULL) {
    *symbolip = rcp->idi;
  }
  goto done;

 err:
  rcp = NULL;
  errno = EINVAL;

 done:
  return rcp;
}

/*****************************************************************************/
short marpaESLIFRecognizer_eventb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *eventArraylp, marpaESLIFEvent_t **eventArraypp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_eventb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_eventb(marpaESLIFRecognizerp, eventArraylp, eventArraypp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_push_eventb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFEventType_t type, marpaESLIF_symbol_t *symbolp, char *events, char *discardp, size_t discardl, marpaESLIF_internal_event_action_t event_actione)
/*****************************************************************************/
{
  static const char        *funcs = "_marpaESLIFRecognizer_push_eventb";
  marpaESLIFEvent_t        *eventArrayp;
  size_t                    eventArrayl;
  size_t                    eventArraySizel;
  marpaESLIFEvent_t         eventArray;
  char                     *tmpp;
  short                     rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Detect hook events and process them instead of pushing to the end-user */
  switch (event_actione) {
  case MARPAESLIF_INTERNAL_EVENT_ACTION__DISCARD_ON:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: event %s: enabling discard", (symbolp != NULL) ? symbolp->descp->asciis : "??", events);
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_hook_discardb(marpaESLIFRecognizerp, 1))) {
      goto err;
    }
    goto no_push;
  case MARPAESLIF_INTERNAL_EVENT_ACTION__DISCARD_OFF:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: event %s: disabling discard", (symbolp != NULL) ? symbolp->descp->asciis : "??", events);
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_hook_discardb(marpaESLIFRecognizerp, 0))) {
      goto err;
    }
    goto no_push;
  case MARPAESLIF_INTERNAL_EVENT_ACTION__DISCARD_SWITCH:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: event %s: switching discard", (symbolp != NULL) ? symbolp->descp->asciis : "??", events);
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_hook_discard_switchb(marpaESLIFRecognizerp))) {
      goto err;
    }
    goto no_push;
  default:
    break;
  }

  /* Hook for MARPAESLIF_EVENTTYPE_DISCARD: the associated symbol is NOT pushed to the grammar */
  /* because discards apply to all grammars, not any particular one. */
  /* So if the end user wants to retrieve the last */
  /* discarded data, when trackb is on, he cannot. */
  if ((discardp != NULL) && (discardl > 0)) {
    if (marpaESLIFRecognizerp->lastDiscards == NULL) {
      marpaESLIFRecognizerp->lastDiscards = (char *) malloc(discardl + 1); /* Hiden NUL byte */
      if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp->lastDiscards == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
    } else if (marpaESLIFRecognizerp->lastDiscardl < discardl) {
      tmpp = (char *) realloc(marpaESLIFRecognizerp->lastDiscards, discardl + 1); /* Hiden NUL byte */
      if (MARPAESLIF_UNLIKELY(tmpp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      marpaESLIFRecognizerp->lastDiscards = tmpp;
    }
    memcpy(marpaESLIFRecognizerp->lastDiscards, discardp, discardl);
    marpaESLIFRecognizerp->lastDiscardl = discardl;
    marpaESLIFRecognizerp->lastDiscards[marpaESLIFRecognizerp->lastDiscardl] = '\0';
  }

  /* These statements have a cost - execute them only if we really push the event */
  eventArrayp     = marpaESLIFRecognizerp->eventArrayp;
  eventArraySizel = marpaESLIFRecognizerp->eventArraySizel;
  eventArrayl     = marpaESLIFRecognizerp->eventArrayl;

  eventArray.type    = type;
  eventArray.symbols = (symbolp != NULL) ? symbolp->descp->asciis : NULL;
  /* Support of ":symbol" is coded here */
  eventArray.events  = (event_actione == MARPAESLIF_INTERNAL_EVENT_ACTION__SYMBOL) ? eventArray.symbols : events;

  /* Extend of create the array */
  /* marpaESLIFRecognizerp->eventArrayl is always in the range [0..marpaESLIFRecognizerp->eventArraySizel] */
  /* and is set to 0 at every reset */
  if (eventArraySizel <= eventArrayl) {
    if (eventArrayp == NULL) {
      /* In theory, here, eventArrayl can only have the value 1 */
      eventArraySizel = eventArrayl + 1;
      eventArrayp = (marpaESLIFEvent_t *) malloc(eventArraySizel * sizeof(marpaESLIFEvent_t));
      if (MARPAESLIF_UNLIKELY(eventArrayp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
    } else {
      eventArraySizel *= 2;
      eventArrayp = realloc(eventArrayp, eventArraySizel * sizeof(marpaESLIFEvent_t));
      if (MARPAESLIF_UNLIKELY(eventArrayp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "realloc failure, %s", strerror(errno));
        goto err;
      }
    }
    marpaESLIFRecognizerp->eventArrayp     = eventArrayp;
    marpaESLIFRecognizerp->eventArraySizel = eventArraySizel;
  }

  eventArrayp[eventArrayl] = eventArray;
  if ((marpaESLIFRecognizerp->eventArrayl = ++eventArrayl) > 1) {
    /* Sort the events if there is more than one */
    _marpaESLIFRecognizer_sort_eventsb(marpaESLIFRecognizerp);
  }

 no_push:
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_set_symbolDatab(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, char *datas, size_t datal, marpaESLIF_symbol_data_t **symbolDatapp)
/*****************************************************************************/
{
  static const char        *funcs      = "_marpaESLIFRecognizer_set_symbolDatab";
  marpaESLIF_symbol_data_t *symbolDatap = symbolDatapp[symbolp->idi];
  char                     *bytes;
  size_t                    byteSizel;
  short                     rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* symbolDatapp is guaranteed to have been allocated. But this is originally an array of NULL pointers */
  if (symbolDatap == NULL) {
    symbolDatap = (marpaESLIF_symbol_data_t *) malloc(sizeof(marpaESLIF_symbol_data_t));
    if (MARPAESLIF_UNLIKELY(symbolDatap == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    symbolDatap->bytes     = NULL;
    symbolDatap->bytel     = 0;
    symbolDatap->byteSizel = 0;

    symbolDatapp[symbolp->idi] = symbolDatap;
  }
  
  /* In theory it is not possible to have a pause event if there is a parent recognizer.

   Memory management of the pause chunk is done so that free/malloc/realloc are avoided as much as
   possible.
  */
  /* These statements have a cost - execute them only if we really set the pause */
  byteSizel = symbolDatap->byteSizel;

  /* Extend or create the chunk (take care: datal can be zero for a zero-length lexeme) */
  if ((byteSizel <= 0) || (byteSizel < datal)) {
    bytes     = symbolDatap->bytes;
    byteSizel = datal;

    if (bytes == NULL) {
      bytes = (char *) malloc(byteSizel + 1); /* We always add a NUL byte for convenience */
      if (MARPAESLIF_UNLIKELY(bytes == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
    } else {
      bytes = realloc(bytes, byteSizel + 1); /* We always add a NUL byte for convenience */
      if (MARPAESLIF_UNLIKELY(bytes == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "realloc failure, %s", strerror(errno));
        goto err;
      }
    }
    symbolDatap->bytes     = bytes;
    symbolDatap->byteSizel = byteSizel;
  } else {
    bytes = symbolDatap->bytes;
  }

  if (datal > 0) {
    memcpy(bytes, datas, datal);
  }
  bytes[datal] = '\0'; /* Just to make the debuggers happy - this is hiden */
  symbolDatap->bytel = datal;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_set_pauseb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, char *bytes, size_t bytel)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_set_symbolDatab(marpaESLIFRecognizerp, grammarp, symbolp, bytes, bytel, marpaESLIFRecognizerp->lastPausepp);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_set_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_grammar_t *grammarp, marpaESLIF_symbol_t *symbolp, char *bytes, size_t bytel)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_set_symbolDatab(marpaESLIFRecognizerp, grammarp, symbolp, bytes, bytel, marpaESLIFRecognizerp->lastTrypp);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_push_grammar_eventsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char                  *funcs              = "_marpaESLIFRecognizer_push_grammar_eventsb";
  marpaESLIF_grammar_t               *grammarp           = marpaESLIFRecognizerp->grammarp;
  marpaESLIF_stream_t                *marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  short                               last_discard_loopb = 0;
  short                               isExhaustedb       = 0;
  short                               skipb;
  marpaESLIF_symbol_t                *symbolp;
  int                                 symboli;
  size_t                              grammarEventl;
  marpaWrapperGrammarEvent_t         *grammarEventp;
  short                               rcb;
  char                               *events;
  size_t                              i;
  marpaESLIFEventType_t               type;
  short                               continue_last_discard_loopb;
  size_t                              discardl;
  marpaESLIF_internal_event_action_t  event_actione;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIFRecognizerp->lastCompletionEvents  = NULL;
  marpaESLIFRecognizerp->lastCompletionSymbolp = NULL;
  marpaESLIFRecognizerp->lastCompletionEvente  = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  marpaESLIFRecognizerp->completedb            = 0;

  /* Collect grammar native events and push them in the events stack */
  if (MARPAESLIF_UNLIKELY(! marpaWrapperGrammar_eventb(marpaESLIFRecognizerp->marpaWrapperGrammarp,
                                                       &grammarEventl,
                                                       &grammarEventp,
                                                       1, /* exhaustedb */
                                                       0 /* forceReloadb */))) {
    goto err;
  }

  if (grammarEventl > 0) {

    for (i = 0; i < grammarEventl; i++) {
      symboli = grammarEventp[i].symboli;
      type    = MARPAESLIF_EVENTTYPE_NONE;
      events  = NULL;
      skipb   = 0;

      if (symboli >= 0) {
        /* Look for the symbol */
        MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFRecognizerp->marpaESLIFp, symbolp, grammarp, symboli);
      } else {
        symbolp = NULL;
      }

      /* Our grammar made sure there can by only one named event per symbol */
      /* In addition, marpaWrapper guarantee there is a symbol associated to */
      /* completion, nulled or prediction events */
      switch (grammarEventp[i].eventType) {
      case MARPAWRAPPERGRAMMAR_EVENT_COMPLETED:
        type        = MARPAESLIF_EVENTTYPE_COMPLETED;
        if (symbolp != NULL) {
          /* The discard event is only possible on completion in discard mode */
          marpaESLIFRecognizerp->lastCompletionEvents  = events        = marpaESLIFRecognizerp->discardb ? symbolp->discardEvents : symbolp->eventCompleteds;
          marpaESLIFRecognizerp->lastCompletionSymbolp = symbolp;
          marpaESLIFRecognizerp->lastCompletionEvente  = event_actione = marpaESLIFRecognizerp->discardb ? symbolp->discardEvente : symbolp->eventCompletede;
        }
        marpaESLIFRecognizerp->completedb = 1;
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: completion event", (symbolp != NULL) ? symbolp->descp->asciis : "??");
        break;
      case MARPAWRAPPERGRAMMAR_EVENT_NULLED:
        type        = MARPAESLIF_EVENTTYPE_NULLED;
        if (symbolp != NULL) {
          events        = symbolp->eventNulleds;
          event_actione = symbolp->eventNullede;
        }
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: nullable event", (symbolp != NULL) ? symbolp->descp->asciis : "??");
        break;
      case MARPAWRAPPERGRAMMAR_EVENT_EXPECTED:
        type        = MARPAESLIF_EVENTTYPE_PREDICTED;
        if (symbolp != NULL) {
          events        = symbolp->eventPredicteds;
          event_actione = symbolp->eventPredictede;
        }
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: prediction event", (symbolp != NULL) ? symbolp->descp->asciis : "??");
        break;
      case MARPAWRAPPERGRAMMAR_EVENT_EXHAUSTED:
        type          = MARPAESLIF_EVENTTYPE_EXHAUSTED;
        events        = MARPAESLIF_EVENTTYPE_EXHAUSTED_NAME;
        event_actione = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
        isExhaustedb = 1;
        MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Exhausted event");
        /* Eventually skip this event */
        skipb = (marpaESLIFRecognizerp->marpaESLIFRecognizerOption.exhaustedb < 0) ? 1 : 0;
        /* Force discard of remaining data */
        last_discard_loopb = 1;
        /* symboli will be -1 as per marpaWrapper spec */
        break;
      default:
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: unsupported event type %d", (symbolp != NULL) ? symbolp->descp->asciis : "??", grammarEventp[i].eventType);
        break;
      }
      if (! skipb) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_push_eventb(marpaESLIFRecognizerp, type, symbolp, events, NULL /* discardp */, 0 /* discardl */, event_actione))) {
          goto err;
        }
      }
    }
  }

  if (! isExhaustedb) {
    /* The event on exhaustion only occurs if needed to provide a reason to return. */
    /* If not sent by the grammar, we check explicitely ourself.                    */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizerp, &isExhaustedb))) {
      goto err;
    }
    if (isExhaustedb) {
      /* Push exhaustion event if recognizer interface has set the option */
      if (MARPAESLIF_UNLIKELY((marpaESLIFRecognizerp->marpaESLIFRecognizerOption.exhaustedb > 0) && (! _marpaESLIFRecognizer_push_eventb(marpaESLIFRecognizerp, MARPAESLIF_EVENTTYPE_EXHAUSTED, NULL /* symbolp */, MARPAESLIF_EVENTTYPE_EXHAUSTED_NAME, NULL /* discardp */, 0 /* discardl */, MARPAESLIF_INTERNAL_EVENT_ACTION_NA)))) {
        goto err;
      }
      /* Force discard of remaining data */
      last_discard_loopb = 1;
      MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Exhausted event (check mode)");
    }
  }

  if (last_discard_loopb) {
    /* By definition, here exhaustedb is a true value. */
    if (MARPAESLIFRECOGNIZER_IS_TOP(marpaESLIFRecognizerp) && (! marpaESLIFRecognizerp->last_discard_loopb)) {
      /* This is the end the parsing (we are called when parsing is exhausted) - we try to discard as much as possible */
      /* to avoid the eventual error message "Grammar is exhausted but lexeme remains" */
      /* We want to make sure that only this loop of this recognizer is doing the last discard */
      marpaESLIFRecognizerp->last_discard_loopb = 1;

      do {
        if (! __marpaESLIFRecognizer_discardb(marpaESLIFRecognizerp, 0 /* minl */, &discardl, 1 /* appendEventb */)) {
          goto err;
        }
        if (discardl > 0) {
          continue_last_discard_loopb = (! marpaESLIF_streamp->eofb) || (marpaESLIF_streamp->inputl > 0);
        } else {
          continue_last_discard_loopb = 0;
        }
      } while (continue_last_discard_loopb);

      marpaESLIFRecognizerp->last_discard_loopb = 0;
    }

    /* Trigger an error if data remains and recognizer do not have the exhausted event flag unless it is already managing the last discard loop */
    if (MARPAESLIF_UNLIKELY(! ((marpaESLIF_streamp->eofb && (marpaESLIF_streamp->inputl <= 0)) || marpaESLIFRecognizerp->marpaESLIFRecognizerOption.exhaustedb))) {
      if (! marpaESLIFRecognizerp->last_discard_loopb) {
        if (! marpaESLIFRecognizerp->silentb) {
          MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Grammar is exhausted but data remains");
          _marpaESLIFRecognizer_errorv(marpaESLIFRecognizerp);
        }
        goto err;
      }
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_clear_grammar_eventsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs           = "_marpaESLIFRecognizer_clear_grammar_eventsb";
  marpaESLIFEvent_t *eventArrayp     = marpaESLIFRecognizerp->eventArrayp;
  size_t             eventArrayl     = marpaESLIFRecognizerp->eventArrayl;
  size_t             i;
  size_t             okl             = 0;

  /* We put to NONE the grammar events, sort (NONE will be at the end), and change the length */
  for (i = 0; i < eventArrayl; i++) {
    switch (eventArrayp[i].type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:
    case MARPAESLIF_EVENTTYPE_NULLED:
    case MARPAESLIF_EVENTTYPE_COMPLETED:
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:
      eventArrayp[i].type = MARPAESLIF_EVENTTYPE_NONE;
      break;
    default:
      okl++;
      break;
    }
  }

  if (okl > 0) {
    /* The sort will put eventual NONE events at the very end */
    _marpaESLIFRecognizer_sort_eventsb(marpaESLIFRecognizerp);
  }
  marpaESLIFRecognizerp->eventArrayl = okl;
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_clear_all_eventsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  marpaESLIFRecognizerp->eventArrayl = 0;
}

/*****************************************************************************/
static inline void  _marpaESLIFRecognizer_sort_eventsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  MARPAESLIF_QSORT(marpaESLIFEvent_t, marpaESLIFRecognizerp->eventArrayp, marpaESLIFRecognizerp->eventArrayl, _marpaESLIF_event_sort_inlinedi, _marpaESLIF_event_sorti);
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
/* Note that marpaESLIFValueResultp is always on the stack.                  */
/*****************************************************************************/
{
  static const char *funcs  = "_marpaESLIFRecognizer_valueResultFreev";

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  switch (marpaESLIFValueResultp->type) {
  case MARPAESLIF_VALUE_TYPE_PTR:
    if ((marpaESLIFValueResultp->u.p.p != NULL) && (! marpaESLIFValueResultp->u.p.shallowb) && (marpaESLIFValueResultp->u.p.freeCallbackp != NULL)) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Calling freeCallbackp for %p of type PTR", marpaESLIFValueResultp->u.p.p);
      MARPAESLIFVALUERESULT_FREE(marpaESLIFValueResultp, marpaESLIFValueResultp->u.p.freeCallbackp, marpaESLIFValueResultp->u.p.freeUserDatavp);
    }
    marpaESLIFValueResultp->u.p.p = NULL;
    break;
  case MARPAESLIF_VALUE_TYPE_ARRAY:
    if ((marpaESLIFValueResultp->u.a.p != NULL) && (! marpaESLIFValueResultp->u.a.shallowb) && (marpaESLIFValueResultp->u.a.freeCallbackp != NULL)) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Calling freeCallbackp for %p of type PTR", marpaESLIFValueResultp->u.a.p);
      MARPAESLIFVALUERESULT_FREE(marpaESLIFValueResultp, marpaESLIFValueResultp->u.a.freeCallbackp, marpaESLIFValueResultp->u.a.freeUserDatavp);
    }
    marpaESLIFValueResultp->u.a.p = NULL;
    break;
  case MARPAESLIF_VALUE_TYPE_STRING:
    if ((marpaESLIFValueResultp->u.s.p != NULL) && (! marpaESLIFValueResultp->u.s.shallowb) && (marpaESLIFValueResultp->u.s.freeCallbackp != NULL)) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Calling freeCallbackp for %p of type PTR", marpaESLIFValueResultp->u.s.p);
      MARPAESLIFVALUERESULT_FREE(marpaESLIFValueResultp, marpaESLIFValueResultp->u.s.freeCallbackp, marpaESLIFValueResultp->u.s.freeUserDatavp);
    }
    marpaESLIFValueResultp->u.s.p = NULL;
    break;
  case MARPAESLIF_VALUE_TYPE_ROW:
    if ((marpaESLIFValueResultp->u.r.p != NULL) && (! marpaESLIFValueResultp->u.r.shallowb) && (marpaESLIFValueResultp->u.r.freeCallbackp != NULL)) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Calling freeCallbackp for %p of type PTR", marpaESLIFValueResultp->u.r.p);
      MARPAESLIFVALUERESULT_FREE(marpaESLIFValueResultp, marpaESLIFValueResultp->u.r.freeCallbackp, marpaESLIFValueResultp->u.r.freeUserDatavp);
    }
    marpaESLIFValueResultp->u.r.p = NULL;
    break;
  case MARPAESLIF_VALUE_TYPE_TABLE:
    if ((marpaESLIFValueResultp->u.t.p != NULL) && (! marpaESLIFValueResultp->u.t.shallowb) && (marpaESLIFValueResultp->u.t.freeCallbackp != NULL)) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Calling freeCallbackp for %p of type PTR", marpaESLIFValueResultp->u.t.p);
      MARPAESLIFVALUERESULT_FREE(marpaESLIFValueResultp, marpaESLIFValueResultp->u.t.freeCallbackp, marpaESLIFValueResultp->u.t.freeUserDatavp);
    }
    marpaESLIFValueResultp->u.t.p = NULL;
    break;
  default:
    break;
  }

  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "return");
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_stream_initb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t bufsizl, int buftriggerperci, short eofb, short utfb)
/*****************************************************************************/
{
  static const char *funcs  = "_marpaESLIFRecognizer_stream_initb";

  if (bufsizl <= 0) {
    bufsizl = MARPAESLIF_BUFSIZ;
    /* Still ?! */
    if (bufsizl <= 0) {
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Please recompile this project with a default buffer value MARPAESLIF_BUFSIZ > 0");
      return 0;
    }
  }

  marpaESLIFRecognizerp->_marpaESLIF_stream.buffers              = NULL;
  marpaESLIFRecognizerp->_marpaESLIF_stream.bufferl              = 0;
  marpaESLIFRecognizerp->_marpaESLIF_stream.bufferallocl         = 0;
  marpaESLIFRecognizerp->_marpaESLIF_stream.globalOffsetp        = NULL;
  marpaESLIFRecognizerp->_marpaESLIF_stream.eofb                 = eofb;
  marpaESLIFRecognizerp->_marpaESLIF_stream.utfb                 = utfb;
  marpaESLIFRecognizerp->_marpaESLIF_stream.charconvb            = 0;
  marpaESLIFRecognizerp->_marpaESLIF_stream.bytelefts            = NULL;
  marpaESLIFRecognizerp->_marpaESLIF_stream.byteleftl            = 0;
  marpaESLIFRecognizerp->_marpaESLIF_stream.byteleftallocl       = 0;
  marpaESLIFRecognizerp->_marpaESLIF_stream.inputs               = NULL;
  marpaESLIFRecognizerp->_marpaESLIF_stream.inputl               = 0;
  marpaESLIFRecognizerp->_marpaESLIF_stream.bufsizl              = bufsizl;
  marpaESLIFRecognizerp->_marpaESLIF_stream.buftriggerl          = (bufsizl * (100 + buftriggerperci)) / 100;
  marpaESLIFRecognizerp->_marpaESLIF_stream.nextReadIsFirstReadb = 1;
  marpaESLIFRecognizerp->_marpaESLIF_stream.noAnchorIsOkb        = eofb;
  marpaESLIFRecognizerp->_marpaESLIF_stream.encodings            = NULL;
  marpaESLIFRecognizerp->_marpaESLIF_stream.tconvp               = NULL;
  marpaESLIFRecognizerp->_marpaESLIF_stream.bomdoneb             = 0;
  marpaESLIFRecognizerp->_marpaESLIF_stream.peeki                = 0;
  marpaESLIFRecognizerp->_marpaESLIF_stream.linel                = 1;
  marpaESLIFRecognizerp->_marpaESLIF_stream.columnl              = 1;

  return 1;
}

/*****************************************************************************/
static inline marpaESLIFRecognizer_t *__marpaESLIFRecognizer_newp(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp, short discardb, short noEventb, short silentb, marpaESLIFRecognizer_t *marpaESLIFRecognizerParentp, short fakeb, int maxStartCompletionsi, short utfb, short isLexemeb)
/*****************************************************************************/
/* For performance reasons, when fakeb is a false value, then please arrange your code to work with a false grammmarIsOnStackb value as well */
{
  static const char             *funcs                 = "__marpaESLIFRecognizer_newp";
  marpaESLIFRecognizer_t        *marpaESLIFRecognizerp = NULL;
  marpaWrapperRecognizerOption_t marpaWrapperRecognizerOption;
  genericStack_t                *symbolStackp;
  int                            symboli;
  marpaESLIF_symbol_t           *symbolp;
  short                          discardEventb;

  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    /* It is legal only in the fake mode, that is internal */
    if (! fakeb) {
      MARPAESLIF_ERROR(marpaESLIFp, "Null grammar pointer");
      goto err;
    }
  }

  /* No option ? Use the default. */
  if (marpaESLIFRecognizerOptionp == NULL) {
    marpaESLIFRecognizerOptionp = &marpaESLIFRecognizerOption_default_template;
  }

  /* If this can be a reusable recognizer, so do we */
  if (! _marpaESLIFRecognizer_getPristineFromCachep(marpaESLIFp, grammarp, discardb, noEventb, silentb, marpaESLIFRecognizerParentp, fakeb, &marpaESLIFRecognizerp, isLexemeb)) {
    goto err;
  }
  if (marpaESLIFRecognizerp != NULL) {
    goto done;
  }

  /* Nope, this will be a fresh new thingy */
  if (marpaESLIFRecognizerp == NULL) {
    marpaESLIFRecognizerp = (marpaESLIFRecognizer_t *) malloc(sizeof(marpaESLIFRecognizer_t));
    if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
  }

  marpaESLIFRecognizerp->marpaESLIFp                     = marpaESLIFp;
  marpaESLIFRecognizerp->grammarp                        = grammarp;
  marpaESLIFRecognizerp->isExpectedArraybp               = NULL;
  marpaESLIFRecognizerp->isExpectedArraybl               = 0;
  marpaESLIFRecognizerp->Lsharep                         = (grammarp != NULL) ? grammarp->Lsharep : NULL;
  marpaESLIFRecognizerp->marpaESLIFGrammarp              = (grammarp != NULL) ? grammarp->marpaESLIFGrammarp : NULL;
  marpaESLIFRecognizerp->isLexemeb                       = isLexemeb;
  marpaESLIFRecognizerp->marpaESLIFRecognizerOption      = *marpaESLIFRecognizerOptionp;
  marpaESLIFRecognizerp->marpaWrapperRecognizerp         = NULL;
  marpaESLIFRecognizerp->lexemeStackp                    = NULL;  /* Take care, it is pointer to internal _lexemeStack if stack init is ok */
  marpaESLIFRecognizerp->eventArrayp                     = NULL;
  marpaESLIFRecognizerp->eventArrayl                     = 0;
  marpaESLIFRecognizerp->eventArraySizel                 = 0;
  marpaESLIFRecognizerp->marpaESLIFRecognizerParentp     = marpaESLIFRecognizerParentp;
  marpaESLIFRecognizerp->lastCompletionEvents            = NULL;
  marpaESLIFRecognizerp->lastCompletionSymbolp           = NULL;
  marpaESLIFRecognizerp->lastCompletionEvente            = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  marpaESLIFRecognizerp->discardEvents                   = NULL;
  marpaESLIFRecognizerp->discardSymbolp                  = NULL;
  marpaESLIFRecognizerp->discardEvente                   = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
  marpaESLIFRecognizerp->resumeCounteri                  = 0;
  marpaESLIFRecognizerp->callstackCounteri               = 0;
  marpaESLIFRecognizerp->callstackCounterGlobali         = 0;
  /* If there is a parent recognizer, we share quite a lot of information */
  if (marpaESLIFRecognizerParentp != NULL) {
    marpaESLIFRecognizerp->leveli                           = marpaESLIFRecognizerParentp->leveli + 1;
    marpaESLIFRecognizerp->marpaESLIFRecognizerHashp        = marpaESLIFRecognizerParentp->marpaESLIFRecognizerHashp;
    marpaESLIFRecognizerp->marpaESLIF_streamp               = marpaESLIFRecognizerParentp->marpaESLIF_streamp;
    marpaESLIFRecognizerp->parentDeltal                     = marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputs - marpaESLIFRecognizerParentp->marpaESLIF_streamp->buffers;
    marpaESLIFRecognizerp->parentLinel                      = marpaESLIFRecognizerParentp->marpaESLIF_streamp->linel;
    marpaESLIFRecognizerp->parentColumnl                    = marpaESLIFRecognizerParentp->marpaESLIF_streamp->columnl;
    marpaESLIFRecognizerp->marpaESLIFRecognizerTopp         = marpaESLIFRecognizerParentp->marpaESLIFRecognizerTopp;
    marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp  = marpaESLIFRecognizerParentp->marpaESLIFValueResultStackOrigp;
    marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp   = marpaESLIFRecognizerParentp->marpaESLIFValueResultStackNewp;
  } else {
    marpaESLIFRecognizerp->leveli                           = 0;
    marpaESLIFRecognizerp->marpaESLIFRecognizerHashp        = NULL; /* Pointer to a hash in the structure, initialized later */
    marpaESLIFRecognizerp->marpaESLIF_streamp               = NULL; /* Initialized below */
    marpaESLIFRecognizerp->parentDeltal                     = 0;
    marpaESLIFRecognizerp->parentLinel                      = 0;
    marpaESLIFRecognizerp->parentColumnl                    = 0;
    marpaESLIFRecognizerp->marpaESLIFRecognizerTopp         = marpaESLIFRecognizerp; /* We are the top-level recognizer */
    marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp  = NULL; /* Only the top-level recognizer owns this pointer */
    marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp   = NULL; /* Only the top-level recognizer owns this pointer */
  }
  marpaESLIFRecognizerp->scanb                              = 0;
  marpaESLIFRecognizerp->noEventb                           = noEventb;
  marpaESLIFRecognizerp->discardb                           = discardb;
  marpaESLIFRecognizerp->silentb                            = silentb;
  marpaESLIFRecognizerp->haveLexemeb                        = 0;
  /* These variables are resetted at every _resume_oneb() */
  marpaESLIFRecognizerp->completedb                         = 0;
  marpaESLIFRecognizerp->forceExhaustedb                    = 0;
  marpaESLIFRecognizerp->cannotcontinueb                    = 0;
  marpaESLIFRecognizerp->alternativeStackSymbolp            = NULL;  /* Take care, it is pointer to internal _alternativeStackSymbolp if stack init is ok */
  marpaESLIFRecognizerp->commitedAlternativeStackSymbolp    = NULL;  /* Take care, it is pointer to internal _commitedAlternativeStackSymbolp if stack init is ok */
  marpaESLIFRecognizerp->lastPausepp                        = NULL;
  marpaESLIFRecognizerp->lastTrypp                          = NULL;
  marpaESLIFRecognizerp->set2InputStackp                    = NULL;  /* Take care, it is pointer to internal _set2InputStackp if stack init is ok */
  marpaESLIFRecognizerp->namesArrayp                        = NULL;
  marpaESLIFRecognizerp->namesArrayAllocl                   = 0;
  marpaESLIFRecognizerp->discardEventStatebp                = NULL;
  marpaESLIFRecognizerp->beforeEventStatebp                 = NULL;
  marpaESLIFRecognizerp->afterEventStatebp                  = NULL;
  marpaESLIFRecognizerp->discardOnOffb                      = 1; /* By default :discard is enabled */
  marpaESLIFRecognizerp->pristineb                          = 1; /* Until at least one alternative was pushed */
  marpaESLIFRecognizerp->previousMaxMatchedl                = 0;
  marpaESLIFRecognizerp->lastSizel                          = 0;
  marpaESLIFRecognizerp->maxStartCompletionsi               = maxStartCompletionsi;
  marpaESLIFRecognizerp->lastSizeBeforeCompletionl          = 0;
  marpaESLIFRecognizerp->atStartCompletionb                 = 0;
  marpaESLIFRecognizerp->startCompletionl                   = 0;
  marpaESLIFRecognizerp->cumulCompletionl                   = 0;
  marpaESLIFRecognizerp->numberOfStartCompletionsi          = 0;
  marpaESLIFRecognizerp->nTerminalPristinel                 = 0;
  marpaESLIFRecognizerp->terminalIdArrayPristinep           = NULL;
  marpaESLIFRecognizerp->terminalArrayPristinepp            = NULL;
  marpaESLIFRecognizerp->lastDiscardl                       = 0;
  marpaESLIFRecognizerp->lastDiscards                       = NULL;
  marpaESLIFRecognizerp->actions                            = NULL;
  marpaESLIFRecognizerp->actionp                            = NULL;
  marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp    = NULL;
  marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp    = NULL;
  marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp     = NULL;
  marpaESLIFRecognizerp->marpaESLIFCalloutBlockp            = NULL;
  marpaESLIFRecognizerp->progressallocl                     = 0;
  marpaESLIFRecognizerp->progressp                          = NULL;
  marpaESLIFRecognizerp->luaprecompiledp                    = NULL;    /* Lua script source precompiled */
  marpaESLIFRecognizerp->luaprecompiledl                    = 0;    /* Lua script source precompiled length in byte */
  marpaESLIFRecognizerp->getContextActionp                  = NULL;
  marpaESLIFRecognizerp->setContextActionp                  = NULL;
  marpaESLIFRecognizerp->popContextActionp                  = NULL;
  marpaESLIFRecognizerp->marpaESLIFRecognizerSharedp        = NULL;
  marpaESLIFRecognizerp->last_discard_loopb                 = 0;
  marpaESLIFRecognizerp->genericLoggerp                     = NULL;

  marpaESLIFRecognizerp->genericLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIFRecognizer_loggerCallbackv, (void *) marpaESLIFRecognizerp, GENERICLOGGER_LOGLEVEL_TRACE);
  if (marpaESLIFRecognizerp->genericLoggerp == NULL) {
    goto err;
  }

  marpaWrapperRecognizerOption.genericLoggerp            = marpaESLIFp->marpaESLIFOption.genericLoggerp;
  marpaWrapperRecognizerOption.disableThresholdb         = marpaESLIFRecognizerOptionp->disableThresholdb;
  marpaWrapperRecognizerOption.exhaustionEventb          = marpaESLIFRecognizerOptionp->exhaustedb;

  if (! fakeb) {

    /* If the grammar has :eol or :sol anywhere, enforce newlineb option */
    if (grammarp->marpaESLIFGrammarp->hasEolPseudoTerminalb || grammarp->marpaESLIFGrammarp->hasSolPseudoTerminalb) {
      marpaESLIFRecognizerp->marpaESLIFRecognizerOption.newlineb = 1;
    }

    /* Call functions that initialize vital memory areas  */
    if (MARPAESLIF_UNLIKELY((! _marpaESLIFRecognizer_createDiscardStateb(marpaESLIFRecognizerp))
                            ||
                            (! _marpaESLIFRecognizer_createBeforeStateb(marpaESLIFRecognizerp))
                            ||
                            (! _marpaESLIFRecognizer_createAfterStateb(marpaESLIFRecognizerp))
                            ||
                            (! _marpaESLIFRecognizer_createLastPauseb(marpaESLIFRecognizerp))
                            ||
                            (! _marpaESLIFRecognizer_createLastTryb(marpaESLIFRecognizerp)))) {
      goto err;
    }

    if (discardb) {
      marpaESLIFRecognizerp->marpaWrapperGrammarp     = noEventb ? grammarp->marpaWrapperGrammarDiscardNoEventp : grammarp->marpaWrapperGrammarDiscardp;
      marpaESLIFRecognizerp->nTerminalPristinel       = grammarp->nTerminalDiscardPristinel;
      marpaESLIFRecognizerp->terminalIdArrayPristinep = grammarp->terminalIdArrayDiscardPristinep;
      marpaESLIFRecognizerp->terminalArrayPristinepp  = grammarp->terminalArrayDiscardPristinepp;
    } else {
      marpaESLIFRecognizerp->marpaWrapperGrammarp     = noEventb ? grammarp->marpaWrapperGrammarStartNoEventp : grammarp->marpaWrapperGrammarStartp;
      marpaESLIFRecognizerp->nTerminalPristinel       = grammarp->nTerminalPristinel;
      marpaESLIFRecognizerp->terminalIdArrayPristinep = grammarp->terminalIdArrayPristinep;
      marpaESLIFRecognizerp->terminalArrayPristinepp  = grammarp->terminalArrayPristinepp;
    }

    marpaESLIFRecognizerp->marpaWrapperRecognizerp = marpaWrapperRecognizer_newp(marpaESLIFRecognizerp->marpaWrapperGrammarp, &marpaWrapperRecognizerOption);
    if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp->marpaWrapperRecognizerp == NULL)) {
      goto err;
    }
    /* Set-up initial event states - Inside Marpa this will be a no-op if the symbol was not set with support of the wanted event */
    /* We know this is a global no-op if we are in the no-event mode */
    symbolStackp = grammarp->symbolStackp;

    marpaESLIFRecognizerp->isExpectedArraybl = sizeof(int) * GENERICSTACK_USED(symbolStackp);
    if (marpaESLIFp->ZeroIntegerisZeroBytesb) {
      /* Use calloc to initialize the array */
      marpaESLIFRecognizerp->isExpectedArraybp = (int *) calloc(sizeof(int), GENERICSTACK_USED(symbolStackp));
      if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp->isExpectedArraybp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "calloc failure, %s", strerror(errno));
        goto err;
      }
    } else {
      marpaESLIFRecognizerp->isExpectedArraybp = (int *) malloc(marpaESLIFRecognizerp->isExpectedArraybl);
      if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp->isExpectedArraybp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
        marpaESLIFRecognizerp->isExpectedArraybp[symboli] = 0;
      }
    }

    if (! noEventb) {

      for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
        MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFp, symbolp, grammarp, symboli);
        if (symbolp->eventPredicteds != NULL) {
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs,
                                      "Setting prediction event state for symbol %d <%s> at grammar level %d (%s) to %s (recognizer discard mode: %d)",
                                      symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis, discardb ? "off" : (symbolp->eventPredictedb ? "on" : "off"), (int) discardb);
          if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_event_onoffb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, symbolp->idi, MARPAWRAPPERGRAMMAR_EVENTTYPE_PREDICTION, discardb ? 0 : symbolp->eventPredictedb))) {
            goto err;
          }
        }
        if (symbolp->eventNulleds != NULL) {
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs,
                                      "Setting nulled event state for symbol %d <%s> at grammar level %d (%s) to %s (recognizer discard mode: %d)",
                                      symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis, discardb ? "off" : (symbolp->eventNulledb ? "on" : "off"), (int) discardb);
          if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_event_onoffb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, symbolp->idi, MARPAWRAPPERGRAMMAR_EVENTTYPE_NULLED, discardb ? 0 : symbolp->eventNulledb))) {
            goto err;
          }
        }
        if (discardb) {
          /* Discard event is a special beast: it is a sub-recognizer, but the event setting is done at the top recognizer level. */
          /* In addition the current grammar (grammarp pointer) of a discard grammar always have the exact same symbols than the */
          /* current grammar of its parent, because this is the same grammar, though precomputed with a different start symbol -; */

          /* It is a non-sense to have discardb to true without a parent recognizer */
          if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerParentp == NULL)) {
            MARPAESLIF_ERROR(marpaESLIFp, "Discard mode called without a parent recognizer");
            goto err;
          }
          if (symbolp->discardEvents != NULL) {
            discardEventb = marpaESLIFRecognizerParentp->discardEventStatebp[symbolp->idi];
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs,
                                        "Setting :discard completion event state for symbol %d <%s> at grammar level %d (%s) to %s (recognizer discard mode: %d)",
                                        symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis, discardEventb ? "on" : "off", (int) discardb);
            if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_event_onoffb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, symbolp->idi, MARPAWRAPPERGRAMMAR_EVENTTYPE_COMPLETION, discardEventb))) {
              goto err;
            }
          }
        } else {
          if (symbolp->eventCompleteds != NULL) {
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs,
                                        "Setting completion event state for symbol %d <%s> at grammar level %d (%s) to %s (recognizer discard mode: %d)",
                                        symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis, discardb ? "off" : (symbolp->eventCompletedb ? "on" : "off"), (int) discardb);
            if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_event_onoffb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, symbolp->idi, MARPAWRAPPERGRAMMAR_EVENTTYPE_COMPLETION, discardb ? 0 : symbolp->eventCompletedb))) {
              goto err;
            }
          }
        }
      }
    } else {
      /* Events outside of marpa that need to be switched off: "before" and "after", except for grammar hooks at the top level (i.e. :discard[on/off/switch]) that keep their initial state as per the grammar */
      for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
        MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFp, symbolp, grammarp, symboli);
        if (symbolp->eventBefores != NULL) {
          if ((marpaESLIFRecognizerParentp != NULL) || (strstr(symbolp->eventBefores, ":discard[") == NULL)) {
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs,
                                        "Setting \"before\" event state for symbol %d <%s> at grammar level %d (%s) to off (recognizer discard mode: %d)",
                                        symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis, (int) discardb);
            marpaESLIFRecognizerp->beforeEventStatebp[symbolp->idi] = 0;
          }
        }
        if (symbolp->eventAfters != NULL) {
          if ((marpaESLIFRecognizerParentp != NULL) || (strstr(symbolp->eventAfters, ":discard[") == NULL)) {
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs,
                                        "Setting \"after\" event state for symbol %d <%s> at grammar level %d (%s) to off (recognizer discard mode: %d)",
                                        symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis, (int) discardb);
            marpaESLIFRecognizerp->afterEventStatebp[symbolp->idi] = 0;
          }
        }
      }
    }
  } else {
    marpaESLIFRecognizerp->marpaWrapperGrammarp         = NULL;
    marpaESLIFRecognizerp->marpaWrapperRecognizerp      = NULL;
    marpaESLIFRecognizerp->discardEventStatebp          = NULL;
    marpaESLIFRecognizerp->beforeEventStatebp           = NULL;
    marpaESLIFRecognizerp->afterEventStatebp            = NULL;
    marpaESLIFRecognizerp->lastPausepp                  = NULL;
    marpaESLIFRecognizerp->lastTrypp                    = NULL;
  }

  marpaESLIFRecognizerp->alternativeStackSymbolp = &(marpaESLIFRecognizerp->_alternativeStackSymbol);
  GENERICSTACK_INIT(marpaESLIFRecognizerp->alternativeStackSymbolp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerp->alternativeStackSymbolp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "alternativeStackSymbolp initialization failure, %s", strerror(errno));
    marpaESLIFRecognizerp->alternativeStackSymbolp = NULL;
    goto err;
  }

  marpaESLIFRecognizerp->commitedAlternativeStackSymbolp = &(marpaESLIFRecognizerp->_commitedAlternativeStackSymbol);
  GENERICSTACK_INIT(marpaESLIFRecognizerp->commitedAlternativeStackSymbolp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerp->commitedAlternativeStackSymbolp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "commitedAlternativeStackSymbolp initialization failure, %s", strerror(errno));
    marpaESLIFRecognizerp->commitedAlternativeStackSymbolp = NULL;
    goto err;
  }

  /* The mapping of earley set to pointer and length in input is available only if trackb is true */
  if (marpaESLIFRecognizerp->marpaESLIFRecognizerOption.trackb) {
    marpaESLIFRecognizerp->set2InputStackp = &(marpaESLIFRecognizerp->_set2InputStack);
    GENERICSTACK_INIT(marpaESLIFRecognizerp->set2InputStackp);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerp->set2InputStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "set2InputStackp initialization failure, %s", strerror(errno));
      marpaESLIFRecognizerp->set2InputStackp = NULL;
      goto err;
    }
  }

  marpaESLIFRecognizerp->lexemeStackp = &(marpaESLIFRecognizerp->_lexemeStack);
  GENERICSTACK_INIT(marpaESLIFRecognizerp->lexemeStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerp->lexemeStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "lexemeStackp initialization failure, %s", strerror(errno));
    marpaESLIFRecognizerp->lexemeStackp = NULL;
    goto err;
  }

  /* Marpa does not like the indice 0 */
  GENERICSTACK_PUSH_NA(marpaESLIFRecognizerp->lexemeStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerp->lexemeStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "lexemeStackp push failure, %s", strerror(errno));
    goto err;
  }

  if (marpaESLIFRecognizerp->marpaESLIFRecognizerHashp == NULL) {
    marpaESLIFRecognizerp->marpaESLIFRecognizerHashp = &(marpaESLIFRecognizerp->_marpaESLIFRecognizerHash);
    GENERICHASH_INIT_ALL(marpaESLIFRecognizerp->marpaESLIFRecognizerHashp,
                         _marpaESLIF_ptrhashi,
                         NULL, /* keyCmpFunctionp */
                         NULL, /* keyCopyFunctionp */
                         NULL, /* keyFreeFunctionp */
                         NULL, /* valCopyFunctionp */
                         _marpaESLIFRecognizerHash_free_callbackv,
                         MARPAESLIF_HASH_SIZE,
                         0 /* wantedSubSize */);
    if (MARPAESLIF_UNLIKELY(GENERICHASH_ERROR(marpaESLIFRecognizerp->marpaESLIFRecognizerHashp))) {
      MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFRecognizerHashp init failure, %s", strerror(errno));
      marpaESLIFRecognizerp->marpaESLIFRecognizerHashp = NULL;
      goto err;
    }
  }

  if (marpaESLIFRecognizerp->marpaESLIF_streamp == NULL) {
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_stream_initb(marpaESLIFRecognizerp, marpaESLIFRecognizerOptionp->bufsizl, marpaESLIFRecognizerOptionp->buftriggerperci, (marpaESLIFRecognizerOptionp->readerCallbackp != NULL) ? fakeb : 1 /* eofb */, utfb))) {
      goto err;
    }
    marpaESLIFRecognizerp->marpaESLIF_streamp = &(marpaESLIFRecognizerp->_marpaESLIF_stream);
  }

  marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard                   = marpaESLIFRecognizerp->marpaESLIFRecognizerOption;
  marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard.disableThresholdb = 1;
  marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard.exhaustedb        = 1;
  marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard.newlineb          = 0;
  marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard.trackb            = 0;
  marpaESLIFRecognizerp->marpaESLIFValueOptionDiscard                        = marpaESLIFValueOption_default_template;
  marpaESLIFRecognizerp->marpaESLIFValueOptionDiscard.ambiguousb             = 1;
  marpaESLIFRecognizerp->marpaESLIFValueOptionDiscard.userDatavp             = (void *) marpaESLIFRecognizerp;

  marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp = &(marpaESLIFRecognizerp->_marpaESLIFValueResultWorkStack);
  GENERICSTACK_INIT(marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp initialization failure, %s", strerror(errno));
    marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp = NULL;
    goto err;
  }

  marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp = &(marpaESLIFRecognizerp->_marpaESLIFValueResultStackOrig);
  GENERICSTACK_INIT(marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp))) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp initialization failure, %s", strerror(errno));
    marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp = NULL;
    goto err;
  }

  marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp = &(marpaESLIFRecognizerp->_marpaESLIFValueResultStackNew);
  GENERICSTACK_INIT(marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp))) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp initialization failure, %s", strerror(errno));
    marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp = NULL;
    goto err;
  }

  _marpaESLIFCalloutBlock_initb(marpaESLIFRecognizerp);
  goto done;

 err:
  /* Creating a recognizer should never fail */
  if (marpaESLIFRecognizerp != NULL) {
    _marpaESLIFRecognizer_freev(marpaESLIFRecognizerp, 1 /* forceb */);
  }
  marpaESLIFRecognizerp = NULL;

 done:
#ifndef MARPAESLIF_NTRACE
  /*
  if (marpaESLIFRecognizerParentp != NULL) {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerParentp, funcs, "return %p", marpaESLIFRecognizerp);
  } else {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", marpaESLIFRecognizerp);
  }
  */
#endif
  return marpaESLIFRecognizerp;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_shareb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFRecognizer_t *marpaESLIFRecognizerSharedp)
/*****************************************************************************/
{
  static const char *funcs  = "_marpaESLIFRecognizer_shareb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (marpaESLIFRecognizerSharedp == NULL) {
    if (marpaESLIFRecognizerp->marpaESLIFRecognizerSharedp == NULL) {
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "No recognizer to unshare");
      goto err;
    }
    /* Unshare */
    marpaESLIFRecognizerp->marpaESLIF_streamp          = &(marpaESLIFRecognizerp->_marpaESLIF_stream);
    marpaESLIFRecognizerp->marpaESLIFRecognizerSharedp = NULL;
  } else {
    /* Share */
    if (marpaESLIFRecognizerp->marpaESLIFRecognizerSharedp != NULL) {
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "A recognizer is already shared");
      goto err;
    }
    marpaESLIFRecognizerp->marpaESLIF_streamp          = marpaESLIFRecognizerSharedp->marpaESLIF_streamp;
    marpaESLIFRecognizerp->marpaESLIFRecognizerSharedp = marpaESLIFRecognizerSharedp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_peekb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFRecognizer_t *marpaESLIFRecognizerPeekedp)
/*****************************************************************************/
{
  static const char      *funcs                       = "_marpaESLIFRecognizer_peekb";
  marpaESLIFRecognizer_t *marpaESLIFRecognizerSharedp = marpaESLIFRecognizerp->marpaESLIFRecognizerSharedp;
  unsigned int            peeki;
  short                   rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Apply share/Unshare */
  if (! _marpaESLIFRecognizer_shareb(marpaESLIFRecognizerp, marpaESLIFRecognizerPeekedp)) {
    goto err;
  }

  if (marpaESLIFRecognizerPeekedp == NULL) {
    /* _marpaESLIFRecognizer_shareb made sure that marpaESLIFRecognizerSharedp is set */
    peeki = marpaESLIFRecognizerSharedp->marpaESLIF_streamp->peeki;
    if (--peeki > marpaESLIFRecognizerSharedp->marpaESLIF_streamp->peeki) {
      MARPAESLIF_WARN(marpaESLIFRecognizerp->marpaESLIFp, "Too many stream unpeeks");
    } else {
      marpaESLIFRecognizerSharedp->marpaESLIF_streamp->peeki = peeki;
    }
  } else {
    /* marpaESLIFRecognizerPeekedp and marpaESLIFRecognizerp share the same stream */
    peeki = marpaESLIFRecognizerPeekedp->marpaESLIF_streamp->peeki;
    if (++peeki < marpaESLIFRecognizerPeekedp->marpaESLIF_streamp->peeki) {
      MARPAESLIF_WARN(marpaESLIFRecognizerp->marpaESLIFp, "Too many stream peeks");
    } else {
      marpaESLIFRecognizerPeekedp->marpaESLIF_streamp->peeki = peeki;
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline marpaESLIFRecognizer_t *_marpaESLIFRecognizer_newFromp(marpaESLIF_grammar_t *grammarp, marpaESLIFRecognizer_t *marpaESLIFRecognizerSharedp, short discardb, short noEventb, short silentb)
/*****************************************************************************/
{
  marpaESLIFRecognizer_t  *marpaESLIFRecognizerp = NULL;
  marpaESLIFValueResult_t  context               = marpaESLIFValueResultUndef;
  marpaESLIFRecognizer_t  *marpaESLIFRecognizerUnsharedTopp;

  marpaESLIFRecognizerp = _marpaESLIFRecognizer_newp(marpaESLIFRecognizerSharedp->marpaESLIFp,
                                                     grammarp,
                                                     &(marpaESLIFRecognizerSharedp->marpaESLIFRecognizerOption),
                                                     discardb,
                                                     noEventb,
                                                     silentb);
  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    goto err;
  }

  /* If the grammar is already using the lua_State because of another recognizer, recuperate current context */
  marpaESLIFRecognizerUnsharedTopp = grammarp->Lsharep->marpaESLIFRecognizerUnsharedTopp;
  if (marpaESLIFRecognizerUnsharedTopp != NULL) {
    if (MARPAESLIF_UNLIKELY(_marpaESLIFRecognizer_context_getp(marpaESLIFRecognizerUnsharedTopp, &context) == NULL)) {
      goto err;
    }

    /* Store it at our indice 0 */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_lexemeStack_i_setb(marpaESLIFRecognizerp, 0, &context))) {
      goto err;
    }
  }
  
  if (! _marpaESLIFRecognizer_shareb(marpaESLIFRecognizerp, marpaESLIFRecognizerSharedp)) {
    goto err;
  }

  goto done;

 err:
  marpaESLIFRecognizer_freev(marpaESLIFRecognizerp);
  marpaESLIFRecognizerp = NULL;

 done:
  return marpaESLIFRecognizerp;
}

/*****************************************************************************/
marpaESLIFRecognizer_t *marpaESLIFRecognizer_newFromp(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFRecognizer_t *marpaESLIFRecognizerSharedp)
/*****************************************************************************/
{
  marpaESLIFRecognizer_t *marpaESLIFRecognizerp = NULL;

  if ((marpaESLIFGrammarp == NULL) || (marpaESLIFRecognizerSharedp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  marpaESLIFRecognizerp = _marpaESLIFRecognizer_newFromp(marpaESLIFGrammarp->grammarp, marpaESLIFRecognizerSharedp, 0 /* discardb */, 0 /* noEventb */, 0 /* silentb */);
  goto done;

 err:
  marpaESLIFRecognizer_freev(marpaESLIFRecognizerp);
  marpaESLIFRecognizerp = NULL;

 done:
  return marpaESLIFRecognizerp;
}

/*****************************************************************************/
short marpaESLIFRecognizer_set_exhausted_flagb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short exhaustedb)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_set_exhausted_flagb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIFRecognizerp->marpaESLIFRecognizerOption.exhaustedb = exhaustedb;
  rcb = 1;
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isExhaustedbp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_isExhaustedb";
  short              isExhaustedb;
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Are we forcing an exhaustion event ? */
  if (marpaESLIFRecognizerp->forceExhaustedb) {
    isExhaustedb = 1;
  } else {
    /* Ask directly to the recognizer */
    if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_exhaustedb(marpaESLIFRecognizerp->marpaWrapperRecognizerp, &isExhaustedb))) {
      goto err;
    }
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "isExhaustedb=%d", (int) isExhaustedb);
  if (isExhaustedbp != NULL) {
    *isExhaustedbp = isExhaustedb;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_isCanContinueb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isCanContinuebp, short *eofbp, short *isExhaustedbp)
/*****************************************************************************/
{
  static const char   *funcs          = "_marpaESLIFRecognizer_isCanContinueb";
  short                isExhaustedb   = -1; /* To detect if it was fetched */
  short                eofb           = -1; /* To detect if it was fetched */
  short                isCanContinueb;
  size_t               inputl;
  short                isZeroLengthLexemeExpectedb;
  short                rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "marpaESLIFRecognizerp->cannotcontinueb=%d, marpaESLIFRecognizerp->maxStartCompletionsi=%d, marpaESLIFRecognizerp->numberOfStartCompletionsi=%ld", (int) marpaESLIFRecognizerp->cannotcontinueb, marpaESLIFRecognizerp->maxStartCompletionsi, (unsigned long) marpaESLIFRecognizerp->numberOfStartCompletionsi);

  /* For the internal cases that have absolute priority */
  if (marpaESLIFRecognizerp->cannotcontinueb) {
    /* Discard failed but lexemes were read */
    isCanContinueb = 0;
  } else if ((marpaESLIFRecognizerp->maxStartCompletionsi > 0) && (marpaESLIFRecognizerp->numberOfStartCompletionsi >= marpaESLIFRecognizerp->maxStartCompletionsi)) {
    isCanContinueb = 0;
  } else {
    /* We cannot continue if grammar is exhausted or (eof is reached and all data is consumed unless :eof is expected) */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizerp, &isExhaustedb))) {
      goto err;
    }
    if (isExhaustedb) {
      isCanContinueb = 0;
    } else {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isEofb(marpaESLIFRecognizerp, &eofb))) {
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_inputb(marpaESLIFRecognizerp, NULL, &inputl))) {
        goto err;
      }
      if (eofb && (inputl <= 0)) {
        /* False unless a pseudo terminal is expected */
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isZeroLengthLexemeExpectedb(marpaESLIFRecognizerp, &isZeroLengthLexemeExpectedb))) {
          goto err;
        }
        isCanContinueb = isZeroLengthLexemeExpectedb;
      } else {
        isCanContinueb = 1;
      }
    }
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "isCanContinueb=%d", (int) isCanContinueb);
  if (isCanContinuebp != NULL) {
    *isCanContinuebp = isCanContinueb;
  }

  if (eofbp != NULL) {
    if (eofb == -1) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isEofb(marpaESLIFRecognizerp, eofbp))) {
        goto err;
      }
    } else {
      *eofbp = eofb;
    }
  }

  if (isExhaustedbp != NULL) {
    if (isExhaustedb == -1) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizerp, isExhaustedbp))) {
        goto err;
      }
    } else {
      *isExhaustedbp = isExhaustedb;
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_isCanContinueb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isCanContinuebp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_isCanContinueb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_isCanContinueb(marpaESLIFRecognizerp, isCanContinuebp, NULL /* eofbp */, NULL /* exhautedbp */);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *isExhaustedbp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_isExhaustedb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_isExhaustedb(marpaESLIFRecognizerp, isExhaustedbp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short __marpaESLIFRecognizer_discardb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t minl, size_t *discardlp, short appendEventb)
/*****************************************************************************/
/* Note that we made sure that discardlp is never NULL in any caller.        */
/* appendEventb will prevent clearing the events. This can happen only once  */
/* in the lifetime of a recognizer: discarding remaining bytes of an         */
/* exhausted grammar.                                                        */
/*****************************************************************************/
{
  static const char       *funcs                 = "__marpaESLIFRecognizer_discardb";
  marpaESLIFValueResult_t  marpaESLIFValueResult = marpaESLIFValueResultUndef;
  short                    isDiscardExpectedb;
  short                    noEventb;
  size_t                   discardl;
  size_t                   fastDiscardl;
  marpaESLIF_symbol_t     *fastDiscardSymbolp;
  short                    parseb;
  short                    rcb;

  if (marpaESLIFRecognizerp->discardb) {
    /* We are already inside :discard */
    *discardlp = 0;
    rcb = 1;
    goto fast_done;
  }

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_isDiscardExpectedb(marpaESLIFRecognizerp, &isDiscardExpectedb, &fastDiscardl, &fastDiscardSymbolp, &marpaESLIFValueResult))) {
    goto err;
  }

  if (isDiscardExpectedb) {
    noEventb = marpaESLIFRecognizerp->noEventb;
    discardl = 0;

    if (! noEventb) {
      /* Reset discardEvents and discardSymbolp */
      marpaESLIFRecognizerp->discardEvents  = NULL;
      marpaESLIFRecognizerp->discardSymbolp = NULL;
      marpaESLIFRecognizerp->discardEvente  = MARPAESLIF_INTERNAL_EVENT_ACTION_NA;
    }

    if (fastDiscardl > 0) {
      /* match already done in the current context */
      parseb = 1;
      discardl = fastDiscardl;
      if (! noEventb) {
        /* fastDiscardSymbolp is not NULL per definition */
        marpaESLIFRecognizerp->discardEvents  = fastDiscardSymbolp->discardEvents;
        marpaESLIFRecognizerp->discardSymbolp = fastDiscardSymbolp;
        marpaESLIFRecognizerp->discardEvente  = fastDiscardSymbolp->discardEvente;
      }
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Fast discard on %ld bytes", (unsigned long) discardl);
    } else {
      parseb = _marpaESLIFGrammar_parseb(marpaESLIFRecognizerp->marpaESLIFp,
                                         marpaESLIFRecognizerp->grammarp,
                                         &(marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard),
                                         &(marpaESLIFRecognizerp->marpaESLIFValueOptionDiscard),
                                         1, /* discardb */
                                         noEventb, /* This will select marpaWrapperGrammarDiscardNoEventp or marpaWrapperGrammarDiscardp */
                                         1, /* silentb */
                                         marpaESLIFRecognizerp, /* marpaESLIFRecognizerParentp */
                                         NULL, /* isExhaustedbp */
                                         &marpaESLIFValueResult,
                                         0, /* maxStartCompletionsi */
                                         NULL, /* lastSizeBeforeCompletionlp */
                                         NULL /* numberOfStartCompletionsip */,
                                         0, /* verboseb */
                                         &discardl,
                                         1 /* isLexemeb - we are only interested by the number of bytes consumed */);
    }

    if (parseb) {
      if (discardl > minl) {
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Discard successful on %ld bytes", (unsigned long) discardl);

        if (! noEventb) {
          /* We want to do as if we would have done a lexeme complete before */
          if (! appendEventb) {
            _marpaESLIFRecognizer_clear_all_eventsb(marpaESLIFRecognizerp);
          }
          if ((marpaESLIFRecognizerp->discardEvents != NULL) && (marpaESLIFRecognizerp->discardSymbolp != NULL)) {
            /* Push discard event */
            if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_push_eventb(marpaESLIFRecognizerp, MARPAESLIF_EVENTTYPE_DISCARD, marpaESLIFRecognizerp->discardSymbolp, marpaESLIFRecognizerp->discardEvents, marpaESLIFRecognizerp->marpaESLIF_streamp->inputs, discardl, marpaESLIFRecognizerp->discardEvente))) {
              goto err;
            }
          }
          if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_push_grammar_eventsb(marpaESLIFRecognizerp))) {
            goto err;
          }
        }

        /* New line processing, etc... */
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_matchPostProcessingb(marpaESLIFRecognizerp, discardl))) {
          goto err;
        }

      } else {
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Discard rejected: %ld bytes < %ld bytes", (unsigned long) discardl, (unsigned long) minl);
        discardl = 0;
      }
    } else {
      MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Discard parse failure");
      discardl = 0;
    }
  } else {
    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "No discard expected");
    discardl = 0;
  }

  *discardlp = discardl;
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, &marpaESLIFValueResult, 1 /* deepb */);
  /* In any case we not in discard mode anymore */
  marpaESLIFRecognizerp->discardb = 0;

 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFGrammar_parseb(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, marpaESLIFRecognizerOption_t *marpaESLIFRecognizerOptionp, marpaESLIFValueOption_t *marpaESLIFValueOptionp, short discardb, short noEventb, short silentb, marpaESLIFRecognizer_t *marpaESLIFRecognizerParentp, short *isExhaustedbp, marpaESLIFValueResult_t *marpaESLIFValueResultp, int maxStartCompletionsi, size_t *lastSizeBeforeCompletionlp, int *numberOfStartCompletionsip, short verboseb, size_t *matchedLengthlp, short isLexemeb)
/*****************************************************************************/
/* Note that consumed is set only when there is parent recognizer.           */
/*****************************************************************************/
{
  static const char      *funcs                 = "_marpaESLIFGrammar_parseb";
  marpaESLIFRecognizer_t *marpaESLIFRecognizerp = NULL;
  marpaESLIFValueOption_t marpaESLIFValueOption = (marpaESLIFValueOptionp != NULL) ? *marpaESLIFValueOptionp : marpaESLIFValueOption_default_template;
  marpaESLIFValue_t      *marpaESLIFValuep      = NULL;
  short                   isExhaustedb;
  short                   canContinueb;
  short                   rcb;

  marpaESLIFRecognizerp = __marpaESLIFRecognizer_newp(marpaESLIFp,
						      grammarp,
						      marpaESLIFRecognizerOptionp,
						      discardb,
						      noEventb,
						      silentb,
						      marpaESLIFRecognizerParentp,
						      0, /* fakeb */
						      maxStartCompletionsi,
						      (marpaESLIFRecognizerParentp != NULL) ? marpaESLIFRecognizerParentp->marpaESLIF_streamp->utfb : 0, /* utfb */
                                                      isLexemeb);
  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_scanb(marpaESLIFRecognizerp, noEventb ? 0 : 1 /* initialEventsb */, &canContinueb, &isExhaustedb))) {
    goto err;
  }
  while (canContinueb) {
    if (MARPAESLIF_UNLIKELY(! __marpaESLIFRecognizer_resumeb(marpaESLIFRecognizerp, 0 /* deltaLengthl */, 0 /* initialEventsb */, &canContinueb, &isExhaustedb))) {
#ifndef MARPAESLIF_NTRACE
      MARPAESLIF_TRACE(marpaESLIFp, funcs, "Resume failure");
#endif
      goto err;
    }
#ifndef MARPAESLIF_NTRACE
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "canContinueb=%d, isExhaustedb=%d", canContinueb, isExhaustedb);
#endif
  }

  /* If there is no parent, force unambiguity. Else this is the lexeme mode, and all we want to know is if */
  /* it valuates. In the later case, if the answer is yes there is no need to call for valuation: per def  */
  /* the value is the stream that matched.                                                                 */

  /* When there is a parent there are two cases: a true lexeme or not. In case of a true lexeme, all we    */
  /* want to know is the number of bytes consumed up to latest completion.                                 */
  if (isLexemeb) {
    /* We are called by _marpaESLIFRecognizer_meta_matcherb() by definition. The later will take care */
    /* to propagage a marpaESLIFValueResult of type OFFSET_AND_LENGTH or to convert it to type ARRAY. */
    if (marpaESLIFRecognizerp->numberOfStartCompletionsi <= 0) {
      /* No completion: this can happen only if we allow a nullable parse */
      if (! marpaESLIFValueOption.nullb) {
        errno = EINVAL;
	goto err;
      }
      if (marpaESLIFValueResultp != NULL) {
        marpaESLIFValueResultp->contextp           = NULL;
        marpaESLIFValueResultp->representationp    = NULL;
        marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH;
        marpaESLIFValueResultp->u.o.p              = marpaESLIFRecognizerp->parentDeltal;
        marpaESLIFValueResultp->u.o.sizel          = 0;
      }
    } else {
      if (marpaESLIFValueResultp != NULL) {
        marpaESLIFValueResultp->contextp           = NULL;
        marpaESLIFValueResultp->representationp    = NULL;
        marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH;
        marpaESLIFValueResultp->u.o.p              = marpaESLIFRecognizerp->parentDeltal;
        marpaESLIFValueResultp->u.o.sizel          = marpaESLIFRecognizerp->startCompletionl;
      }
    }
  } else {
    /* True valuation */
    marpaESLIFValueOption.ambiguousb = (marpaESLIFRecognizerParentp != NULL) ? 1 : 0;
    marpaESLIFValuep = _marpaESLIFValue_newp(marpaESLIFRecognizerp, &marpaESLIFValueOption, silentb, 0 /* fakeb */, isLexemeb);
    if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
      goto err;
    }

    /* No loop because we asked either for a non-ambigous parse tree value, either _marpaESLIFValue_valueb enters a hook that */
    /* knows we are in a lexeme mode (marpaESLIFRecognizerParentp != NULL).                                                   */
    if (MARPAESLIF_UNLIKELY(_marpaESLIFValue_valueb(marpaESLIFValuep, marpaESLIFValueResultp) <= 0)) {
      goto err;
    }
  }

  rcb = 1;

  if (isExhaustedbp != NULL) {
    *isExhaustedbp = isExhaustedb;
  }
  if (lastSizeBeforeCompletionlp != NULL) {
    /* If we get here, then marpaESLIFRecognizerp is != NULL */
    *lastSizeBeforeCompletionlp = marpaESLIFRecognizerp->lastSizeBeforeCompletionl;
  }
  if (numberOfStartCompletionsip != NULL) {
    *numberOfStartCompletionsip = marpaESLIFRecognizerp->numberOfStartCompletionsi;
  }
  if (matchedLengthlp != NULL) {
    *matchedLengthlp = marpaESLIFRecognizerp->startCompletionl;
  }

  goto done;
  
 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  marpaESLIFValue_freev(marpaESLIFValuep);

#ifndef MARPAESLIF_NTRACE
  if (marpaESLIFRecognizerp != NULL) {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  } else {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %d", (int) rcb);
  }
#endif
  if (marpaESLIFRecognizerp != NULL) {
    if ((! rcb) && silentb && verboseb) {
      _marpaESLIFRecognizer_errorv(marpaESLIFRecognizerp);
    }
    marpaESLIFRecognizer_freev(marpaESLIFRecognizerp);
  }

  return rcb;
}

/*****************************************************************************/
static void _marpaESLIF_generateStringWithLoggerCallback(void *userDatavp, genericLoggerLevel_t logLeveli, const char *msgs)
/*****************************************************************************/
{
  _marpaESLIF_appendOpaqueDataToStringGenerator((marpaESLIF_stringGenerator_t *) userDatavp, (char *) msgs, strlen(msgs));
}

/*****************************************************************************/
static void _marpaESLIF_generateSeparatedStringWithLoggerCallback(void *userDatavp, genericLoggerLevel_t logLeveli, const char *msgs)
/*****************************************************************************/
{
  marpaESLIF_stringGenerator_t *contextp = (marpaESLIF_stringGenerator_t *) userDatavp;

  if (contextp->s == NULL) {
    /* First time */
    _marpaESLIF_appendOpaqueDataToStringGenerator((marpaESLIF_stringGenerator_t *) userDatavp, (char *) msgs, strlen(msgs));
  } else {
    if (_marpaESLIF_appendOpaqueDataToStringGenerator((marpaESLIF_stringGenerator_t *) userDatavp, (char *) "|", 1)) {
      _marpaESLIF_appendOpaqueDataToStringGenerator((marpaESLIF_stringGenerator_t *) userDatavp, (char *) msgs, strlen(msgs));
    }
  }
}

/*****************************************************************************/
static void _marpaESLIF_traceLoggerCallbackv(void *userDatavp, genericLoggerLevel_t logLeveli, const char *msgs)
/*****************************************************************************/
{
#ifndef MARPAESLIF_NTRACE
  static const char *funcs       = "_marpaESLIF_traceLoggerCallbackv";
  marpaESLIF_t      *marpaESLIFp = (marpaESLIF_t *) userDatavp;

  if (marpaESLIFp != NULL) {
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "%s", msgs);
  }
#endif
}

/*****************************************************************************/
static void _marpaESLIFRecognizer_loggerCallbackv(void *userDatavp, genericLoggerLevel_t logLeveli, const char *msgs)
/*****************************************************************************/
{
  marpaESLIFRecognizer_t *marpaESLIFRecognizerp = (marpaESLIFRecognizer_t *) userDatavp;

  if (! marpaESLIFRecognizerp->silentb) {
    if (marpaESLIFRecognizerp->marpaESLIFp->marpaESLIFOption.genericLoggerp != NULL) {
      GENERICLOGGER_LOG(marpaESLIFRecognizerp->marpaESLIFp->marpaESLIFOption.genericLoggerp, logLeveli, msgs);
    }
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_stringGeneratorInitv(marpaESLIF_t *marpaESLIFp, marpaESLIF_stringGenerator_t *marpaESLIF_stringGeneratorp)
/*****************************************************************************/
{
  marpaESLIF_stringGeneratorp->marpaESLIFp = marpaESLIFp;
  marpaESLIF_stringGeneratorp->s           = NULL;
  marpaESLIF_stringGeneratorp->l           = 0;
  marpaESLIF_stringGeneratorp->okb         = 0;
  marpaESLIF_stringGeneratorp->allocl      = 0;
}

/*****************************************************************************/
static inline void _marpaESLIF_stringGeneratorResetv(marpaESLIF_stringGenerator_t *marpaESLIF_stringGeneratorp)
/*****************************************************************************/
{
  /* If not NULL, it has already be in used */
  if (marpaESLIF_stringGeneratorp->s != NULL) {
    /* It is equivalent to the empty string */
    marpaESLIF_stringGeneratorp->s[0] = '\0';
    marpaESLIF_stringGeneratorp->l    = 1;
    marpaESLIF_stringGeneratorp->okb  = 1;
  } else {
    marpaESLIF_stringGeneratorp->l   = 0;
    marpaESLIF_stringGeneratorp->okb = 0;
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_stringGeneratorFreev(marpaESLIF_stringGenerator_t *marpaESLIF_stringGeneratorp, short onStackb)
/*****************************************************************************/
{
  if (marpaESLIF_stringGeneratorp->s != NULL) {
    free(marpaESLIF_stringGeneratorp->s);
  }
  if (! onStackb) {
    free(marpaESLIF_stringGeneratorp);
  } else {
    marpaESLIF_stringGeneratorp->s      = NULL;
    marpaESLIF_stringGeneratorp->l      = 0;
    marpaESLIF_stringGeneratorp->okb    = 0;
    marpaESLIF_stringGeneratorp->allocl = 0;
  }
}

/*****************************************************************************/
static inline short _marpaESLIF_appendOpaqueDataToStringGenerator(marpaESLIF_stringGenerator_t *marpaESLIF_stringGeneratorp, char *p, size_t sizel)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIF_appendOpaqueDataToStringGenerator";
  char              *tmpp;
  short              rcb;
  size_t             allocl;
  size_t             wantedl;

  /* Note: caller must guarantee that marpaESLIF_stringGeneratorp->marpaESLIFp, p != NULL and l > 0 */

  if (marpaESLIF_stringGeneratorp->s == NULL) {
    /* Get an allocl that is a multiple of 1024, taking into account the hiden NUL byte */
    /* 1023 -> 1024 */
    /* 1024 -> 2048 */
    /* 2047 -> 2048 */
    /* 2048 -> 3072 */
    /* ... */
    /* i.e. this is the upper multiple of 1024 and have space for the NUL byte */
    allocl = MARPAESLIF_CHUNKED_SIZE_UPPER(sizel, 1024);
    /* Check for turn-around, should never happen */
    if (MARPAESLIF_UNLIKELY(allocl < sizel)) {
      MARPAESLIF_ERROR(marpaESLIF_stringGeneratorp->marpaESLIFp, "size_t turnaround detected");
      goto err;
    }
    marpaESLIF_stringGeneratorp->s  = (char *) malloc(allocl);
    if (MARPAESLIF_UNLIKELY(marpaESLIF_stringGeneratorp->s == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIF_stringGeneratorp->marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    if (sizel > 0) {
      /* In theory, every memcpy() implementation should be protected if sizel == 0, though this is since C99 */
      memcpy(marpaESLIF_stringGeneratorp->s, p, sizel);
    }
    marpaESLIF_stringGeneratorp->l      = sizel + 1;  /* NUL byte is set at exit of the routine */
    marpaESLIF_stringGeneratorp->allocl = allocl;
    marpaESLIF_stringGeneratorp->okb    = 1;
  } else if (marpaESLIF_stringGeneratorp->okb) {
    wantedl = marpaESLIF_stringGeneratorp->l + sizel; /* +1 for the NUL is already accounted in marpaESLIF_stringGeneratorp->l */
    allocl = MARPAESLIF_CHUNKED_SIZE_UPPER(wantedl, 1024);
    /* Check for turn-around, should never happen */
    if (MARPAESLIF_UNLIKELY(allocl < wantedl)) {
      MARPAESLIF_ERROR(marpaESLIF_stringGeneratorp->marpaESLIFp, "size_t turnaround detected");
      goto err;
    }
    if (allocl > marpaESLIF_stringGeneratorp->allocl) {
      tmpp = realloc(marpaESLIF_stringGeneratorp->s, allocl); /* The +1 for the NULL byte is already in */
      if (MARPAESLIF_UNLIKELY(tmpp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIF_stringGeneratorp->marpaESLIFp, "realloc failure, %s", strerror(errno));
        goto err;
      }
      marpaESLIF_stringGeneratorp->s      = tmpp;
      marpaESLIF_stringGeneratorp->allocl = allocl;
    }
    if (sizel > 0) {
      memcpy(marpaESLIF_stringGeneratorp->s + marpaESLIF_stringGeneratorp->l - 1, p, sizel);
    }
    marpaESLIF_stringGeneratorp->l = wantedl; /* Already contains the +1 fir the NUL byte */
  } else {
    MARPAESLIF_ERRORF(marpaESLIF_stringGeneratorp->marpaESLIFp, "Invalid internal call to %s", funcs);
    goto err;
  }

  marpaESLIF_stringGeneratorp->s[marpaESLIF_stringGeneratorp->l - 1] = '\0';
  rcb = 1;
  goto done;

 err:
  if (marpaESLIF_stringGeneratorp->s != NULL) {
    free(marpaESLIF_stringGeneratorp->s);
    marpaESLIF_stringGeneratorp->s = NULL;
  }
  marpaESLIF_stringGeneratorp->okb    = 0;
  marpaESLIF_stringGeneratorp->l      = 0;
  marpaESLIF_stringGeneratorp->allocl = 0;
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
marpaESLIFValue_t *marpaESLIFValue_newp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueOption_t *marpaESLIFValueOptionp)
/*****************************************************************************/
{
  return _marpaESLIFValue_newp(marpaESLIFRecognizerp, marpaESLIFValueOptionp, 0 /* silentb */, 0 /* fakeb */, 0 /* isLexemeb */);
}

/*****************************************************************************/
static inline short __marpaESLIFValue_valueb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char       *funcs                 = "__marpaESLIFValue_valueb";
  static const int         indicei               = 0; /* By definition result is always at indice No 0 */
  marpaESLIFRecognizer_t  *marpaESLIFRecognizerp = marpaESLIFValuep->marpaESLIFRecognizerp;
  short                    rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Caller says to get immediately the value - this is applicable ONLY for true lexemes */
  if (marpaESLIFValuep->isLexemeb) {
    MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "Lexeme shortcut");
    rcb = marpaWrapperValue_valueb(marpaESLIFValuep->marpaWrapperValuep,
                                   (void *) marpaESLIFValuep,
                                   NULL,
                                   NULL,
                                   NULL);
    if ((rcb > 0) && (marpaESLIFValueResultp != NULL)) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Lexeme shortcut: OFFSET_AND_LENGTH {%ld,%ld}", (long) marpaESLIFRecognizerp->parentDeltal, (unsigned long) marpaESLIFRecognizerp->startCompletionl);
      marpaESLIFValueResultp->contextp           = NULL;
      marpaESLIFValueResultp->representationp    = NULL;
      marpaESLIFValueResultp->type               = MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH;
      marpaESLIFValueResultp->u.o.p              = marpaESLIFRecognizerp->parentDeltal;
      marpaESLIFValueResultp->u.o.sizel          = marpaESLIFRecognizerp->startCompletionl;
    }

    goto fast_done;
  }

  /* Classic mode that communicates via the stack */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_newb(marpaESLIFValuep))) {
    goto err;
  }

  rcb = marpaWrapperValue_valueb(marpaESLIFValuep->marpaWrapperValuep,
                                 (void *) marpaESLIFValuep,
                                 _marpaESLIFValue_ruleCallbackWrapperb,
                                 _marpaESLIFValue_symbolCallbackWrapperb,
                                 _marpaESLIFValue_nullingCallbackWrapperb);

  if (rcb > 0) {
    /* The output is at position indicei of valueResultStackp */
    /* This indice must be something we know about */
#ifndef MARPAESLIF_NTRACE
    /* Should never happen */
    if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_CUSTOM(marpaESLIFValuep->valueResultStackp, indicei))) {
      MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "marpaESLIFValuep->valueResultStackp at indice %d is not CUSTOM (got %s, value %d)", indicei, _marpaESLIF_genericStack_i_types(marpaESLIFValuep->valueResultStackp, indicei), GENERICSTACKITEMTYPE(marpaESLIFValuep->valueResultStackp, indicei));
      goto err;
    }
#endif

    /* Only internal calls set this variable: then we know by construction that we do not want to have an import */
    /* and we will manage the consequence of resetting the value at this stack indice. */
    if (marpaESLIFValueResultp != NULL) {
      *marpaESLIFValueResultp = GENERICSTACK_GET_CUSTOM(marpaESLIFValuep->valueResultStackp, indicei);
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValuep->valueResultStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "GENERICSTACK_GET_CUSTOM failure at indice %d, %s", strerror(errno), indicei);
      }
      GENERICSTACK_SET_NA(marpaESLIFValuep->valueResultStackp, indicei);
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValuep->valueResultStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "marpaESLIFValuep->valueResultStackp set to NA failure at indice %d, %s", strerror(errno), indicei);
      }
    } else {
      /* Call the end-user importer */
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_eslif2hostb(marpaESLIFValuep, GENERICSTACK_GET_CUSTOMP(marpaESLIFValuep->valueResultStackp, indicei), NULL /* forcedUserDatavp */, NULL /* forcedImporterp */))) {
        goto err;
      }
    }
  }

  goto done;

 err:
  rcb = -1;

 done:
  if (! _marpaESLIFValue_stack_freeb(marpaESLIFValuep)) {
    rcb = -1;
  }
 fast_done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_valueb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFValue_valueb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  /* We always do a first call with the wanted workflow */
  rcb = __marpaESLIFValue_valueb(marpaESLIFValuep, marpaESLIFValueResultp);
  if (rcb < 0) {
    goto done;
  }

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFValue_valueb(marpaESLIFValue_t *marpaESLIFValuep)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return _marpaESLIFValue_valueb(marpaESLIFValuep, NULL /* marpaESLIFValueResultp */);
}

/*****************************************************************************/
void marpaESLIFValue_freev(marpaESLIFValue_t *marpaESLIFValuep)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFValue_freev";

  if (marpaESLIFValuep != NULL) {
    if (marpaESLIFValuep->marpaWrapperValuep != NULL) {
      marpaWrapperValue_freev(marpaESLIFValuep->marpaWrapperValuep);
    }
    /* The stacks should never be something different than NULL at this stage. */
    /* The methods to use them are protected so that it is impossible */
    /* to use them outside of valuation mode. */
    /*
    GENERICSTACK_FREE(marpaESLIFValuep->valueResultStackp);
    */

    _marpaESLIF_stringGeneratorFreev(&(marpaESLIFValuep->stringGenerator), 1 /* onStackb */);
    GENERICLOGGER_FREE(marpaESLIFValuep->stringGeneratorLoggerp);

    if (marpaESLIFValuep->luaprecompiledp != NULL) {
      free(marpaESLIFValuep->luaprecompiledp);
    }

    /* Dispose lua if needed */
    _marpaESLIF_lua_value_freev(marpaESLIFValuep);

    free(marpaESLIFValuep);
  }
}

/*****************************************************************************/
static short _marpaESLIFValue_ruleCallbackWrapperb(void *userDatavp, int rulei, int arg0i, int argni, int resulti)
/*****************************************************************************/
{
  static const char                  *funcs                 = "_marpaESLIFValue_ruleCallbackWrapperb";
  marpaESLIFValue_t                  *marpaESLIFValuep      = (marpaESLIFValue_t *) userDatavp;
  marpaESLIFRecognizer_t             *marpaESLIFRecognizerp = marpaESLIFValuep->marpaESLIFRecognizerp;
  marpaESLIF_grammar_t               *grammarp              = marpaESLIFRecognizerp->grammarp;
  marpaESLIFValueRuleCallback_t       ruleCallbackp         = NULL;
  marpaESLIF_rule_t                  *rulep;
  short                               rcb;
  int                                 i;
  int                                 j;
  int                                 k;
  
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start [%d] <- [%d-%d]", resulti, arg0i, argni);
#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: start [%d] <- [%d-%d]", funcs, resulti, arg0i, argni);
#endif

  /* This is an internal method, we know that rulei is correct. */
  MARPAESLIF_GRAMMAR_INTERNAL_GET_RULE(marpaESLIFValuep->marpaESLIFp, rulep, grammarp, rulei);

  marpaESLIFValuep->inValuationb   =  1;
  marpaESLIFValuep->symbolp        = NULL;
  marpaESLIFValuep->rulep          = rulep;

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Grammar %d Rule %d %s", grammarp->leveli, rulep->idi, rulep->asciishows);

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_ruleActionCallbackb(marpaESLIFValuep, &ruleCallbackp, rulep->asciishows, rulep->effectiveRuleActionp, rulep->effectiveRuleActione))) {
    goto err;
  }

  /* If the rule have a separator, eventually remove it */
  if ((rulep->separatorp != NULL) && rulep->hideseparatorb
      /* && (argni > arg0i) */             /* test not necessary in theory because we are not nullable */
      ) {
    marpaESLIFValuep->hideSeparatorb = 1;
    if ((rulep->effectiveRuleActione != MARPAESLIF_INTERNAL_RULE_ACTION___ROW) && (rulep->effectiveRuleActione != MARPAESLIF_INTERNAL_RULE_ACTION___TABLE)) {
      /* We have internal hook in ::row and ::table that takes into account the hide-separator adverb */
      for (i = arg0i, j = arg0i; i <= argni; i += 2) {
        if (i == j) {
          /* First occurence always exist */
          continue;
        }
        /* We are processing the (j+1)'th argument hosted at indice i, by definition indice j+1 is a separator: */
        /* 0 ...  j  j+1  ...    i ... argni                                                                    */
        /* We switch i and j+1 contents:                                                                        */
        /* 0 ...  j *i   ... *(j+1) ... argni                                                                   */
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Hide separator: Switching [%d] and [%d] contents", i, j + 1);
#ifdef MARPAESLIF_NOTICE_ACTION
        MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Hide separator: Switching [%d] and [%d] contents", funcs, i, j + 1);
#endif
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_switchb(marpaESLIFValuep, i, ++j))) {
          goto err;
        }
      }
#ifdef MARPAESLIF_NOTICE_ACTION
      MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Hide value changed stack indices: [%d] <- [%d-%d]", funcs, resulti, arg0i, argni);
#endif
      argni = j;
    }
  }
    
  /* If the rule have skipped elements, eventually remove them (starting at the latest indice) */
  if (rulep->skipbp != NULL) {
    k = 0; /* k is the number of arguments to shift */
    for (i = argni; i >= arg0i; i--) {
      if (rulep->skipbp[i - arg0i]) {
        /* Shift remaining values - last element is naturally skipped with argni-- */
        if (k > 0) {
          /* There are k unhiden values scanned and we want to shift them. Current argument being skipped is at indice i. */
          for (j = i; j < i + k; j++) {
            MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Hide value: Switching [%d] and [%d] contents", j + 1, j);
#ifdef MARPAESLIF_NOTICE_ACTION
            MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Hide value: Switching [%d] and [%d] contents", funcs, j + 1, j);
#endif
            if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_switchb(marpaESLIFValuep, j + 1, j))) {
              goto err;
            }
          }
        }
        /* Number of arguments to the callback decreases (note that the first part of the for (i = argni; ...) loop is NOT reevaluated) */
        argni--;
      } else {
        k++; /* This element is not skipped */
      }
    }
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Hide value changed stack indices: [%d] <- [%d-%d]", resulti, arg0i, argni);
#ifdef MARPAESLIF_NOTICE_ACTION
    MARPAESLIF_TRACEF(marpaESLIFRecognizerp->marpaESLIFp, funcs, "Hide value changed stack indices: [%d] <- [%d-%d]", resulti, arg0i, argni);
#endif
  }

#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Action %s: Symbol <%s>: [%d] <- [%d-%d]", funcs, marpaESLIFValuep->actions, rulep->lhsp->descp->asciis, resulti, arg0i, argni);
#endif

  if (MARPAESLIF_UNLIKELY(! ruleCallbackp(marpaESLIFValuep->marpaESLIFValueOption.userDatavp, marpaESLIFValuep, arg0i, argni, resulti, 0 /* nullableb */))) {
    /* marpaWrapper logging will not give rule description, so do we */
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Action %s failed for rule: %s", marpaESLIFValuep->actions, rulep->asciishows);
    goto err;
  }

  rcb = 1;
  goto done;

 err:
#if MARPAESLIF_VALUEERRORPROGRESSREPORT
  _marpaESLIFValueErrorProgressReportv(marpaESLIFValuep);
#endif
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  marpaESLIFValuep->inValuationb       =  0;
  marpaESLIFValuep->symbolp            = NULL;
  marpaESLIFValuep->rulep              = NULL;
  marpaESLIFValuep->actions            = NULL;
  marpaESLIFValuep->stringp            = NULL;
  marpaESLIFValuep->hideSeparatorb     = 0;
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_anySymbolCallbackWrapperb(void *userDatavp, int symboli, int argi, int resulti, short nullableb)
/*****************************************************************************/
{
  static const char                    *funcs                 = "_marpaESLIFValue_anySymbolCallbackWrapperb";
  marpaESLIFValue_t                    *marpaESLIFValuep      = (marpaESLIFValue_t *) userDatavp;
  marpaESLIFRecognizer_t               *marpaESLIFRecognizerp = marpaESLIFValuep->marpaESLIFRecognizerp;
  marpaESLIF_grammar_t                 *grammarp              = marpaESLIFRecognizerp->grammarp;
  marpaESLIFValueSymbolCallback_t       symbolCallbackp       = NULL;
  marpaESLIFValueRuleCallback_t         ruleCallbackp         = NULL;
  marpaESLIF_symbol_t                  *symbolp;
  short                                 rcb;
  marpaESLIFValueResult_t              *marpaESLIFValueResultp;
  
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
#ifndef MARPAESLIF_NTRACE
  if (nullableb) {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start(nullable=%d) [%d] <-", (int) nullableb, resulti);
  } else {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start(nullable=%d) [%d] <- [%d]", (int) nullableb, resulti, argi);
  }
#endif

  /* This is an internal method, we know that symboli is correct. */
  MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFValuep->marpaESLIFp, symbolp, grammarp, symboli);

  marpaESLIFValuep->inValuationb   =  1;
  marpaESLIFValuep->symbolp        = symbolp;
  marpaESLIFValuep->rulep          = NULL;

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Grammar %d Symbol %d %s", grammarp->leveli, symbolp->idi, symbolp->descp->asciis);

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_symbolActionCallbackb(marpaESLIFValuep, &symbolCallbackp, nullableb, &ruleCallbackp, symbolp))) {
    goto err;
  }

#ifdef MARPAESLIF_NOTICE_ACTION
  if (nullableb) {
    MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Action %s: Symbol <%s>: [%d] <-", funcs, marpaESLIFValuep->actions, symbolp->descp->asciis, resulti);
  } else {
    MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Action %s: Symbol <%s>: [%d] <- [%d]", funcs, marpaESLIFValuep->actions, symbolp->descp->asciis, resulti, argi);
  }
#endif

  if (symbolCallbackp != NULL) {
    marpaESLIFValueResultp = _marpaESLIFRecognizer_lexemeStack_i_getp(marpaESLIFValuep->marpaESLIFRecognizerp, argi);
    if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp == NULL)) {
      goto err;
    }
    if (MARPAESLIF_UNLIKELY(! symbolCallbackp(marpaESLIFValuep->marpaESLIFValueOption.userDatavp, marpaESLIFValuep, marpaESLIFValueResultp, resulti))) {
      /* marpaWrapper logging will not give symbol description, so do we */
      MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Action %s failed for symbol: %s", marpaESLIFValuep->actions, symbolp->descp->asciis);
      goto err;
    }
  } else {
    if (MARPAESLIF_UNLIKELY(! ruleCallbackp(marpaESLIFValuep->marpaESLIFValueOption.userDatavp, marpaESLIFValuep, -1, -1, resulti, nullableb))) {
      /* marpaWrapper logging will not give symbol description, so do we */
      MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Action %s failed for symbol: %s", marpaESLIFValuep->actions, symbolp->descp->asciis);
      goto err;
    }
  }

  rcb = 1;
  goto done;

 err:
#if MARPAESLIF_VALUEERRORPROGRESSREPORT
  _marpaESLIFValueErrorProgressReportv(marpaESLIFValuep);
#endif
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  marpaESLIFValuep->inValuationb       = 0;
  marpaESLIFValuep->symbolp            = NULL;
  marpaESLIFValuep->rulep              = NULL;
  marpaESLIFValuep->actions            = NULL;
  marpaESLIFValuep->stringp            = NULL;
  marpaESLIFValuep->hideSeparatorb     = 0;
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIFValue_symbolCallbackWrapperb(void *userDatavp, int symboli, int argi, int resulti)
/*****************************************************************************/
{
  static const char      *funcs            = "_marpaESLIFValue_symbolCallbackWrapperb";
#ifndef MARPAESLIF_NTRACE
  marpaESLIFValue_t      *marpaESLIFValuep = (marpaESLIFValue_t *) userDatavp;
#endif
  short                   rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFValue_anySymbolCallbackWrapperb(userDatavp, symboli, argi, resulti, 0 /* nullableb */);

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIFValue_nullingCallbackWrapperb(void *userDatavp, int symboli, int resulti)
/*****************************************************************************/
{
  static const char      *funcs            = "_marpaESLIFValue_nullingCallbackWrapperb";
#ifndef MARPAESLIF_NTRACE
  marpaESLIFValue_t      *marpaESLIFValuep = (marpaESLIFValue_t *) userDatavp;
#endif
  short                   rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFValue_anySymbolCallbackWrapperb(userDatavp, symboli, -1 /* arg0i - not used when nullable is true */, resulti, 1 /* nullableb */);

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline void _marpaESLIFGrammar_bootstrap_freev(marpaESLIFGrammar_bootstrap_t *marpaESLIFGrammarp)
/*****************************************************************************/
{
  if (marpaESLIFGrammarp != NULL) {
    _marpaESLIF_grammarBootstrapStack_freev(marpaESLIFGrammarp->grammarBootstrapStackp);
    if (marpaESLIFGrammarp->luabytep != NULL) {
      free(marpaESLIFGrammarp->luabytep);
    }
    free(marpaESLIFGrammarp);
  }
}

/*****************************************************************************/
static inline void _marpaESLIFGrammar_freev(marpaESLIFGrammar_t *marpaESLIFGrammarp, short onStackb)
/*****************************************************************************/
{
  if (marpaESLIFGrammarp != NULL) {
    _marpaESLIF_grammarStack_freev(marpaESLIFGrammarp->grammarStackp);
    _marpaESLIF_string_freev(marpaESLIFGrammarp->luadescp, 0 /* onStackb */);
    if (marpaESLIFGrammarp->luabytep != NULL) {
      free(marpaESLIFGrammarp->luabytep);
    }
    if (marpaESLIFGrammarp->luaprecompiledp != NULL) {
      free(marpaESLIFGrammarp->luaprecompiledp);
    }
    if (marpaESLIFGrammarp->lexemeGrammarHashp != NULL) {
      /* This will free all cached grammars in cascade -; */
      GENERICHASH_RESET(marpaESLIFGrammarp->lexemeGrammarHashp, marpaESLIFGrammarp->marpaESLIFp);
    }
    _marpaESLIF_lua_grammar_freev(marpaESLIFGrammarp);
    _marpaESLIFGrammar_bootstrap_freev(marpaESLIFGrammarp->marpaESLIFGrammar_bootstrapp);
    if (! onStackb) {
      free(marpaESLIFGrammarp);
    }
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_grammarBootstrapStack_freev(genericStack_t *grammarStackp)
/*****************************************************************************/
{
  marpaESLIF_grammar_bootstrap_t *grammarp;

  if (grammarStackp != NULL) {
    while (GENERICSTACK_USED(grammarStackp) > 0) {
      if (GENERICSTACK_IS_PTR(grammarStackp, GENERICSTACK_USED(grammarStackp) - 1)) {
        grammarp = (marpaESLIF_grammar_bootstrap_t *) GENERICSTACK_POP_PTR(grammarStackp);
        _marpaESLIF_grammar_bootstrap_freev(grammarp);
      } else {
        GENERICSTACK_USED(grammarStackp)--;
      }
    }
    GENERICSTACK_RESET(grammarStackp); /* Take care, this a pointer to a stack inside Grammar structure */
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_grammarStack_freev(genericStack_t *grammarStackp)
/*****************************************************************************/
{
  if (grammarStackp != NULL) {
    while (GENERICSTACK_USED(grammarStackp) > 0) {
      if (GENERICSTACK_IS_PTR(grammarStackp, GENERICSTACK_USED(grammarStackp) - 1)) {
        marpaESLIF_grammar_t *grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_POP_PTR(grammarStackp);
        _marpaESLIF_grammar_freev(grammarp);
      } else {
        GENERICSTACK_USED(grammarStackp)--;
      }
    }
    GENERICSTACK_RESET(grammarStackp); /* Take care, this a pointer to a stack inside Grammar structure */
  }
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_lexemeStack_i_p_and_sizeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, int i, char **pp, size_t *sizelp)
/*****************************************************************************/
{
  static const char       *funcs = "_marpaESLIFRecognizer_lexemeStack_i_p_and_sizeb";
  marpaESLIFValueResult_t *marpaESLIFValueResultp;
  short                    rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start, i=%d", i);

  marpaESLIFValueResultp = _marpaESLIFRecognizer_lexemeStack_i_getp(marpaESLIFRecognizerp, i);
  if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp == NULL)) {
    goto err;
  }

  *pp     = marpaESLIFValueResultp->u.a.p;
  *sizelp = marpaESLIFValueResultp->u.a.sizel;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline marpaESLIFValueResult_t *_marpaESLIFRecognizer_lexemeStack_i_getp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, int i)
/*****************************************************************************/
{
  static const char       *funcs = "_marpaESLIFRecognizer_lexemeStack_i_getp";
  marpaESLIFValueResult_t *rcp;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

#ifndef MARPAESLIF_NTRACE
  /* Should never happen */
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_CUSTOM(marpaESLIFRecognizerp->lexemeStackp, i))) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "No such indice %d in lexeme stack", i);
    goto err;
  }
#endif
  rcp = GENERICSTACK_GET_CUSTOMP(marpaESLIFRecognizerp->lexemeStackp, i);
#ifndef MARPAESLIF_NTRACE
  MARPAESLIFRECOGNIZER_MARPAESLIFVALUE_TRACE(funcs, marpaESLIFRecognizerp, NULL /* symbolp */, i, rcp);
#endif

#ifndef MARPAESLIF_NTRACE
  goto done;

 err:
  rcp = NULL;

 done:
#endif
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %p", rcp);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcp;
}

/*****************************************************************************/
static inline const char *_marpaESLIF_genericStack_i_types(genericStack_t *stackp, int i)
/*****************************************************************************/
{
  const char *s;

  switch (GENERICSTACKITEMTYPE(stackp, i)) {
  case GENERICSTACKITEMTYPE_NA:
    s = GENERICSTACKITEMTYPE_NA_STRING;
    break;
  case GENERICSTACKITEMTYPE_CHAR:
    s = GENERICSTACKITEMTYPE_CHAR_STRING;
    break;
  case GENERICSTACKITEMTYPE_SHORT:
    s = GENERICSTACKITEMTYPE_SHORT_STRING;
    break;
  case GENERICSTACKITEMTYPE_INT:
    s = GENERICSTACKITEMTYPE_INT_STRING;
    break;
  case GENERICSTACKITEMTYPE_LONG:
    s = GENERICSTACKITEMTYPE_LONG_STRING;
    break;
  case GENERICSTACKITEMTYPE_FLOAT:
    s = GENERICSTACKITEMTYPE_FLOAT_STRING;
    break;
  case GENERICSTACKITEMTYPE_DOUBLE:
    s = GENERICSTACKITEMTYPE_DOUBLE_STRING;
    break;
  case GENERICSTACKITEMTYPE_PTR:
    s = GENERICSTACKITEMTYPE_PTR_STRING;
    break;
  case GENERICSTACKITEMTYPE_ARRAY:
    s = GENERICSTACKITEMTYPE_ARRAY_STRING;
    break;
  case GENERICSTACKITEMTYPE_CUSTOM:
    s = GENERICSTACKITEMTYPE_CUSTOM_STRING;
    break;
  case GENERICSTACKITEMTYPE_LONG_DOUBLE:
    s = GENERICSTACKITEMTYPE_LONG_DOUBLE_STRING;
    break;
  default:
    s = GENERICSTACKITEMTYPE_UNKNOWN_STRING;
    break;
  }

  return s;
}

/*****************************************************************************/
static inline const char *_marpaESLIF_value_types(int typei)
/*****************************************************************************/
{
  const char *s;

  switch (typei) {
  case MARPAESLIF_VALUE_TYPE_UNDEF:
    s = MARPAESLIF_VALUE_TYPE_UNDEF_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_CHAR:
    s = MARPAESLIF_VALUE_TYPE_CHAR_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_SHORT:
    s = MARPAESLIF_VALUE_TYPE_SHORT_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_INT:
    s = MARPAESLIF_VALUE_TYPE_INT_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_LONG:
    s = MARPAESLIF_VALUE_TYPE_LONG_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_FLOAT:
    s = MARPAESLIF_VALUE_TYPE_FLOAT_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_DOUBLE:
    s = MARPAESLIF_VALUE_TYPE_DOUBLE_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_PTR:
    s = MARPAESLIF_VALUE_TYPE_PTR_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_ARRAY:
    s = MARPAESLIF_VALUE_TYPE_ARRAY_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_BOOL:
    s = MARPAESLIF_VALUE_TYPE_BOOL_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_STRING:
    s = MARPAESLIF_VALUE_TYPE_STRING_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_ROW:
    s = MARPAESLIF_VALUE_TYPE_ROW_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_TABLE:
    s = MARPAESLIF_VALUE_TYPE_TABLE_STRING;
    break;
  case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:
    s = MARPAESLIF_VALUE_TYPE_LONG_DOUBLE_STRING;
    break;
#ifdef MARPAESLIF_HAVE_LONG_LONG
  case MARPAESLIF_VALUE_TYPE_LONG_LONG:
    s = MARPAESLIF_VALUE_TYPE_LONG_LONG_STRING;
    break;
#endif
  case MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH:
    s = MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH_STRING;
    break;
  default:
    s = MARPAESLIF_VALUE_TYPE_UNKNOWN_STRING;
    break;
  }

  return s;
}

/*****************************************************************************/
static char *_marpaESLIFGrammar_symbolDescriptionCallbacks(void *userDatavp, int symboli)
/*****************************************************************************/
{
  static const char    *funcs              = "_marpaESLIFGrammar_symbolDescriptionCallbacks";
  marpaESLIF_grammar_t *grammarp           = (marpaESLIF_grammar_t *) userDatavp;
  genericStack_t       *symbolStackp       = grammarp->symbolStackp;
  marpaESLIF_symbol_t  *symbolp;
  char                 *rcs;

#ifndef MARPAESLIF_NTRACE
  /* Should never happen */
  if (! GENERICSTACK_IS_PTR(symbolStackp, symboli)) {
    return NULL;
  }
#endif

  symbolp = GENERICSTACK_GET_PTR(symbolStackp, symboli);
  switch (symbolp->type) {
  case MARPAESLIF_SYMBOL_TYPE_TERMINAL:
    rcs = symbolp->u.terminalp->descp->asciis;
    break;
  case MARPAESLIF_SYMBOL_TYPE_META:
    rcs = symbolp->u.metap->descp->asciis;
    break;
  default:
    rcs = (char *) MARPAESLIF_EMPTY_STRING;
    break;
  }

  return rcs;
}

/*****************************************************************************/
 static short _marpaESLIFGrammar_symbolOptionSetterInitb(void *userDatavp, int symboli, marpaWrapperGrammarSymbolOption_t *marpaWrapperGrammarSymbolOptionp)
/*****************************************************************************/
{
  static const char         *funcs                    = "_marpaESLIFGrammar_symbolOptionSetterInit";
  marpaESLIF_cloneContext_t *marpaESLIF_cloneContextp = (marpaESLIF_cloneContext_t *) userDatavp;
  marpaESLIF_grammar_t      *grammarp                 = marpaESLIF_cloneContextp->grammarp;
  genericStack_t            *symbolStackp             = grammarp->symbolStackp;
  marpaESLIF_symbol_t       *symbolp;
  short                      rcb;

  MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIF_cloneContextp->marpaESLIFp, symbolp, symbolStackp, symboli);

  /* Consistenty check */
  if (MARPAESLIF_UNLIKELY(symbolp->idi != symboli)) {
    MARPAESLIF_ERRORF(marpaESLIF_cloneContextp->marpaESLIFp, "Clone symbol callback for symbol No %d while we have %d !?", symboli, symbolp->idi);
    goto err;
  }

  marpaWrapperGrammarSymbolOptionp->eventSeti = MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE;

  /* Get event set */
  if (! symbolp->discardRhsb) {
    if (symbolp->eventPredicteds != NULL) {
      MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Setting prediction event for symbol %d <%s> at grammar level %d (%s)", symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis);
      marpaWrapperGrammarSymbolOptionp->eventSeti |= MARPAWRAPPERGRAMMAR_EVENTTYPE_PREDICTION;
    }
    if (symbolp->eventNulleds != NULL) {
      MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Setting nulled event for symbol %d <%s> at grammar level %d (%s)", symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis);
      marpaWrapperGrammarSymbolOptionp->eventSeti |= MARPAWRAPPERGRAMMAR_EVENTTYPE_NULLED;
    }
    if (symbolp->eventCompleteds != NULL) {
      MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Setting completion event for symbol %d <%s> at grammar level %d (%s)", symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis);
      marpaWrapperGrammarSymbolOptionp->eventSeti |= MARPAWRAPPERGRAMMAR_EVENTTYPE_COMPLETION;
    }
  } else {
    if (symbolp->discardEvents != NULL) {
      MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Setting :discard completion event for symbol %d <%s> at grammar level %d (%s)", symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis);
      marpaWrapperGrammarSymbolOptionp->eventSeti |= MARPAWRAPPERGRAMMAR_EVENTTYPE_COMPLETION;
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
 static short _marpaESLIFGrammar_symbolOptionSetterInternalb(void *userDatavp, int symboli, marpaWrapperGrammarSymbolOption_t *marpaWrapperGrammarSymbolOptionp)
/*****************************************************************************/
{
  static const char         *funcs                    = "_marpaESLIFGrammar_symbolOptionSetterInternalb";
  marpaESLIF_cloneContext_t *marpaESLIF_cloneContextp = (marpaESLIF_cloneContext_t *) userDatavp;
  marpaESLIF_grammar_t      *grammarp                 = marpaESLIF_cloneContextp->grammarp;
  genericStack_t            *symbolStackp             = grammarp->symbolStackp;
  marpaESLIF_symbol_t       *symbolp;
  short                     rcb;

  MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIF_cloneContextp->marpaESLIFp, symbolp, symbolStackp, symboli);

  /* Consistenty check */
  if (MARPAESLIF_UNLIKELY(symbolp->idi != symboli)) {
    MARPAESLIF_ERRORF(marpaESLIF_cloneContextp->marpaESLIFp, "Clone symbol callback for symbol No %d while we have %d !?", symboli, symbolp->idi);
    goto err;
  }

  marpaWrapperGrammarSymbolOptionp->eventSeti = MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE;

  if ((symbolp->eventNulleds != NULL) &&
      ((strcmp(symbolp->eventNulleds, ":discard[on]") == 0) ||
       (strcmp(symbolp->eventNulleds, ":discard[off]") == 0) ||
       (strcmp(symbolp->eventNulleds, ":discard[switch]") == 0))) {
    MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Setting nullabled event %s for symbol %d <%s> at grammar level %d (%s)", symbolp->eventNulleds, symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis);
    marpaWrapperGrammarSymbolOptionp->eventSeti |= MARPAWRAPPERGRAMMAR_EVENTTYPE_NULLED;
  }
  if ((symbolp->eventPredicteds != NULL) &&
      ((strcmp(symbolp->eventPredicteds, ":discard[on]") == 0) ||
       (strcmp(symbolp->eventPredicteds, ":discard[off]") == 0) ||
       (strcmp(symbolp->eventPredicteds, ":discard[switch]") == 0))) {
    MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Setting prediction event %s for symbol %d <%s> at grammar level %d (%s)", symbolp->eventPredicteds, symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis);
    marpaWrapperGrammarSymbolOptionp->eventSeti |= MARPAWRAPPERGRAMMAR_EVENTTYPE_PREDICTION;
  }
  if ((symbolp->eventCompleteds != NULL) &&
      ((strcmp(symbolp->eventCompleteds, ":discard[on]") == 0) ||
       (strcmp(symbolp->eventCompleteds, ":discard[off]") == 0) ||
       (strcmp(symbolp->eventCompleteds, ":discard[switch]") == 0))) {
    MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Setting completiong event %s for symbol %d <%s> at grammar level %d (%s)", symbolp->eventCompleteds, symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis);
    marpaWrapperGrammarSymbolOptionp->eventSeti |= MARPAWRAPPERGRAMMAR_EVENTTYPE_COMPLETION;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
 static short _marpaESLIFGrammar_symbolOptionSetterInternalNoeventb(void *userDatavp, int symboli, marpaWrapperGrammarSymbolOption_t *marpaWrapperGrammarSymbolOptionp)
/*****************************************************************************/
{
  static const char         *funcs                    = "_marpaESLIFGrammar_symbolOptionSetterInternalNoeventb";
  marpaESLIF_cloneContext_t *marpaESLIF_cloneContextp = (marpaESLIF_cloneContext_t *) userDatavp;
  marpaESLIF_grammar_t      *grammarp                 = marpaESLIF_cloneContextp->grammarp;
  genericStack_t            *symbolStackp             = grammarp->symbolStackp;
  marpaESLIF_symbol_t       *symbolp;
  short                     rcb;

  MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIF_cloneContextp->marpaESLIFp, symbolp, symbolStackp, symboli);

  /* Consistenty check */
  if (MARPAESLIF_UNLIKELY(symbolp->idi != symboli)) {
    MARPAESLIF_ERRORF(marpaESLIF_cloneContextp->marpaESLIFp, "Clone symbol callback for symbol No %d while we have %d !?", symboli, symbolp->idi);
    goto err;
  }

  marpaWrapperGrammarSymbolOptionp->eventSeti = MARPAWRAPPERGRAMMAR_EVENTTYPE_NONE;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIFGrammar_grammarOptionSetterNoLoggerb(void *userDatavp, marpaWrapperGrammarOption_t *marpaWrapperGrammarOptionp)
/*****************************************************************************/
{
  static const char         *funcs                    = "_marpaESLIFGrammar_grammarOptionSetterNoLoggerb";
  marpaESLIF_cloneContext_t *marpaESLIF_cloneContextp = (marpaESLIF_cloneContext_t *) userDatavp;
  marpaESLIF_grammar_t      *grammarp                 = marpaESLIF_cloneContextp->grammarp;

  MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Disabling generic logger at grammar level %d (%s)", grammarp->leveli, grammarp->descp->asciis);

  marpaWrapperGrammarOptionp->genericLoggerp = NULL;

  return 1;
}

/*****************************************************************************/
 static short _marpaESLIFGrammar_symbolOptionSetterDiscardb(void *userDatavp, int symboli, marpaWrapperGrammarSymbolOption_t *marpaWrapperGrammarSymbolOptionp)
/*****************************************************************************/
{
  static const char         *funcs                    = "_marpaESLIFGrammar_symbolOptionSetterDiscardb";
  marpaESLIF_cloneContext_t *marpaESLIF_cloneContextp = (marpaESLIF_cloneContext_t *) userDatavp;
  marpaESLIF_grammar_t      *grammarp                 = marpaESLIF_cloneContextp->grammarp;
  genericStack_t            *symbolStackp             = grammarp->symbolStackp;
  marpaESLIF_symbol_t       *symbolp;
  short                     rcb;

  MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK(marpaESLIF_cloneContextp->marpaESLIFp, symbolp, symbolStackp, symboli);

  /* Consistenty check */
  if (MARPAESLIF_UNLIKELY(symbolp->idi != symboli)) {
    MARPAESLIF_ERRORF(marpaESLIF_cloneContextp->marpaESLIFp, "Clone symbol callback for symbol No %d while we have %d !?", symboli, symbolp->idi);
    goto err;
  }

  /* A "discard" event is possible only for symbols that are the RHS of a :discard in the current grammar */
  if (symbolp->discardRhsb && (symbolp->discardEvents != NULL)) {
    if (marpaWrapperGrammarSymbolOptionp->eventSeti != MARPAWRAPPERGRAMMAR_EVENTTYPE_COMPLETION) {
      MARPAESLIF_TRACEF(marpaESLIF_cloneContextp->marpaESLIFp, funcs, "Setting completion event for symbol %d <%s> at grammar level %d (%s) on completion", symbolp->idi, symbolp->descp->asciis, grammarp->leveli, grammarp->descp->asciis);
      marpaWrapperGrammarSymbolOptionp->eventSeti = MARPAWRAPPERGRAMMAR_EVENTTYPE_COMPLETION;
    }
    rcb = 1;
  } else {
    rcb = _marpaESLIFGrammar_symbolOptionSetterInternalNoeventb(userDatavp, symboli, marpaWrapperGrammarSymbolOptionp);
  }

  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short __marpaESLIFRecognizer_readb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
/*
  In the recognizer:
  - buffers is containing unparsed data, and its size can vary at any time. ALWAYS SHARED with all parents.
  - inputs is always a pointer within buffers.                              ALWAYS SPECIFIC to current recognizer.
  - eofb is when EOF is hit.                                                ALWAYS SHARED with all parents.

  Handled in regex match:
  - encodings is eventual encoding information as per the user              ALWAYS SHARED with all parents.
  - utf8s is the UTF-8 conversion of buffer. Handled in regex match.        ALWAYS SHARED with all parents.
  
  Remember the semantics: from our point of view, reader is reading NEW data. We always append.
*/
{
  static const char            *funcs                      = "__marpaESLIFRecognizer_readb";
  marpaESLIF_t                 *marpaESLIFp                = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIF_stream_t          *marpaESLIF_streamp         = marpaESLIFRecognizerp->marpaESLIF_streamp;
  marpaESLIF_grammar_t         *grammarp                   = marpaESLIFRecognizerp->grammarp;
  char                         *inputs                     = NULL;
  char                         *encodings                  = NULL;
  size_t                        encodingl                  = 0;
  size_t                        inputl                     = 0;
  short                         eofb                       = 0;
  short                         characterStreamb           = 0;
  char                         *utf8s                      = NULL;
  marpaESLIFReaderDispose_t     disposeCallbackp           = NULL;
  short                         disposeCallbackb           = 0; /* To know if we have to call disposer */
  size_t                        utf8l;
  short                         appendDatab;
  short                         charconvb;
  short                         rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.readerCallbackp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Null reader callback");
    errno = EINVAL;
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->eofb)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Stream is already at eof");
    errno = ENOSYS;
    goto err;
  }

 again:
  if (disposeCallbackb) {
    if (disposeCallbackp != NULL) {
      disposeCallbackp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, inputs, inputl, eofb, characterStreamb, encodings, encodingl);
      disposeCallbackp = NULL;
    }
    disposeCallbackb = 0;
  }
  if (MARPAESLIF_UNLIKELY(! marpaESLIFRecognizerp->marpaESLIFRecognizerOption.readerCallbackp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, &inputs, &inputl, &eofb, &characterStreamb, &encodings, &encodingl, &disposeCallbackp))) {
    MARPAESLIF_ERROR(marpaESLIFp, "reader failure");
    goto err;
  }
  disposeCallbackb = (disposeCallbackp != NULL) ? 1 : 0;

  if ((inputs != NULL) && (inputl > 0)) {
    if (characterStreamb) {
      /* ************************************************************************************************************************************************* */
      /* User say this is a stream of characters.                                                                                                          */
      /* ************************************************************************************************************************************************* */
      /* Here are the possible cases:                                                                                                                      */
      /* - Previous read was a stream of characters (marpaESLIF_streamp->charconvb is true).                                                               */
      /*   [We MUST have the current input encodings in marpaESLIF_streamp->encodings and a conversion engine in marpaESLIF_streamp->tconvp]               */
      /*   [We MUST have a fake terminal associated to input encoding]                                                                                     */
      /*   - user gave encoding (encodings != NULL)                                                                                                        */
      /*     - If encodings and marpaESLIF_streamp->encodings differ, current conversion engine is flushed, last state clean. A new one start.             */
      /*       >> Encoding aliases are not supported.                                                                                                      */
      /*       >> This mode does not support incomplete characters in the input streaming.                                                                 */
      /*     - If encodings and marpaESLIF_streamp->encodings are the same, current conversion engine continue.                                            */
      /*       >> Encoding aliases are not supported.                                                                                                      */
      /*       >> This mode support incomplete characters in the input streaming.                                                                          */
      /*   - user gave NO encoding (encodings == NULL)                                                                                                     */
      /*     - It is assumed that current conversion can continue.                                                                                         */
      /*       >> This mode support incomplete characters in the input streaming.                                                                          */
      /* - Previous read was NOT a stream of characters (marpaESLIF_streamp->charconvb is false).                                                          */
      /*   [Input encodings in marpaESLIF_streamp->encodings should be NULL and current conversion in marpaESLIF_streamp->tconvp as well.]                 */
      /*   - user gave encoding (encodings != NULL) or not                                                                                                 */
      /*     - This is used as-is in the call to _marpaESLIF_charconvb(). Current encoding and conversion engine are initialized.                          */
      /*                                                                                                                                                   */
      /* Input is systematically converted into UTF-8. If user said "UTF-8" it is equivalent to                                                            */
      /* an UTF-8 validation. The user MUST send a buffer information that contain full characters.                                                        */
      /* ************************************************************************************************************************************************* */
      if (marpaESLIF_streamp->charconvb) {
        /* ************************************************************************************************************************************************* */
        /* - Previous read was a stream of characters (marpaESLIF_streamp->charconvb is true).                                                               */
        /* ************************************************************************************************************************************************* */
        if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->encodings == NULL)) {
          MARPAESLIF_ERROR(marpaESLIFp, "Previous encoding is unknown");
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->tconvp == NULL)) {
          MARPAESLIF_ERROR(marpaESLIFp, "Previous conversion engine is not set");
          goto err;
        }
        if (encodings != NULL) {
          /* ************************************************************************************************************************************************* */
          /*   - user gave encoding (encodings != NULL)                                                                                                        */
          /* ************************************************************************************************************************************************* */
          if (! _marpaESLIF_charset_eqb(marpaESLIFp, marpaESLIF_streamp->encodings, encodings, encodingl)) {
            /* ************************************************************************************************************************************************* */
            /*     - If encodings and marpaESLIF_streamp->encodings differ, current conversion engine is flushed. A new one start.                               */
            /* ************************************************************************************************************************************************* */
            /* Flush current conversion engine */
            if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_flush_charconvb(marpaESLIFRecognizerp))) {
              goto err;
            }
            /* Start a new one */
            charconvb = _marpaESLIFRecognizer_start_charconvb(marpaESLIFRecognizerp, encodings, encodingl, inputs, inputl, eofb, grammarp->defaultEncodings, grammarp->fallbackEncodings);
            if (MARPAESLIF_UNLIKELY(! charconvb)) {
              goto err;
            } else if (charconvb < 0) {
              /* EAGAIN case: charconv internally appends data, the later tried to remove BOM, this is not eof, and there are not enough bytes */
              goto again;
            }
          } else {
            /* ************************************************************************************************************************************************* */
            /*     - If encodings and marpaESLIF_streamp->encodings are the same, current conversion engine continue.                                            */
            /* ************************************************************************************************************************************************* */
            /* Continue with current conversion engine */
            utf8s = _marpaESLIF_charconvb(marpaESLIFp, (char *) MARPAESLIF_UTF8_STRING, marpaESLIF_streamp->encodings, inputs, inputl, &utf8l, NULL /* encodingsp */, &(marpaESLIF_streamp->tconvp), eofb, &(marpaESLIF_streamp->bytelefts), &(marpaESLIF_streamp->byteleftl), &(marpaESLIF_streamp->byteleftallocl), 0 /* tconvsilentb */, grammarp->defaultEncodings, grammarp->fallbackEncodings);
            if (MARPAESLIF_UNLIKELY(utf8s == NULL)) {
              goto err;
            }
            appendDatab = _marpaESLIFRecognizer_appendDatab(marpaESLIFRecognizerp, utf8s, utf8l, eofb);
            if (MARPAESLIF_UNLIKELY(! appendDatab)) {
              goto err;
            } else if (appendDatab < 0) {
              /* EAGAIN case: appending data tried to remove BOM, this is not eof, and there are not enough bytes */
              goto again;
            }
          }
        } else {
          /* ************************************************************************************************************************************************* */
          /*   - user gave NO encoding (encodings == NULL)                                                                                                     */
          /* ************************************************************************************************************************************************* */
          /* Continue with current conversion engine */
          utf8s = _marpaESLIF_charconvb(marpaESLIFp, (char *) MARPAESLIF_UTF8_STRING, marpaESLIF_streamp->encodings, inputs, inputl, &utf8l, NULL /* encodingsp */, &(marpaESLIF_streamp->tconvp), eofb, &(marpaESLIF_streamp->bytelefts), &(marpaESLIF_streamp->byteleftl), &(marpaESLIF_streamp->byteleftallocl), 0 /* tconvsilentb */, grammarp->defaultEncodings, grammarp->fallbackEncodings);
          if (MARPAESLIF_UNLIKELY(utf8s == NULL)) {
            goto err;
          }
          appendDatab = _marpaESLIFRecognizer_appendDatab(marpaESLIFRecognizerp, utf8s, utf8l, eofb);
          if (MARPAESLIF_UNLIKELY(! appendDatab)) {
            goto err;
          } else if (appendDatab < 0) {
            /* EAGAIN case: appending data tried to remove BOM, this is not eof, and there are not enough bytes */
            goto again;
          }
        }
      } else {
        /* ************************************************************************************************************************************************* */
        /* - Previous read was NOT a stream of characters (marpaESLIF_streamp->charconvb is false).                                                          */
        /* ************************************************************************************************************************************************* */
        /* Start a new conversion engine */
        charconvb = _marpaESLIFRecognizer_start_charconvb(marpaESLIFRecognizerp, encodings, encodingl, inputs, inputl, eofb, grammarp->defaultEncodings, grammarp->fallbackEncodings);
        if (MARPAESLIF_UNLIKELY(! charconvb)) {
          goto err;
        } else if (charconvb < 0) {
          /* EAGAIN case: charconv internally appends data, the later tried to remove BOM, this is not eof, and there are not enough bytes */
          goto again;
        }
      }
    } else {
      /* ************************************************************************************************************************************************* */
      /* User say this is not a stream of characters.                                                                                                      */
      /* ************************************************************************************************************************************************* */
      /* Here are the possible cases:                                                                                                                      */
      /* - Previous read was a stream of characters (marpaESLIF_streamp->charconvb is true).                                                               */
      /*   [We MUST have the input encodings in marpaESLIF_streamp->encodings and a current conversion engine in marpaESLIF_streamp->tconvp]               */
      /*   - Current encoding is flushed.                                                                                                                  */
      /*   - Data is appended as-is.                                                                                                                       */
      /* - Previous read was NOT a stream of characters (marpaESLIF_streamp->charconvb is false).                                                          */
      /*   - Data is appended as-is.                                                                                                                       */
      /* ************************************************************************************************************************************************* */
      if (marpaESLIF_streamp->charconvb) {
        /* ************************************************************************************************************************************************* */
        /* - Previous read was a stream of characters (marpaESLIF_streamp->charconvb is true).                                                               */
        /* ************************************************************************************************************************************************* */
        /* Flush current conversion engine */
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_flush_charconvb(marpaESLIFRecognizerp))) {
          goto err;
        }
        /* Data is appended as-is */
        appendDatab = _marpaESLIFRecognizer_appendDatab(marpaESLIFRecognizerp, inputs, inputl, eofb);
        if (MARPAESLIF_UNLIKELY(! appendDatab)) {
          goto err;
        } else if (MARPAESLIF_UNLIKELY(appendDatab < 0)) {
          /* EAGAIN case: should never happen because we said this is not anymore a character stream */
          MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Internal failure, appending data wants more data when it should not");
          goto err;
        }
      } else {
        /* ************************************************************************************************************************************************* */
        /* - Previous read was NOT a stream of characters (marpaESLIF_streamp->charconvb is false).                                                          */
        /* ************************************************************************************************************************************************* */
        /* Data is appended as-is */
        appendDatab = _marpaESLIFRecognizer_appendDatab(marpaESLIFRecognizerp, inputs, inputl, eofb);
        if (MARPAESLIF_UNLIKELY(! appendDatab)) {
          goto err;
        } else if (MARPAESLIF_UNLIKELY(appendDatab < 0)) {
          /* EAGAIN case: should never happen because we said this is not anymore a character stream */
          MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Internal failure, appending data wants more data when it should not");
          goto err;
        }
      }
      /* We do not know UTF-8 correctness. */
      marpaESLIF_streamp->utfb = 0;
    }
  }

  rcb = 1;
  marpaESLIF_streamp->eofb = eofb;

  /* We maintain here a very special thing: if there is EOF at the very first read, this mean that the user gave the whole stream */
  /* in ONE step: then removing PCRE2_ANCHORED is allowed. */
  if (marpaESLIF_streamp->nextReadIsFirstReadb) {
    marpaESLIF_streamp->noAnchorIsOkb = eofb;
    marpaESLIF_streamp->nextReadIsFirstReadb = 0; /* Next read will not be the first read */
  }

  goto done;

 err:
  rcb = 0;

 done:
  if (utf8s != NULL) {
    free(utf8s);
  }
  if (disposeCallbackb) {
    if (disposeCallbackp != NULL) {
      disposeCallbackp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, inputs, inputl, eofb, characterStreamb, encodings, encodingl);
    }
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

#define MARPAESLIF_LEVEL_CREATESHOW(grammarp, asciishowl, asciishows) do { \
    if (grammarp->leveli == 0) {                                        \
      asciishowl += 5;                                                  \
      if (asciishows != NULL) {                                         \
        strcat(asciishows, " ::= ");                                    \
      }                                                                 \
    } else if (grammarp->leveli == 1) {                                 \
      asciishowl += 3;                                                  \
      if (asciishows != NULL) {                                         \
        strcat(asciishows, " ~ ");                                      \
      }                                                                 \
    } else {                                                            \
      asciishowl += 2;                                                  \
      if (asciishows != NULL) {                                         \
        strcat(asciishows, " :");                                       \
      }                                                                 \
      sprintf(tmps, "%d", grammarp->leveli);                            \
      asciishowl += 1 + strlen(tmps) + 1;                               \
      if (asciishows != NULL) {                                         \
        strcat(asciishows, "[");                                        \
        strcat(asciishows, tmps);                                       \
        strcat(asciishows, "]");                                        \
      }                                                                 \
      asciishowl += 3;                                                  \
      if (asciishows != NULL) {                                         \
        strcat(asciishows, ":= ");                                      \
      }                                                                 \
    }                                                                   \
  } while (0)

#define MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, strings) do { \
    asciishowl += strlen(strings);                                      \
    if (asciishows != NULL) {                                           \
      strcat(asciishows, strings);                                      \
    }                                                                   \
  } while (0)

#define MARPAESLIF_STRING_CREATEQUOTE(quote, strings) do {      \
    if (strchr(strings, '\'') == NULL) {                        \
      strcpy(quote[0], "'");                                    \
      strcpy(quote[1], "'");                                    \
    } else if (strchr(strings, '"') == NULL) {                  \
      strcpy(quote[0], "\"");                                   \
      strcpy(quote[1], "\"");                                   \
    } else {                                                    \
      strcpy(quote[0], "");                                     \
      strcpy(quote[1], "");                                     \
    }                                                           \
  } while (0)

#define _MARPAESLIF_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp, rhsb) do { \
    if (symbolp->lookaheadb > 0) {                                      \
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "(?= ");     \
    } else if (symbolp->lookaheadb < 0) {                               \
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "(?! ");     \
    }                                                                   \
    switch (symbolp->type) {                                            \
    case MARPAESLIF_SYMBOL_TYPE_TERMINAL:                               \
      /* If rhsb is set, we support the alias in the show */            \
      if (rhsb && (symbolp->u.terminalp->descp != symbolp->descp)) {    \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "$");      \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->descp->asciis); \
      } else {                                                          \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->u.terminalp->descp->asciis); \
      }                                                                 \
      break;                                                            \
    case MARPAESLIF_SYMBOL_TYPE_META:                                   \
      if (symbolp->discardb) {                                          \
        /* Special case of ":discard" that we want to shown as is */    \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->u.metap->descp->asciis); \
      } else {                                                          \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "<");      \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->u.metap->descp->asciis); \
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ">");      \
      }                                                                 \
      if (MARPAESLIF_IS_LEXEME(symbolp)) {                              \
        /* Default lookup is grammarp->leveli + 1 : we output the @deltaLeveli information if this is not the case */ \
        if (symbolp->lookupResolvedLeveli != (grammarp->leveli + 1)) {  \
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "@");    \
          sprintf(tmps, "%+d", symbolp->lookupLevelDeltai);             \
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);   \
        }                                                               \
      }                                                                 \
    default:                                                            \
      break;                                                            \
    }                                                                   \
    if (symbolp->lookaheadb) {                                          \
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " )");       \
    }                                                                   \
   } while (0)

#define MARPAESLIF_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp) _MARPAESLIF_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp, 0)
#define MARPAESLIF_RHS_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp) _MARPAESLIF_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp, 1)
#define MARPAESLIF_LHS_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp) _MARPAESLIF_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp, 0)

#define MARPAESLIF_LHS_CREATESHOW(asciishowl, asciishows, symbolp, declp) do { \
    MARPAESLIF_LHS_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp);  \
    if (declp != NULL) {                                                \
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, declp->luaparlistcb ? "<--" : "<-"); \
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, declp->luaparlists); \
    }                                                                   \
   } while (0)

#define MARPAESLIF_RHS_CREATESHOW(asciishowl, asciishows, symbolp, callp) do { \
    MARPAESLIF_RHS_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp);  \
    if (callp != NULL) {                                                \
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, callp->luaexplistcb ? "-->" : "->"); \
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, callp->luaexplists); \
    }                                                                   \
   } while (0)

/*****************************************************************************/
static inline void _marpaESLIF_rule_createshowv(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, marpaESLIF_rule_t *rulep, char *asciishows, size_t *asciishowlp)
/*****************************************************************************/
{
  marpaESLIF_symbol_t *symbolp;
  short                skipb;
  size_t               asciishowl = 0;
  size_t               rhsl;
  char                 tmps[1024];
  char                 quote[2][2];

  /* Calculate the size needed to show the rule in ASCII form */

  MARPAESLIF_LHS_CREATESHOW(asciishowl, asciishows, rulep->lhsp, rulep->declp);
  MARPAESLIF_LEVEL_CREATESHOW(grammarp, asciishowl, asciishows);
  for (rhsl = 0; rhsl < rulep->nrhsl; rhsl++) {
    if (rhsl > 0) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " ");
    }
    symbolp = rulep->rhspp[rhsl];
    skipb = (rulep->skipbp != NULL) && rulep->skipbp[rhsl];
    if (skipb) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "(- ");
    }
    MARPAESLIF_RHS_CREATESHOW(asciishowl, asciishows, symbolp, rulep->callpp[rhsl]);
    if (skipb) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " -)");
    }
  }
  if (rulep->sequenceb) {
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, (rulep->minimumi == 0) ? "*" : "+");
    if (rulep->separatorp != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " separator => ");
      MARPAESLIF_RHS_CREATESHOW(asciishowl, asciishows, rulep->separatorp, rulep->separatorcallp);
    }
    if (rulep->properb) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " proper => 1");
    }
    if (rulep->hideseparatorb) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " hide-separator => 1");
    }
  }
  if (rulep->exceptionp != NULL) {
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " - ");
    MARPAESLIF_SYMBOL_CREATESHOW(asciishowl, asciishows, rulep->exceptionp); /* An exception consist of lexemes, that can never be parameterized */
  }
  if (rulep->ranki != 0) {
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " rank => ");
    sprintf(tmps, "%d", rulep->ranki);
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
  }
  if (rulep->nullRanksHighb) {
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " null-ranking => high");
  }
  if (rulep->actionp != NULL) {
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " action => ");
    switch (rulep->actionp->type) {
    case MARPAESLIF_ACTION_TYPE_NAME:
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, rulep->actionp->u.names);
      break;
    case MARPAESLIF_ACTION_TYPE_STRING:
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::u8\"");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, rulep->actionp->u.stringp->asciis); /* Best effort ASCII */
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\"");
      break;
    case MARPAESLIF_ACTION_TYPE_LUA:
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::lua->");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, rulep->actionp->u.luas);
      break;
    case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, rulep->actionp->u.luaFunction.actions);
      break;
    default:
      break;
    }
  }
  if ((! rulep->descautob) && (rulep->descp != NULL) && (rulep->descp->asciis != NULL)) {
    /* name adverb is allowed everywhere except with :discard */
    if (! rulep->lhsp->discardb) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " name => ");
      MARPAESLIF_STRING_CREATEQUOTE(quote, rulep->descp->asciis);
      if (strlen(quote[0]) > 0) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, quote[0]);
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, rulep->descp->asciis);
      if (strlen(quote[1]) > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, quote[1]);
      }
    }
  }
  if (rulep->lhsp->discardb && rulep->discardEvents != NULL) {
    /* Please note that this is a shared with symbol's discardEvents, even if the show does not "show" it */
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " event => ");
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, rulep->discardEvents);
    /* Show event state only if it off, default is on */
    if (! rulep->discardEventb) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "=off");
    }
  }
  if (rulep->internalb) {
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " /* Internal rule */");
  }

  asciishowl++; /* NUL byte */

  if (asciishowlp != NULL) {
    *asciishowlp = asciishowl;
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_grammar_createshowv(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIF_grammar_t *grammarp, char *asciishows, size_t *asciishowlp)
/*****************************************************************************/
{
  static const char            *funcs          = "_marpaESLIF_grammar_createshowv";
  marpaESLIF_t                 *marpaESLIFp    = marpaESLIFGrammarp->marpaESLIFp;
  genericStack_t               *symbolStackp   = grammarp->symbolStackp;
  genericStack_t               *ruleStackp     = grammarp->ruleStackp;
  genericLogger_t              *genericLoggerp = NULL;
  size_t                        asciishowl     = 0;
  marpaESLIF_uint32_t           pcre2Optioni   = 0;
  int                           pcre2Errornumberi;
  char                          tmps[1024];
  int                          *ruleip;
  size_t                        rulel;
  char                         *ruleshows;
  size_t                        l;
  char                          quote[2][2];
  marpaESLIF_symbol_t          *symbolp;
  int                           symboli;
  marpaESLIF_rule_t            *rulep;
  int                           rulei;
  int                           npropertyi;
  int                           neventi;
  marpaESLIF_stringGenerator_t  marpaESLIF_stringGenerator;
  short                         skipb;
  marpaESLIF_pcre2_callout_enumerate_context_t enumerate_context;

  /* Calculate the size needed to show the grammar in ASCII form */

  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "/*\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * **********************\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * Meta-grammar settings:\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * **********************\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " */\n");

  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ":start");
  MARPAESLIF_LEVEL_CREATESHOW(grammarp, asciishowl, asciishows);
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "<");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->starts);
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ">\n");

  if ((! grammarp->descautob) && (grammarp->descp != NULL) && (grammarp->descp->asciis != NULL)) {
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ":desc");
    MARPAESLIF_LEVEL_CREATESHOW(grammarp, asciishowl, asciishows);
    MARPAESLIF_STRING_CREATEQUOTE(quote, grammarp->descp->asciis);
    if (strlen(quote[0]) > 0) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, quote[0]);
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->descp->asciis);
    if (strlen(quote[1]) > 0) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, quote[1]);
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
  }
  if ((grammarp->defaultRuleActionp != NULL)
      ||
      (grammarp->defaultEventActionp != NULL)
      ||
      (grammarp->defaultRegexActionp != NULL)
      ||
      (grammarp->defaultSymbolActionp != NULL)
      ||
      (grammarp->latmb)
      ||
      (grammarp->discardIsFallbackb)
      ||
      (grammarp->defaultEncodings != NULL)
      ||
      (grammarp->fallbackEncodings != NULL)
      ) {
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ":default");
    MARPAESLIF_LEVEL_CREATESHOW(grammarp, asciishowl, asciishows);
    if (grammarp->defaultRuleActionp != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " action => ");
      switch (grammarp->defaultRuleActionp->type) {
      case MARPAESLIF_ACTION_TYPE_NAME:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultRuleActionp->u.names);
        break;
      case MARPAESLIF_ACTION_TYPE_STRING:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::u8\"");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultRuleActionp->u.stringp->asciis); /* Best effort ASCII */
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\"");
        break;
      case MARPAESLIF_ACTION_TYPE_LUA:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::lua->");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultRuleActionp->u.luas);
        break;
      case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultRuleActionp->u.luaFunction.actions);
        break;
      default:
        break;
      }
    }
    if (grammarp->defaultEventActionp != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " event-action => ");
      switch (grammarp->defaultEventActionp->type) {
      case MARPAESLIF_ACTION_TYPE_NAME:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultEventActionp->u.names);
        break;
      case MARPAESLIF_ACTION_TYPE_STRING:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::u8\"");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultEventActionp->u.stringp->asciis); /* Best effort ASCII */
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\"");
        break;
      case MARPAESLIF_ACTION_TYPE_LUA:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::lua->");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultEventActionp->u.luas);
        break;
      case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultEventActionp->u.luaFunction.actions);
        break;
      default:
        break;
      }
    }
    if (grammarp->defaultRegexActionp != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " regex-action => ");
      switch (grammarp->defaultRegexActionp->type) {
      case MARPAESLIF_ACTION_TYPE_NAME:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultRegexActionp->u.names);
        break;
      case MARPAESLIF_ACTION_TYPE_STRING:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::u8\"");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultRegexActionp->u.stringp->asciis); /* Best effort ASCII */
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\"");
        break;
      case MARPAESLIF_ACTION_TYPE_LUA:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::lua->");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultRegexActionp->u.luas);
        break;
      case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultRegexActionp->u.luaFunction.actions);
        break;
      default:
        break;
      }
    }
    if (grammarp->defaultSymbolActionp != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " symbol-action => ");
      switch (grammarp->defaultSymbolActionp->type) {
      case MARPAESLIF_ACTION_TYPE_NAME:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultSymbolActionp->u.names);
        break;
      case MARPAESLIF_ACTION_TYPE_STRING:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::u8\"");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultSymbolActionp->u.stringp->asciis); /* Best effort ASCII */
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\"");
        break;
      case MARPAESLIF_ACTION_TYPE_LUA:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::lua->");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultSymbolActionp->u.luas);
        break;
      case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultSymbolActionp->u.luaFunction.actions);
        break;
      default:
        break;
      }
    }
    if (grammarp->latmb) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " latm => 1");
    }
    if (grammarp->discardIsFallbackb) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " discard-is-fallback => 1");
    }
    if (grammarp->defaultEncodings != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " default-encoding => ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->defaultEncodings);
    }
    if (grammarp->fallbackEncodings != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " fallback-encoding => ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, grammarp->fallbackEncodings);
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
  }

  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "/*\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * ****************\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * Symbol settings:\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * ****************\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " */\n");

  /* Lexeme information - this is all about events */
  for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
#ifndef MARPAESLIF_NTRACE
    /* Should never happen */
    if (! GENERICSTACK_IS_PTR(symbolStackp, symboli)) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s): No PTR in symbolStackp[%d] ?", grammarp->leveli, grammarp->descp->asciis, symboli);
      continue;
    }
#endif
    symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_GET_PTR(symbolStackp, symboli);

    /* C.f. the validate(),, we made sure that eventBefores and eventAfters are mutually exclusive */
    if ((symbolp->eventBefores != NULL)
        ||
        (symbolp->eventAfters != NULL)
        ||
        (symbolp->priorityi != 0)
        ||
        (symbolp->verboseb)
        ||
        (symbolp->symbolActionp != NULL)
        ||
        (symbolp->ifActionp != NULL)
        ||
        (symbolp->generatorActionp!= NULL)
        ||
        ((symbolp->type == MARPAESLIF_SYMBOL_TYPE_TERMINAL) && (symbolp->descp != symbolp->u.terminalp->descp))
        ||
        ((symbolp->type == MARPAESLIF_SYMBOL_TYPE_META) && (symbolp->descp != symbolp->u.metap->descp))
        ) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# Symbol No ");
      sprintf(tmps, "%d", symbolp->idi);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ":symbol");
      MARPAESLIF_LEVEL_CREATESHOW(grammarp, asciishowl, asciishows);
      /* We voluntarily want to show the symbol as if it was an LHS definition */
      MARPAESLIF_LHS_SYMBOL_CREATESHOW(asciishowl, asciishows, symbolp);

      if (symbolp->eventBefores != NULL) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " pause => before event => ");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->eventBefores);
        /* Show event state only if it off, default is on */
        if (! symbolp->eventBeforeb) {
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "=off");
        }
      }
      if (symbolp->eventAfters != NULL) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " pause => after event => ");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->eventAfters);
        /* Show event state only if it off, default is on */
        if (! symbolp->eventAfterb) {
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "=off");
        }
      }
      if (symbolp->priorityi != 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " priority => ");
        sprintf(tmps, "%d", symbolp->priorityi);
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      }
      if (symbolp->verboseb) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " verbose => ");
        sprintf(tmps, "%d", (int) symbolp->verboseb);
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      }
      if (symbolp->symbolActionp != NULL) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " symbol-action => ");
        switch (symbolp->symbolActionp->type) {
        case MARPAESLIF_ACTION_TYPE_NAME:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->symbolActionp->u.names);
          break;
        case MARPAESLIF_ACTION_TYPE_STRING:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::u8\"");
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->symbolActionp->u.stringp->asciis); /* Best effort ASCII */
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\"");
          break;
        case MARPAESLIF_ACTION_TYPE_LUA:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::lua->");
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->symbolActionp->u.luas);
          break;
        case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->symbolActionp->u.luaFunction.actions);
          break;
        default:
          break;
        }
      }
      if (symbolp->ifActionp != NULL) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " if-action => ");
        switch (symbolp->ifActionp->type) {
        case MARPAESLIF_ACTION_TYPE_NAME:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->ifActionp->u.names);
          break;
        case MARPAESLIF_ACTION_TYPE_STRING:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::u8\"");
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->ifActionp->u.stringp->asciis); /* Best effort ASCII */
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\"");
          break;
        case MARPAESLIF_ACTION_TYPE_LUA:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::lua->");
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->ifActionp->u.luas);
          break;
        case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->ifActionp->u.luaFunction.actions);
          break;
        default:
          break;
        }
      }
      if (symbolp->generatorActionp != NULL) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " . => ");
        switch (symbolp->generatorActionp->type) {
        case MARPAESLIF_ACTION_TYPE_NAME:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->generatorActionp->u.names);
          break;
        case MARPAESLIF_ACTION_TYPE_STRING:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::u8\"");
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->generatorActionp->u.stringp->asciis); /* Best effort ASCII */
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\"");
          break;
        case MARPAESLIF_ACTION_TYPE_LUA:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "::lua->");
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->generatorActionp->u.luas);
          break;
        case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->generatorActionp->u.luaFunction.actions);
          break;
        default:
          break;
        }
      }
      if ((symbolp->type == MARPAESLIF_SYMBOL_TYPE_TERMINAL) && (symbolp->descp != symbolp->u.terminalp->descp)) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " name => ");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->descp->asciis);
      }
      if ((symbolp->type == MARPAESLIF_SYMBOL_TYPE_META) && (symbolp->descp != symbolp->u.metap->descp)) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " name => ");
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->descp->asciis);
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    }
  }

  /* Event information */
  for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
#ifndef MARPAESLIF_NTRACE
    /* Should never happen */
    if (! GENERICSTACK_IS_PTR(symbolStackp, symboli)) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s): No PTR in symbolStackp[%d] ?", grammarp->leveli, grammarp->descp->asciis, symboli);
      continue;
    }
#endif
    symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_GET_PTR(symbolStackp, symboli);

    if (symbolp->eventPredicteds != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "event ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->eventPredicteds);
      /* Show event state only if it off, default is on */
      if (! symbolp->eventPredictedb) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "=off");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " = predicted ");
      MARPAESLIF_LHS_CREATESHOW(asciishowl, asciishows, symbolp, symbolp->eventDeclp);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " /* Symbol No ");
      sprintf(tmps, "%d", symbolp->idi);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " */");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    }

    if (symbolp->eventNulleds != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "event ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->eventNulleds);
      /* Show event state only if it off, default is on */
      if (! symbolp->eventNulledb) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "=off");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " = nulled ");
      MARPAESLIF_LHS_CREATESHOW(asciishowl, asciishows, symbolp, symbolp->eventDeclp);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " /* Symbol No ");
      sprintf(tmps, "%d", symbolp->idi);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " */");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    }

    if (symbolp->eventCompleteds != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "event ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->eventCompleteds);
      /* Show event state only if it off, default is on */
      if (! symbolp->eventCompletedb) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "=off");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " = completed ");
      MARPAESLIF_LHS_CREATESHOW(asciishowl, asciishows, symbolp, symbolp->eventDeclp);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " /* Symbol No ");
      sprintf(tmps, "%d", symbolp->idi);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " */");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    }
  }

  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "/*\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * ******\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * Rules:\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " * ******\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " */\n");

  /* Rules */
  if (marpaESLIFGrammar_rulearray_by_levelb(marpaESLIFGrammarp, &ruleip, &rulel, grammarp->leveli, NULL /* descp */)) {
    for (l = 0; l < rulel; l++) {
      if (marpaESLIFGrammar_ruleshowform_by_levelb(marpaESLIFGrammarp, l, &ruleshows, grammarp->leveli, NULL /* descp */)) {
        if (ruleshows == NULL) {
          continue;
        }
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ruleshows);
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
      }
    }
  }


  /* Give useful information:
     - meta symbols that are terminals (they refered to another grammar)
     - nullable symbols
  */
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# The following is giving information on grammar components: lexemes, rules and symbols properties\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# --------\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# Lexemes:\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# --------\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#\n");
  for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
#ifndef MARPAESLIF_NTRACE
    /* Should never happen */
    if (! GENERICSTACK_IS_PTR(symbolStackp, symboli)) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s): No PTR in symbolStackp[%d] ?", grammarp->leveli, grammarp->descp->asciis, symboli);
      continue;
    }
#endif
    symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_GET_PTR(symbolStackp, symboli);
    if (symbolp->lhsb) {
      continue;
    }
    if (symbolp->type != MARPAESLIF_SYMBOL_TYPE_META) {
      continue;
    }
    if (symbolp->lookupSymbolp != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "<");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->descp->asciis);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ">");
      MARPAESLIF_LEVEL_CREATESHOW(grammarp, asciishowl, asciishows);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "<");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->lookupSymbolp->descp->asciis);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ">");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "@");
      sprintf(tmps, "%+d", symbolp->lookupLevelDeltai);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " /* Symbol No ");
      sprintf(tmps, "%d", symbolp->idi);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      sprintf(tmps, "@=%d", grammarp->leveli);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " => Symbol No ");
      sprintf(tmps, "%d", symbolp->lookupSymbolp->idi);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      sprintf(tmps, "@=%d", symbolp->lookupResolvedLeveli);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " (lookahead: ");
      if (symbolp->lookaheadb) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows,  "yes");
      } else {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows,  "no");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ") */\n");
    } else {
      /* This is very strange unless it is a parameterized symbol */
      if (! symbolp->parameterizedRhsb) {
        MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s): Symbol No %d <%s> is not an LHS nor an ESLIF META and has no lookup symbol", grammarp->leveli, grammarp->descp->asciis, symboli, symbolp->descp->asciis);
      }
    }
  }

  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# -----------------\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# Rules properties:\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# -----------------\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#\n");

  for (rulei = 0; rulei < GENERICSTACK_USED(ruleStackp); rulei++) {
#ifndef MARPAESLIF_NTRACE
    /* Should never happen */
    if (! GENERICSTACK_IS_PTR(ruleStackp, rulei)) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s): No PTR in ruleStackp[%d] ?", grammarp->leveli, grammarp->descp->asciis, rulei);
      continue;
    }
#endif
    rulep = (marpaESLIF_rule_t *) GENERICSTACK_GET_PTR(ruleStackp, rulei);
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# Rule No ");
    sprintf(tmps, "%d", rulep->idi);
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#   Properties: ");
    npropertyi = 0;
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_ACCESSIBLE) == MARPAWRAPPER_RULE_IS_ACCESSIBLE) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "ACCESSIBLE");
      npropertyi++;
    }
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_NULLABLE) == MARPAWRAPPER_RULE_IS_NULLABLE) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "NULLABLE");
    }
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_NULLING) == MARPAWRAPPER_RULE_IS_NULLING) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "NULLING");
    }
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_LOOP) == MARPAWRAPPER_RULE_IS_LOOP) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "LOOP");
    }
    if ((rulep->propertyBitSet & MARPAWRAPPER_RULE_IS_PRODUCTIVE) == MARPAWRAPPER_RULE_IS_PRODUCTIVE) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "PRODUCTIVE");
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#   Definition: ");
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, rulep->asciishows);

    marpaESLIF_stringGenerator.marpaESLIFp = marpaESLIFp;
    marpaESLIF_stringGenerator.s           = NULL;
    marpaESLIF_stringGenerator.l           = 0;
    marpaESLIF_stringGenerator.okb         = 0;
    marpaESLIF_stringGenerator.allocl      = 0;

    genericLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIF_generateStringWithLoggerCallback, (void *) &marpaESLIF_stringGenerator, GENERICLOGGER_LOGLEVEL_TRACE);
    if (genericLoggerp != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
      if (rulep->exceptionp != NULL) {
        GENERICLOGGER_TRACE (genericLoggerp, "#   Components:  LHS = RHS - EXCEPTION\n");
      } else {
        GENERICLOGGER_TRACE (genericLoggerp, "#   Components:  LHS = RHS[]\n");
      }
      GENERICLOGGER_TRACEF(genericLoggerp, "#               %4d", rulep->lhsp->idi);
      for (symboli = 0; symboli < rulep->nrhsl; symboli++) {
        symbolp = rulep->rhspp[symboli];
        skipb = (rulep->skipbp != NULL) && rulep->skipbp[symboli];
        if (symboli == 0) {
          GENERICLOGGER_TRACEF(genericLoggerp, " = %s%d%s", skipb ? "(- " : "", symbolp->idi, skipb ? " -)" : "");
        } else {
          GENERICLOGGER_TRACEF(genericLoggerp, " %s%d%s", skipb ? "(- " : "", symbolp->idi, skipb ? " -)" : "");
        }
      }
      if (rulep->exceptionp != NULL) {
        GENERICLOGGER_TRACEF(genericLoggerp, " - %d", rulep->exceptionp->idi);
      }
      if (marpaESLIF_stringGenerator.okb) {
        if (marpaESLIF_stringGenerator.s != NULL) {
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, marpaESLIF_stringGenerator.s);
        }
      }
      if (marpaESLIF_stringGenerator.s != NULL) {
        free(marpaESLIF_stringGenerator.s);
      }
      GENERICLOGGER_FREE(genericLoggerp);
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
  }

  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# -------------------\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# Symbols properties:\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# -------------------\n");
  MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#\n");

  for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
#ifndef MARPAESLIF_NTRACE
    /* Should never happen */
    if (! GENERICSTACK_IS_PTR(symbolStackp, symboli)) {
      MARPAESLIF_TRACEF(marpaESLIFp, funcs, "At grammar level %d (%s): No PTR in symbolStackp[%d] ?", grammarp->leveli, grammarp->descp->asciis, symboli);
      continue;
    }
#endif
    symbolp = (marpaESLIF_symbol_t *) GENERICSTACK_GET_PTR(symbolStackp, symboli);

    if (symboli > 0) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#\n");
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# Symbol No ");
    sprintf(tmps, "%d\n", symbolp->idi);
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
    switch (symbolp->type) {
    case MARPAESLIF_SYMBOL_TYPE_TERMINAL:
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#         Type: ESLIF TERMINAL\n");
      break;
    case MARPAESLIF_SYMBOL_TYPE_META:
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#         Type: ESLIF META\n");
      break;
    default:
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#         Type: ?\n");
      break;
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#   Properties: ");
    npropertyi = 0;
    if ((symbolp->propertyBitSet & MARPAWRAPPER_SYMBOL_IS_ACCESSIBLE) == MARPAWRAPPER_SYMBOL_IS_ACCESSIBLE) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "ACCESSIBLE");
      npropertyi++;
    }
    if ((symbolp->propertyBitSet & MARPAWRAPPER_SYMBOL_IS_NULLABLE) == MARPAWRAPPER_SYMBOL_IS_NULLABLE) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "NULLABLE");
    }
    if ((symbolp->propertyBitSet & MARPAWRAPPER_SYMBOL_IS_NULLING) == MARPAWRAPPER_SYMBOL_IS_NULLING) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "NULLING");
    }
    if ((symbolp->propertyBitSet & MARPAWRAPPER_SYMBOL_IS_PRODUCTIVE) == MARPAWRAPPER_SYMBOL_IS_PRODUCTIVE) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "PRODUCTIVE");
    }
    if ((symbolp->propertyBitSet & MARPAWRAPPER_SYMBOL_IS_START) == MARPAWRAPPER_SYMBOL_IS_START) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "START");
    }
    if ((symbolp->propertyBitSet & MARPAWRAPPER_SYMBOL_IS_TERMINAL) == MARPAWRAPPER_SYMBOL_IS_TERMINAL) {
      if (npropertyi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "TERMINAL");
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#       Events: ");

    neventi = 0;
    if ((symbolp->eventBitSet & MARPAESLIF_SYMBOL_EVENT_COMPLETION) == MARPAESLIF_SYMBOL_EVENT_COMPLETION) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "COMPLETION");
      neventi++;
    }
    if ((symbolp->eventBitSet & MARPAESLIF_SYMBOL_EVENT_NULLED) == MARPAESLIF_SYMBOL_EVENT_NULLED) {
      if (neventi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "NULLED");
    }
    if ((symbolp->eventBitSet & MARPAESLIF_SYMBOL_EVENT_PREDICTION) == MARPAESLIF_SYMBOL_EVENT_PREDICTION) {
      if (neventi++ > 0) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ", ");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "PREDICTION");
    }
    MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    if (symbolp->type == MARPAESLIF_SYMBOL_TYPE_TERMINAL) {
      if (symbolp->u.terminalp->pseudob) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#      Builtin:");
        switch (symbolp->u.terminalp->type) {
        case MARPAESLIF_TERMINAL_TYPE__EOF:
        case MARPAESLIF_TERMINAL_TYPE__EOL:
        case MARPAESLIF_TERMINAL_TYPE__SOL:
        case MARPAESLIF_TERMINAL_TYPE__EMPTY:
          /* We know we made a 100% ASCII compatible pattern that is the builtin lexeme itself when the original type is _EOF, _EOL, _SOL or _EMPTY */
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " ");
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->u.terminalp->patterns);
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
          break;
          break;
        default:
          break;
        }
      } else {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#      Pattern:");
        if (symbolp->u.terminalp->type == MARPAESLIF_TERMINAL_TYPE_STRING) {
          /* We know we made a 100% ASCII compatible pattern when the original type is STRING */
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " ");
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->u.terminalp->patterns);
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
        } else {
          /* Opaque UTF-8 pattern */
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
          MARPAESLIF_PATTERN_CREATESHOW(marpaESLIFp, symbolp->u.terminalp->patterns, symbolp->u.terminalp->patternl);
        }
        /* Dump PCRE2 flags - we inspect the regex because use can have put some other embedded options */
        pcre2Errornumberi = pcre2_pattern_info(symbolp->u.terminalp->regex.patternp, PCRE2_INFO_ALLOPTIONS, &pcre2Optioni);
        if (pcre2Errornumberi == 0) {
          MARPAESLIF_PCRE2_FLAGS_CREATESHOW(marpaESLIFp, "#        Flags: ", pcre2Optioni, 0 /* substituteb */);
        }
#ifdef PCRE2_CONFIG_JIT
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#          JIT: ");
        if (symbolp->u.terminalp->regex.jitb) {
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "yes");
        } else {
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "no");
        }
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
#endif
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#      Callout: ");
        if (symbolp->u.terminalp->regex.calloutb) {
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "yes");
        } else {
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "no");
        }
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
        if (symbolp->u.terminalp->regex.calloutb) {
          /* Enumerate callouts; if any */
          enumerate_context.marpaESLIFp = marpaESLIFp;
          enumerate_context.asciishows  = asciishows;
          enumerate_context.asciishowl  = asciishowl;
          enumerate_context.calloutb    = 0;
          pcre2_callout_enumerate(symbolp->u.terminalp->regex.patternp, _marpaESLIF_pcre2_callout_enumeratei, &enumerate_context);
          asciishows  = enumerate_context.asciishows;
          asciishowl  = enumerate_context.asciishowl;
        }
        if (symbolp->u.terminalp->substitutionPatterns != NULL) {
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "# Substitution:");
          /* Opaque UTF-8 pattern */
          MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
          MARPAESLIF_PATTERN_CREATESHOW(marpaESLIFp, symbolp->u.terminalp->substitutionPatterns, symbolp->u.terminalp->substitutionPatternl);
          /* Dump substitution flags - we know what they can be - this is not a regex. */
          MARPAESLIF_PCRE2_FLAGS_CREATESHOW(marpaESLIFp, "#   Sub. Flags: ", symbolp->u.terminalp->substitutionPatterni, 1 /* substituteb */);
        }
      }
    } else {
      /* This is an ESLIF meta */
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#         Name: ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "<");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->descp->asciis);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ">");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    }
    if (symbolp->lookupSymbolp != NULL) {
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#       Lookup: ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "<");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, symbolp->lookupSymbolp->descp->asciis);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ">");
      sprintf(tmps, "@=%d", symbolp->lookupResolvedLeveli);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " /* Symbol No ");
      sprintf(tmps, "%d", symbolp->idi);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      sprintf(tmps, "@=%d", grammarp->leveli);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " => Symbol No ");
      sprintf(tmps, "%d", symbolp->lookupSymbolp->idi);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      sprintf(tmps, "@=%d", symbolp->lookupResolvedLeveli);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, " (lookahead: ");
      if (symbolp->lookaheadb) {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows,  "yes");
      } else {
        MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows,  "no");
      }
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, ") */\n");
    }
    if (symbolp->parami >= 0) {
      sprintf(tmps, "%d", symbolp->parami);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "#       #param: ");
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, tmps);
      MARPAESLIF_STRING_CREATESHOW(asciishowl, asciishows, "\n");
    }
  }

  asciishowl++; /* NUL byte */

  if (asciishowlp != NULL) {
    *asciishowlp = asciishowl;
  }
}

/*****************************************************************************/
static inline int _marpaESLIF_utf82ordi(PCRE2_SPTR8 utf8bytes, marpaESLIF_uint32_t *uint32p, PCRE2_SPTR8 utf8maxexcludedp)
/*****************************************************************************/
/* If utf8maxexcludedp is set, then _marpaESLIF_utf82ordi is not allowed to read from this value */
/* We do not check if utf8maxexcludedp >= utf8bytes */
/*****************************************************************************/
/* This is a copy of utf2ord from pcre2test.c
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.

    * Neither the name of the University of Cambridge nor the names of its
      contributors may be used to endorse or promote products derived from
      this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
/* This function reads one or more bytes that represent a UTF-8 character,
and returns the codepoint of that character. Note that the function supports
the original UTF-8 definition of RFC 2279, allowing for values in the range 0
to 0x7fffffff, up to 6 bytes long. This makes it possible to generate
codepoints greater than 0x10ffff which are useful for testing PCRE2's error
checking, and also for generating 32-bit non-UTF data values above the UTF
limit.

Argument:
  utf8bytes   a pointer to the byte vector
  vptr        a pointer to an int to receive the value

Returns:      >  0 => the number of bytes consumed
              -6 to 0 => malformed UTF-8 character at offset = (-return)
*/
/*****************************************************************************/
{
  marpaESLIF_uint32_t c = *utf8bytes++;
  marpaESLIF_uint32_t d = c;
  int                 i;
  int                 j;
  int                 s;

  for (i = -1; i < 6; i++) {               /* i is number of additional bytes */
    if ((d & 0x80) == 0) break;
    d <<= 1;
  }

  if (i == -1) {
    /* ascii character */
    *uint32p = c;
    return 1;
  }
  if (i == 0 || i == 6) {
    return 0;
  } /* invalid UTF-8 */

  /* i now has a value in the range 1-5 */

  s = 6*i;
  d = (c & utf8_table3[i]) << s;

  for (j = 0; j < i; j++) {
    if ((utf8maxexcludedp != NULL) && (utf8bytes >= utf8maxexcludedp)) {
      return -(j+1);
    }
    c = *utf8bytes++;
    if ((c & 0xc0) != 0x80) {
      return -(j+1);
    }
    s -= 6;
    d |= (c & 0x3f) << s;
  }

  /* Check that encoding was the correct unique one */

  for (j = 0; j < utf8_table1_size; j++) {
    if (d <= (uint32_t)utf8_table1[j]) {
      break;
    }
  }
  if (j != i) {
    return -(i+1);
  }

  /* Valid value */

  *uint32p = d;
  return i+1;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_getNextLineAndColumnb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t matchl)
/*****************************************************************************/
{
  static const char          *funcs              = "_marpaESLIFRecognizer_getNextLineAndColumnb";
  marpaESLIF_stream_t        *marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  marpaESLIF_terminal_t      *newlinep;
  char                       *linep;
  char                       *linemaxp;
  size_t                      linel;
  size_t                      matchedLengthl;
  marpaESLIF_matcher_value_t  rci;
  short                       rcb;
  int                         utf82ordi;
  marpaESLIF_uint32_t         codepointi;
    
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* If newline counting is on, so do we */
  if (marpaESLIFRecognizerp->marpaESLIFRecognizerOption.newlineb && marpaESLIF_streamp->utfb) {
    newlinep = marpaESLIFRecognizerp->marpaESLIFp->newlinep;
    linep = marpaESLIF_streamp->inputs;
    linel = matchl;

    /* Check newline */
    while (1) {
      /* We count newlines only when a discard or a complete has happened. So by definition */
      /* character sequences are complete. This is why we fake EOF to true. */
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_terminal_matcherb(marpaESLIFRecognizerp,
                                                                        marpaESLIF_streamp,
                                                                        newlinep,
                                                                        linep,
                                                                        linel,
                                                                        1, /* eofb */
                                                                        &rci,
                                                                        NULL /* marpaESLIFValueResultp */,
                                                                        &matchedLengthl))) {
        goto err;
      }
      if (rci != MARPAESLIF_MATCH_OK) {
        break;
      }
      linep += matchedLengthl;
      linel -= matchedLengthl;
      /* A new line, reset column count */
      marpaESLIF_streamp->linel++;
      marpaESLIF_streamp->columnl = 1;
    }

    if (linel > 0) {
      /* Count characters */
      linemaxp = linep + linel;
      while (linep < linemaxp) {
        /* We count newlines only when a discard or a complete has happened. So by definition */
        /* character sequences are complete. This is why the following should never fail. */
        utf82ordi = _marpaESLIF_utf82ordi((PCRE2_SPTR8) linep, &codepointi, (PCRE2_SPTR8) linemaxp);
        if (MARPAESLIF_UNLIKELY(utf82ordi <= 0)) {
          MARPAESLIF_WARN(marpaESLIFRecognizerp->marpaESLIFp, "Malformed UTF-8 character when processing column number");
          break;
        }

        linep += utf82ordi;
        marpaESLIF_streamp->columnl++;
      }
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_matchPostProcessingb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t matchl)
/*****************************************************************************/
{
  static const char   *funcs              = "_marpaESLIFRecognizer_matchPostProcessingb";
  marpaESLIF_stream_t *marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  short                rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Update line and column numbers */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_getNextLineAndColumnb(marpaESLIFRecognizerp, matchl))) {
    goto err;
  }

  /* Update internal position */
  if (matchl > 0) {
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Advancing stream position %p by %ld bytes", marpaESLIF_streamp->inputs, (unsigned long) matchl);
    marpaESLIF_streamp->inputs += matchl;
    marpaESLIF_streamp->inputl -= matchl;
  }

  /* Check if we are at start completion and update number of bytes (eventually cumulative ones if we are not at start completion) */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_checkStartCompletionb(marpaESLIFRecognizerp, matchl))) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_progressLogb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, int starti, int endi, genericLoggerLevel_t logleveli)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_progressLogb";
  short              silentb;
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Caller has access to this recognizer per def and asked for a progress report. */
  /* We want to unsilent the recognizer in any case.                               */
  silentb = marpaESLIFRecognizerp->silentb;
  marpaESLIFRecognizerp->silentb = 0;

  rcb = marpaWrapperRecognizer_progressLogb(marpaESLIFRecognizerp->marpaWrapperRecognizerp,
                                            starti,
                                            endi,
                                            logleveli,
                                            marpaESLIFRecognizerp->grammarp,
                                            _marpaESLIFGrammar_symbolDescriptionCallbacks);

  marpaESLIFRecognizerp->silentb = silentb;

  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
marpaESLIFRecognizer_t *marpaESLIFValue_recognizerp(marpaESLIFValue_t *marpaESLIFValuep)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFValue_recognizerp";

  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return NULL;
  }

  return marpaESLIFValuep->marpaESLIFRecognizerp;
}

/*****************************************************************************/
marpaESLIFValueOption_t *marpaESLIFValue_optionp(marpaESLIFValue_t *marpaESLIFValuep)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFValue_optionp";

  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return NULL;
  }

  return &(marpaESLIFValuep->marpaESLIFValueOption);
}

/*****************************************************************************/
marpaESLIFGrammar_t *marpaESLIFRecognizer_grammarp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_grammarp";

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    return NULL;
  }

  return marpaESLIFRecognizerp->grammarp->marpaESLIFGrammarp;
}

/*****************************************************************************/
marpaESLIFRecognizerOption_t *marpaESLIFRecognizer_optionp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_optionp";

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    return NULL;
  }

  return &(marpaESLIFRecognizerp->marpaESLIFRecognizerOption);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_appendDatab(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *datas, size_t datal, short eofb)
/*****************************************************************************/
{
  static const char       *funcs              = "_marpaESLIFRecognizer_appendDatab";
  marpaESLIF_stream_t     *marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  char                    *buffers            = marpaESLIF_streamp->buffers;
  size_t                   bufferallocl       = marpaESLIF_streamp->bufferallocl;
  char                    *globalOffsetp      = marpaESLIF_streamp->globalOffsetp;
  size_t                   bufferl            = marpaESLIF_streamp->bufferl;
  size_t                   inputl             = marpaESLIF_streamp->inputl;
  size_t                   deltal             = marpaESLIF_streamp->inputs - buffers;
  size_t                   bufsizl            = marpaESLIF_streamp->bufsizl;
  size_t                   buftriggerl        = marpaESLIF_streamp->buftriggerl;
  unsigned int             bufaddperci        = marpaESLIFRecognizerp->marpaESLIFRecognizerOption.bufaddperci;
  short                    removebomb;
  size_t                   bomsizel;
  size_t                   wantedl;
  size_t                   minwantedl;
  char                    *tmps;
  short                    rcb;

  /* The stream is decomposed like this:                   */
  /*                                                       */
  /* ----------------------------------------------------- */
  /* ^                          ^                          */
  /* |                          |                          */
  /* buffers                    |                          */
  /*                            inputs                     */
  /*                                                       */
  /* <--------------------- bufferl -------------------- > */
  /* <-------- deltal --------->< ------- inputl ------- > */
  /* ----------------------------------------------------- */

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start (datas=%p, datal=%ld)", datas, (unsigned long) datal);

  if (datal <= 0) {
    /* Nothing to do */
    rcb = 1;
    goto done;
  }

  if (MARPAESLIFRECOGNIZER_IS_TOP(marpaESLIFRecognizerp) /* Top recognizer ? */
      &&
      (marpaESLIF_streamp->peeki == 0)                   /* Not peeked ? */
      ) {
    /* We can crunch data at any time unless blocked because of a pending BOM check. */

    if (((marpaESLIF_streamp->tconvp == NULL) || marpaESLIF_streamp->bomdoneb) /* BOM check done or not needed ? */
        &&
        (bufferallocl > buftriggerl)          /* If we allocated more than the trigger */
        &&                                    /* and */
        (inputl > 0)                          /* some bytes were already processed */
        &&                                    /* and */
        (inputl < bufsizl)                    /* there is less remaining bytes to process than minimum buffer size */
        ) {
      /* ... then we can realloc to minimum buffer size */

      /* Before reallocating, we need to move the remaining bytes at the beginning */
      memmove(buffers, marpaESLIF_streamp->inputs, inputl + 1);       /* + 1 for internal NUL byte */
      /* Try to realloc */
      wantedl = bufsizl;
      tmps = realloc(buffers, wantedl + 1); /* We always add a hiden NUL byte for convenience */
      if (MARPAESLIF_UNLIKELY(tmps == NULL)) {
        /* We COULD continue, this is not truely fatal - but we are in a bad shape anyway -; */
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "realloc failure, %s", strerror(errno));
        goto err;
      }
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Internal buffer crunched from {%p,%ld} bytes to {%p,%ld} bytes", buffers, (unsigned long) (bufferallocl + 1), tmps, (unsigned long) (wantedl + 1));
      buffers       = marpaESLIF_streamp->buffers      = tmps;        /* Buffer pointer */
      bufferallocl  = marpaESLIF_streamp->bufferallocl = wantedl;     /* Allocated size */
      bufferl       = marpaESLIF_streamp->bufferl      = inputl;      /* Number of valid bytes */
      deltal        = 0;                                              /* Delta between inputs and buffers */
      globalOffsetp += inputl;                                        /* We "forget" inputl bytes: increase global offset (size_t turnaround not checked) */
      marpaESLIF_streamp->globalOffsetp = globalOffsetp;
      marpaESLIF_streamp->inputs = buffers;
    }
  }

  /* Append data */
  if (buffers == NULL) {
    /* First time we put in the buffer */
    wantedl = (bufsizl < datal) ? datal : bufsizl;
    tmps = (char *) malloc(wantedl + 1); /* We always add a NUL byte for convenience */
    if (MARPAESLIF_UNLIKELY(tmps == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Internal buffer created at {%p,%ld} bytes", tmps, (unsigned long) (wantedl + 1));
    buffers      = marpaESLIF_streamp->buffers      = tmps;        /* Buffer pointer */
    bufferallocl = marpaESLIF_streamp->bufferallocl = wantedl;     /* Allocated size */
    bufferl      = marpaESLIF_streamp->bufferl      = 0;           /* Number of valid bytes (increased below) */
    marpaESLIF_streamp->inputs = buffers;                          /* Pointer inside internal buffer is at the beginning */
  } else {
    wantedl = bufferl + datal;
    if (wantedl > bufferallocl) {
      /* We need more bytes than what has been allocated. Apply augment policy */
      minwantedl = (bufferallocl * (100 + bufaddperci)) / 100;
      /* minwantedl is guaranteed to be >= bufferallocl (modulo turnaround, that we do not consider here) */
      if (wantedl < minwantedl) {
        wantedl = minwantedl;
      }
      tmps = (char *) realloc(buffers, wantedl + 1); /* We always add a NUL byte for convenience */
      if (MARPAESLIF_UNLIKELY(tmps == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "realloc failure, %s", strerror(errno));
        goto err;
      }
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Internal buffer resized from {%p,%ld} bytes to {%p,%ld} bytes", buffers, (unsigned long) (bufferallocl + 1), tmps, (unsigned long) (wantedl + 1));
      buffers      = marpaESLIF_streamp->buffers      = tmps;        /* Buffer pointer */
      bufferallocl = marpaESLIF_streamp->bufferallocl = wantedl;     /* Allocated size */
      /* Pointer inside internal buffer is moving */
      marpaESLIF_streamp->inputs = buffers + deltal;
    }
  }

  /* In any case, append data just after the valid bytes */
  memcpy(buffers + bufferl, datas, datal);

  /* Commit number of valid bytes, and number of remaining bytes to process */
  marpaESLIF_streamp->bufferl += datal;
  marpaESLIF_streamp->inputl  += datal;

  /* Add a convenient NUL byte after valid data */
  buffers[marpaESLIF_streamp->bufferl] = '\0';

  /* In character mode, process BOM if not already done - we test marpaESLIF_streamp->tconvp instead of marpaESLIF_streamp->charconvb because */
  /* the later is set to true only after append data is done */
  if ((marpaESLIF_streamp->tconvp != NULL) && (! marpaESLIF_streamp->bomdoneb)) {
    removebomb = _marpaESLIF_string_removebomb(marpaESLIFRecognizerp->marpaESLIFp, marpaESLIF_streamp->inputs, &(marpaESLIF_streamp->inputl), (char *) MARPAESLIF_UTF8_STRING, &bomsizel);
    if (MARPAESLIF_UNLIKELY(! removebomb)) {
      goto err;
    } else if (removebomb > 0) {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "BOM is %ld bytes", (unsigned long) bomsizel);
      /* BOM processed */
      marpaESLIF_streamp->bomdoneb = 1;
      /* It is guaranteed that buffer was never crunched because of this pending BOM check - _marpaESLIF_string_removebomb() did an internal memmove, decreasing inputl */
      marpaESLIF_streamp->bufferl = marpaESLIF_streamp->inputl;
    } else {
      if (! eofb) {
        MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "BOM must be checked at next read");
        rcb = -1;
        goto done;
      } else {
        MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "BOM cannot be checked and eof is reached");
      }
    }
  }

  /* Please see the free method for the impact on parent's current pointer in input   */
  /* This need to be done once only, at return, this is why it is done at free level. */
  /* Note that when we create a grand child we strip off ALL events, so the user can */
  /* never got control back until we are finished. I.e. until all the free methods of */
  /* all the children are executed -; */

  /* MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: buffers=%p, bufferl=%04ld, inputs=%p, inputl=%4ld", funcs, marpaESLIF_streamp->buffers, (unsigned long) marpaESLIF_streamp->bufferl, marpaESLIF_streamp->inputs, (unsigned long) marpaESLIF_streamp->inputl); */
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_createDiscardStateb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char    *funcs                = "_marpaESLIFRecognizer_createDiscardStateb";
  short                *discardEventStatebp  = marpaESLIFRecognizerp->discardEventStatebp;
  marpaESLIF_grammar_t *grammarp;
  genericStack_t       *symbolStackp;
  short                 rcb;
  int                   symboli;
  marpaESLIF_symbol_t  *symbolp;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (discardEventStatebp == NULL) {
    /* First time */
    grammarp             = marpaESLIFRecognizerp->grammarp;
    symbolStackp         = grammarp->symbolStackp;

    discardEventStatebp = (short *) malloc(sizeof(short) * GENERICSTACK_USED(symbolStackp));
    if (MARPAESLIF_UNLIKELY(discardEventStatebp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFRecognizerp->marpaESLIFp, symbolp, grammarp, symboli);
      discardEventStatebp[symboli] = symbolp->discardEventb;
    }

    /* Initialization ok */
    marpaESLIFRecognizerp->discardEventStatebp = discardEventStatebp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_createBeforeStateb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char    *funcs               = "_marpaESLIFRecognizer_createBeforeStateb";
  short                *beforeEventStatebp  = marpaESLIFRecognizerp->beforeEventStatebp;
  marpaESLIF_grammar_t *grammarp;
  genericStack_t       *symbolStackp;
  short                 rcb;
  int                   symboli;
  marpaESLIF_symbol_t  *symbolp;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (beforeEventStatebp == NULL) {
    /* First time */
    grammarp            = marpaESLIFRecognizerp->grammarp;
    symbolStackp        = grammarp->symbolStackp;

    beforeEventStatebp = (short *) malloc(sizeof(short) * GENERICSTACK_USED(symbolStackp));
    if (MARPAESLIF_UNLIKELY(beforeEventStatebp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFRecognizerp->marpaESLIFp, symbolp, grammarp, symboli);
      beforeEventStatebp[symboli] = symbolp->eventBeforeb;
    }

    /* Initialization ok */
    marpaESLIFRecognizerp->beforeEventStatebp = beforeEventStatebp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_createAfterStateb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char    *funcs              = "_marpaESLIFRecognizer_createAfterStateb";
  short                *afterEventStatebp  = marpaESLIFRecognizerp->afterEventStatebp;
  marpaESLIF_grammar_t *grammarp;
  genericStack_t       *symbolStackp;
  short                 rcb;
  int                   symboli;
  marpaESLIF_symbol_t  *symbolp;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (afterEventStatebp == NULL) {
    /* First time */
    grammarp            = marpaESLIFRecognizerp->grammarp;
    symbolStackp        = grammarp->symbolStackp;

    afterEventStatebp = (short *) malloc(sizeof(short) * GENERICSTACK_USED(symbolStackp));
    if (MARPAESLIF_UNLIKELY(afterEventStatebp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }
    for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
      MARPAESLIF_GRAMMAR_INTERNAL_GET_SYMBOL(marpaESLIFRecognizerp->marpaESLIFp, symbolp, grammarp, symboli);
      afterEventStatebp[symboli] = symbolp->eventAfterb;
    }

    /* Initialization ok */
    marpaESLIFRecognizerp->afterEventStatebp = afterEventStatebp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_createSymbolDatab(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_symbol_data_t ***symbolDatappp, short forPauseb)
/*****************************************************************************/
{
  /* It assumed that symbolDatappp is != NULL */
  static const char         *funcs        = "_marpaESLIFRecognizer_createSymbolDatab";
  marpaESLIF_t              *marpaESLIFp  = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIF_symbol_data_t **symbolDatapp = *symbolDatappp;
  marpaESLIF_grammar_t      *grammarp;
  genericStack_t            *symbolStackp;
  short                      rcb;
  int                        symboli;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (symbolDatapp == NULL) {
    /* First time */
    grammarp            = marpaESLIFRecognizerp->grammarp;
    symbolStackp        = grammarp->symbolStackp;

    if (marpaESLIFp->NULLisZeroBytesb) {
      symbolDatapp = (marpaESLIF_symbol_data_t **) calloc(GENERICSTACK_USED(symbolStackp), sizeof(marpaESLIF_symbol_data_t *));
      if (MARPAESLIF_UNLIKELY(symbolDatapp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "calloc failure, %s", strerror(errno));
        goto err;
      }
    } else {
      symbolDatapp = (marpaESLIF_symbol_data_t **) malloc(sizeof(marpaESLIF_symbol_data_t *) * GENERICSTACK_USED(symbolStackp));
      if (MARPAESLIF_UNLIKELY(symbolDatapp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      for (symboli = 0; symboli < GENERICSTACK_USED(symbolStackp); symboli++) {
        symbolDatapp[symboli] = NULL;
      }
    }

    /* Initialization ok */
    *symbolDatappp = symbolDatapp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_createLastPauseb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_createSymbolDatab(marpaESLIFRecognizerp, &(marpaESLIFRecognizerp->lastPausepp), 1 /* forPauseb */);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_createLastTryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_createSymbolDatab(marpaESLIFRecognizerp, &(marpaESLIFRecognizerp->lastTrypp), 0 /* forPauseb */);
}

/*****************************************************************************/
static inline unsigned int _marpaESLIF_charset_toupperi(marpaESLIF_t *marpaESLIFp, const char c)
/*****************************************************************************/
/* We follow java.nio.charset.Charset definition of a charset.               */
{
  static const int    upperdeltai = 'a' - 'A';
  const unsigned char uc = (unsigned char) c;

  if (((uc >= 'A') && (uc <= 'Z')) || ((uc >= '0') && (uc <= '9'))) {
    return uc;
  }

  if ((uc >= 'a') && (uc <= 'z')) {
    return uc - upperdeltai;
  }

  switch (uc) {
  case '-':
  case '+':
  case '.':
  case ':':
  case '_':
    return uc;
  default:
    /* Invalid character */
    MARPAESLIF_ERRORF(marpaESLIFp, "Invalid character in charset: '%c' (0x%02lx)", (unsigned char) c, (unsigned long) c);
    return 0;
  }
}

/*****************************************************************************/
static inline short _marpaESLIF_charset_eqb(marpaESLIF_t *marpaESLIFp, const char *s, const char *p, size_t sizel)
/*****************************************************************************/
/* A charset-dedicated comparison function.                                  */
/* ASCII encoding is assumed.                                                */
/* Take care: sizel is the size on p.                                        */
/* s is assumed to be a valid charset, NUL terminated ASCII string.          */
/*****************************************************************************/
{
  unsigned int i;

  if (sizel <= 0) {
    return 0;
  }

  do {
    i = _marpaESLIF_charset_toupperi(marpaESLIFp, *p++);
    if (i == '\0') {
      /* Invalid character */
      return 0;
    }

    if (i != (unsigned int) *s++) {
      /* Not the same */
      return 0;
    }
  } while (--sizel > 0);

  return 1;
}

/*****************************************************************************/
static inline char *_marpaESLIF_charset_canonicals(marpaESLIF_t *marpaESLIFp, const char *s, const size_t sizel)
/*****************************************************************************/
/* Allocate a string on the heap that contains the canonical charset.        */
/*****************************************************************************/
{
  static const char *funcs    = "_marpaESLIF_charset_canonicals";
  char              *charsets = NULL;
  size_t             i;

  if (MARPAESLIF_UNLIKELY(sizel <= 0)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Invalid charset sizel");
    goto err;
  }

  charsets = (char *) malloc(sizel + 1);
  if (MARPAESLIF_UNLIKELY(charsets == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }
  for (i = 0; i < sizel; i++) {
    charsets[i] = (char) _marpaESLIF_charset_toupperi(marpaESLIFp, s[i]);
    if (MARPAESLIF_UNLIKELY(charsets[i] == '\0')) {
      goto err;
    }
  }
  charsets[sizel] = '\0';
  goto done;

 err:
  if (charsets != NULL) {
    free(charsets);
    charsets = NULL;
  }

 done:
  return charsets;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_flush_charconvb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char   *funcs              = "_marpaESLIFRecognizer_flush_charconvb";
  marpaESLIF_t        *marpaESLIFp        = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIF_stream_t *marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  char                *utf8s              = NULL;
  size_t               utf8l;
  short                rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* It is a non-sense to flush a character conversion engine if we were not already in this state */
  if (MARPAESLIF_UNLIKELY(! marpaESLIF_streamp->charconvb)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Previous state says character conversion is off");
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->encodings == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Previous encoding is unknown");
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->tconvp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Previous conversion engine is not set");
    goto err;
  }

  /* Note that here we let tconvsilentb == 0. This is because if we flush, then we were able to start character convertion. Flushing should not fail then. */
  utf8s = _marpaESLIF_charconvb(marpaESLIFp, NULL /* toEncodings, was MARPAESLIF_UTF8_STRING */, NULL /* fromEncodings */, NULL /* srcs */, 0 /* srcl */, &utf8l /* dstlp */, NULL /* fromEncodingsp */, &(marpaESLIF_streamp->tconvp), 1 /* eofb */, &(marpaESLIF_streamp->bytelefts), &(marpaESLIF_streamp->byteleftl), &(marpaESLIF_streamp->byteleftallocl), 0 /* tconvsilentb */, NULL /* defaultEncodings */, NULL /* fallbackEncodings*/);
  if (MARPAESLIF_UNLIKELY(utf8s == NULL)) {
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_appendDatab(marpaESLIFRecognizerp, utf8s, utf8l, 1 /* eofb */))) {
    goto err;
  }

  /* last state is cleaned */
  free(marpaESLIF_streamp->encodings);
  marpaESLIF_streamp->encodings = NULL;

  if (MARPAESLIF_UNLIKELY(tconv_close(marpaESLIF_streamp->tconvp) != 0)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "tconv_close failure, %s", strerror(errno));
    marpaESLIF_streamp->tconvp = NULL; /* A priori a retry is a bad idea, even during general cleanup... */
    goto err;
  }
  marpaESLIF_streamp->tconvp = NULL;

  /* Put global flag to off */
  marpaESLIF_streamp->charconvb = 0;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  if (utf8s != NULL) {
    free(utf8s);
  }
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_start_charconvb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *encodings, size_t encodingl, char *srcs, size_t srcl, short eofb, char *defaultEncodings, char *fallbackEncodings)
/*****************************************************************************/
/* Take care: this CAN RETURN -1, meaning that it needs more data, the reason is BOM removal */
/*****************************************************************************/
{
  static const char          *funcs              = "_marpaESLIFRecognizer_start_charconvb";
  marpaESLIF_t               *marpaESLIFp        = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIF_stream_t        *marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  marpaESLIF_grammar_t       *grammarp            = marpaESLIFRecognizerp->grammarp;
  char                       *encodingasciis     = NULL;
  char                       *utf8s              = NULL;
  size_t                      utf8l;
  short                       appendDatab;
  short                       rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* It is a non-sense to start a character conversion engine if we were already in this state */
  if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->charconvb)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Previous state says character conversion is on");
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->encodings != NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Previous encoding is already known");
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->tconvp != NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Previous conversion engine is already set");
    goto err;
  }

  /* New char conversion is starting: we have to take care of the BOM */
  marpaESLIF_streamp->bomdoneb = 0;

  /* Get an eventual ASCII version of input encoding */
  if ((encodings != NULL) && (encodingl > 0)) {
    encodingasciis = _marpaESLIF_charset_canonicals(marpaESLIFp, encodings, encodingl);
    if (MARPAESLIF_UNLIKELY(encodingasciis == NULL)) {
      goto err;
    }
  }

  /* Convert input */
  utf8s = _marpaESLIF_charconvb(marpaESLIFp, (char *) MARPAESLIF_UTF8_STRING, encodingasciis, srcs, srcl, &utf8l, &(marpaESLIF_streamp->encodings), &(marpaESLIF_streamp->tconvp), eofb, &(marpaESLIF_streamp->bytelefts), &(marpaESLIF_streamp->byteleftl), &(marpaESLIF_streamp->byteleftallocl), marpaESLIFRecognizerp->silentb, grammarp->defaultEncodings, grammarp->fallbackEncodings);
  if (MARPAESLIF_UNLIKELY(utf8s == NULL)) {
    goto err;
  }

  /* Verify information is set */
  if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->encodings == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Encoding has not been set");
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(marpaESLIF_streamp->tconvp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Conversion engine has not been set");
    goto err;
  }

  /* We hardcode conversion to UTF-8, tconv will certify UTF-8 correctness */
  marpaESLIF_streamp->utfb = 1;

  appendDatab = _marpaESLIFRecognizer_appendDatab(marpaESLIFRecognizerp, utf8s, utf8l, eofb);
  /* Take care: appendDatab can be < 0 */
  if (MARPAESLIF_UNLIKELY(! appendDatab)) {
    goto err;
  }

  /* Put global flag to on */
  marpaESLIF_streamp->charconvb = 1;

  rcb = appendDatab;
  goto done;

 err:
  rcb = 0;

 done:
  if (encodingasciis != NULL) {
    free(encodingasciis);
  }
  if (utf8s != NULL) {
    free(utf8s);
  }
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFValue_value_startb(marpaESLIFValue_t *marpaESLIFValuep, int *startip)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return marpaWrapperValue_value_startb(marpaESLIFValuep->marpaWrapperValuep, startip);
}

/*****************************************************************************/
short marpaESLIFValue_value_lengthb(marpaESLIFValue_t *marpaESLIFValuep, int *lengthip)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return marpaWrapperValue_value_lengthb(marpaESLIFValuep->marpaWrapperValuep, lengthip);
}

/*****************************************************************************/
marpaESLIFGrammar_t *marpaESLIF_grammarp(marpaESLIF_t *marpaESLIFp)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    return NULL;
  }

  return marpaESLIFp->marpaESLIFGrammarp;
}

/*****************************************************************************/
short marpaESLIFGrammar_ngrammarib(marpaESLIFGrammar_t *marpaESLIFGrammarp, int *ngrammarip)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    return 0;
  }

  if (ngrammarip != NULL) {
    *ngrammarip = GENERICSTACK_USED(marpaESLIFGrammarp->grammarStackp);
  }

  return 1;
}

/*****************************************************************************/
short marpaESLIFGrammar_defaultsb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFGrammarDefaults_t *marpaESLIFGrammarDefaultsp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t        *grammarp;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    return 0;
  }

  grammarp = marpaESLIFGrammarp->grammarp;
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return marpaESLIFGrammar_defaults_by_levelb(marpaESLIFGrammarp, marpaESLIFGrammarDefaultsp, grammarp->leveli, NULL /* descp */);
}

/*****************************************************************************/
short marpaESLIFGrammar_defaults_by_levelb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFGrammarDefaults_t *marpaESLIFGrammarDefaultsp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t        *grammarp;
  marpaESLIFGrammarDefaults_t  marpaESLIFGrammarDefaults;
  short                        rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  marpaESLIFGrammarDefaults.defaultRuleActionp      = grammarp->defaultRuleActionp;
  marpaESLIFGrammarDefaults.defaultEventActionp     = grammarp->defaultEventActionp;
  marpaESLIFGrammarDefaults.defaultRegexActionp     = grammarp->defaultRegexActionp;
  marpaESLIFGrammarDefaults.defaultSymbolActionp    = grammarp->defaultSymbolActionp;
  marpaESLIFGrammarDefaults.defaultEncodings        = grammarp->defaultEncodings;
  marpaESLIFGrammarDefaults.fallbackEncodings       = grammarp->fallbackEncodings;

  if (marpaESLIFGrammarDefaultsp != NULL) {
    *marpaESLIFGrammarDefaultsp = marpaESLIFGrammarDefaults;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFGrammar_defaults_setb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFGrammarDefaults_t *marpaESLIFGrammarDefaultsp)
/*****************************************************************************/
{
  marpaESLIF_grammar_t        *grammarp;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    return 0;
  }

  grammarp = marpaESLIFGrammarp->grammarp;
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return marpaESLIFGrammar_defaults_by_level_setb(marpaESLIFGrammarp, marpaESLIFGrammarDefaultsp, grammarp->leveli, NULL /* descp */);
}

/*****************************************************************************/
short marpaESLIFGrammar_defaults_by_level_setb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIFGrammarDefaults_t *marpaESLIFGrammarDefaultsp, int leveli, marpaESLIFString_t *descp)
/*****************************************************************************/
{
  marpaESLIF_t         *marpaESLIFp;
  marpaESLIF_grammar_t *grammarp;
  marpaESLIF_action_t  *previousActionp;
  char                 *previousDefaultEncodings;
  char                 *previousFallbackEncodings;
  short                 rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFGrammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }
  marpaESLIFp = marpaESLIFGrammarp->marpaESLIFp;

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (marpaESLIFGrammarDefaultsp != NULL) {

    if (marpaESLIFGrammarDefaultsp->defaultRuleActionp != NULL) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, marpaESLIFGrammarDefaultsp->defaultRuleActionp))) {
        goto err;
      }
      previousActionp = grammarp->defaultRuleActionp;
      grammarp->defaultRuleActionp = _marpaESLIF_action_clonep(marpaESLIFp, marpaESLIFGrammarDefaultsp->defaultRuleActionp);
      if (MARPAESLIF_UNLIKELY(grammarp->defaultRuleActionp == NULL)) {
        grammarp->defaultRuleActionp = previousActionp;
        goto err;
      }
      _marpaESLIF_action_freev(previousActionp);
    } else {
      _marpaESLIF_action_freev(grammarp->defaultRuleActionp);
      grammarp->defaultRuleActionp = NULL;
    }

    if (marpaESLIFGrammarDefaultsp->defaultEventActionp != NULL) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, marpaESLIFGrammarDefaultsp->defaultEventActionp))) {
        goto err;
      }
      previousActionp = grammarp->defaultEventActionp;
      grammarp->defaultEventActionp = _marpaESLIF_action_clonep(marpaESLIFp, marpaESLIFGrammarDefaultsp->defaultEventActionp);
      if (MARPAESLIF_UNLIKELY(grammarp->defaultEventActionp == NULL)) {
        grammarp->defaultEventActionp = previousActionp;
        goto err;
      }
      _marpaESLIF_action_freev(previousActionp);
    } else {
      _marpaESLIF_action_freev(grammarp->defaultEventActionp);
      grammarp->defaultEventActionp = NULL;
    }

    if (marpaESLIFGrammarDefaultsp->defaultRegexActionp != NULL) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, marpaESLIFGrammarDefaultsp->defaultRegexActionp))) {
        goto err;
      }
      previousActionp = grammarp->defaultRegexActionp;
      grammarp->defaultRegexActionp = _marpaESLIF_action_clonep(marpaESLIFp, marpaESLIFGrammarDefaultsp->defaultRegexActionp);
      if (MARPAESLIF_UNLIKELY(grammarp->defaultRegexActionp == NULL)) {
        grammarp->defaultRegexActionp = previousActionp;
        goto err;
      }
      _marpaESLIF_action_freev(previousActionp);
    } else {
      _marpaESLIF_action_freev(grammarp->defaultRegexActionp);
      grammarp->defaultRegexActionp = NULL;
    }

    if (marpaESLIFGrammarDefaultsp->defaultSymbolActionp != NULL) {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIF_action_validb(marpaESLIFp, marpaESLIFGrammarDefaultsp->defaultSymbolActionp))) {
        goto err;
      }
      previousActionp = grammarp->defaultSymbolActionp;
      grammarp->defaultSymbolActionp = _marpaESLIF_action_clonep(marpaESLIFp, marpaESLIFGrammarDefaultsp->defaultSymbolActionp);
      if (MARPAESLIF_UNLIKELY(grammarp->defaultSymbolActionp == NULL)) {
        grammarp->defaultSymbolActionp = previousActionp;
        goto err;
      }
      _marpaESLIF_action_freev(previousActionp);
    } else {
      _marpaESLIF_action_freev(grammarp->defaultSymbolActionp);
      grammarp->defaultSymbolActionp = NULL;
    }

    if (marpaESLIFGrammarDefaultsp->defaultEncodings != NULL) {
      previousDefaultEncodings = grammarp->defaultEncodings;
      grammarp->defaultEncodings = strdup(marpaESLIFGrammarDefaultsp->defaultEncodings);
      if (MARPAESLIF_UNLIKELY(grammarp->defaultEncodings == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        grammarp->defaultEncodings = previousDefaultEncodings;
        goto err;
      }
      if (previousDefaultEncodings != NULL) {
        free(previousDefaultEncodings);
      }
    } else {
      if (grammarp->defaultEncodings != NULL) {
        free(grammarp->defaultEncodings);
        grammarp->defaultEncodings = NULL;
      }
    }

    if (marpaESLIFGrammarDefaultsp->fallbackEncodings != NULL) {
      previousFallbackEncodings = grammarp->fallbackEncodings;
      grammarp->fallbackEncodings = strdup(marpaESLIFGrammarDefaultsp->fallbackEncodings);
      if (MARPAESLIF_UNLIKELY(grammarp->fallbackEncodings == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
        grammarp->fallbackEncodings = previousFallbackEncodings;
        goto err;
      }
      if (previousFallbackEncodings != NULL) {
        free(previousFallbackEncodings);
      }
    } else {
      if (grammarp->fallbackEncodings != NULL) {
        free(grammarp->fallbackEncodings);
        grammarp->fallbackEncodings = NULL;
      }
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

#if MARPAESLIF_VALUEERRORPROGRESSREPORT
/*****************************************************************************/
static inline void _marpaESLIFValueErrorProgressReportv(marpaESLIFValue_t *marpaESLIFValuep)
/*****************************************************************************/
{
  static const char      *funcs = "_marpaESLIFValueErrorProgressReportv";
  marpaESLIF_t           *marpaESLIFp                = marpaESLIFValuep->marpaESLIFp;
  marpaESLIFRecognizer_t *marpaESLIFRecognizerp      = marpaESLIFValuep->marpaESLIFRecognizerp;
  int                     starti;
  int                     lengthi;

  /* If we were generating the value of the top level recognizer, modulo discard that is also at same level, log the error */
  if (! marpaESLIFRecognizerp->silentb) {
    if (marpaESLIFValue_value_startb(marpaESLIFValuep, &starti) &&
        marpaESLIFValue_value_lengthb(marpaESLIFValuep, &lengthi)) {
      marpaESLIFRecognizer_progressLogb(marpaESLIFRecognizerp,
                                        starti,
                                        /* lengthi is zero when this is a MARPA_STEP_NULLABLE_SYMBOL */
                                        (lengthi > 0) ? starti+lengthi-1 : starti,
                                        GENERICLOGGER_LOGLEVEL_ERROR);
    }
  }
}
#endif

/*****************************************************************************/
static inline marpaESLIF_symbol_t *_marpaESLIF_resolveLhsp(marpaESLIF_t *marpaESLIFp, genericStack_t *grammarStackp, marpaESLIF_grammar_t *current_grammarp, char *asciis, int parami, int lookupLevelDeltai, marpaESLIF_string_t *lookupGrammarStringp, marpaESLIF_grammar_t **grammarpp, short silentb)
/*****************************************************************************/
{
  static const char     *funcs   = "_marpaESLIF_resolveLhsp";
  marpaESLIF_symbol_t   *symbolp;
  marpaESLIF_grammar_t  *thisGrammarp;
  marpaESLIF_grammar_t  *grammarp;
  int                    grammari;

  if (MARPAESLIF_UNLIKELY((grammarStackp == NULL)
                          ||
                          (current_grammarp == NULL)
                          ||
                          (asciis == NULL))) {
    goto err;
  }
  
  grammarp = NULL;
  /* First look for the grammar */
  if (lookupGrammarStringp != NULL) {
    /* Look for such a grammar description */
    for (grammari = 0; grammari < GENERICSTACK_USED(grammarStackp); grammari++) {
      if (! GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
        /* Sparse array */
        continue;
      }
      thisGrammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
      if (_marpaESLIF_string_utf8_eqb(thisGrammarp->descp, lookupGrammarStringp)) {
        grammarp = thisGrammarp;
        break;
      }
    }
  } else {
    /* RHS level is relative - if RHS level is 0 the we fall back to current grammar */
    grammari = current_grammarp->leveli + lookupLevelDeltai;
    if ((grammari >= 0) && GENERICSTACK_IS_PTR(grammarStackp, grammari)) {
      grammarp = (marpaESLIF_grammar_t *) GENERICSTACK_GET_PTR(grammarStackp, grammari);
    }
  }

  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    goto err;
  }

  /* Then look into this grammar */
  symbolp = _marpaESLIF_symbol_findp(marpaESLIFp, grammarp, asciis, -1 /* symboli */, NULL /* symbolip */, silentb, 1 /* onlyLhsb */, 0 /* onlyRhsb */, MARPAESLIF_SYMBOL_TYPE_META);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    goto err;
  }  

  if (symbolp->parami != parami) {
    goto err;
  }

  if (grammarpp != NULL) {
    *grammarpp = grammarp;
  }
  goto done;

 err:
  symbolp = NULL;

 done:
  return symbolp;
}

/*****************************************************************************/
static inline char *_marpaESLIF_ascii2ids(marpaESLIF_t *marpaESLIFp, char *asciis)
/*****************************************************************************/
{
  /* Produces a C identifier-compatible version of ascii string */
  static const char   *funcs = "_marpaESLIF_ascii2ids";
  char                *rcs   = NULL;
  char                *p;

  if (MARPAESLIF_UNLIKELY(asciis == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "asciis is NULL");
    goto err;
  }

  rcs = strdup(asciis);
  if (MARPAESLIF_UNLIKELY(rcs == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
    goto err;
  }

  p = rcs;
  while (*p != '\0') {
    if ((*p == '_')                  ||
        ((*p >= 'a') && (*p <= 'z')) ||
        ((*p >= 'A') && (*p <= 'Z')) ||
        ((*p >= '0') && (*p <= '9'))) {
      goto next;
    }
    *p  = '_';
  next:
    ++p;
  }

  goto done;

 err:
  if (rcs != NULL) {
    free(rcs);
    rcs = NULL;
  }

 done:
  return rcs;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_stack_setb(marpaESLIFValue_t *marpaESLIFValuep, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char       *funcs                 = "_marpaESLIFValue_stack_setb";
  marpaESLIFRecognizer_t  *marpaESLIFRecognizerp = marpaESLIFValuep->marpaESLIFRecognizerp;
  short                    rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "start indicei=%d", indicei);

  /* Validate the input */
#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Validating value for destination stack indice %d", funcs, indicei);
#endif
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_value_validb(marpaESLIFRecognizerp, marpaESLIFValueResultp, NULL /* userDatavp */, NULL /* callbackp */))) {
    goto err;
  }
  
#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Setting value at stack indice %d", funcs, indicei);
#endif
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_internalStack_i_setb(marpaESLIFRecognizerp,
								       marpaESLIFValuep->valueResultStackp,
								       indicei,
								       marpaESLIFValueResultp,
								       0, /* forgetb */
								       NULL /* marpaESLIFValueResultOrigp */))) {
    goto err;
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Action %s success, valueResultStackp[%d] is of type %s", marpaESLIFValuep->actions, indicei, _marpaESLIF_value_types(marpaESLIFValueResultp->type));
  rcb = 1;
  goto done;

 err:
    rcb = 0;
 done:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
    MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
    return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_stack_switchb(marpaESLIFValue_t *marpaESLIFValuep, int i, int j)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFValue_stack_switchb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start i=%d j=%d", i, j);

  GENERICSTACK_SWITCH(marpaESLIFValuep->valueResultStackp, i, j);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValuep->valueResultStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "valueResultStackp switch between %d and %d indices failure, stack current usage is %d, %s", i, j, GENERICSTACK_USED(marpaESLIFValuep->valueResultStackp), strerror(errno));
    goto err;
  }

  rcb = 1;
  goto done;

 err:
    rcb = 0;
 done:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
    MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
    return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_stack_getb(marpaESLIFValue_t *marpaESLIFValuep, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFValue_stack_getb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start indicei=%d", indicei);

#ifndef MARPAESLIF_NTRACE
  /* Should never happen */
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_CUSTOM(marpaESLIFValuep->valueResultStackp, indicei))) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "No such indice %d in value result stack", indicei);
    goto err;
  }
#endif
  *marpaESLIFValueResultp = GENERICSTACK_GET_CUSTOM(marpaESLIFValuep->valueResultStackp, indicei);

  rcb = 1;
#ifndef MARPAESLIF_NTRACE
  /* Remove valid warnings for unused label err -; */
  goto done;

 err:
    rcb = 0;
 done:
#endif
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
    MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
    return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_stack_getAndForgetb(marpaESLIFValue_t *marpaESLIFValuep, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFValue_stack_getAndForgetb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start indicei=%d", indicei);

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_getb(marpaESLIFValuep, indicei, marpaESLIFValueResultp))) {
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_forgetb(marpaESLIFValuep, indicei))) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
    rcb = 0;
 done:
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
    MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
    return rcb;
}

/*****************************************************************************/
short marpaESLIFValue_marpaESLIFValueResult_freeb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, short deepb)
/*****************************************************************************/
{
  static const char *funcs  = "marpaESLIFValue_marpaESLIFValueResult_freeb";

  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return _marpaESLIFValue_marpaESLIFValueResult_freeb(marpaESLIFValuep, marpaESLIFValueResultp, deepb);
}

/*****************************************************************************/
short marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short deepb)
/*****************************************************************************/
{
  static const char *funcs  = "marpaESLIFRecognizer_marpaESLIFValueResult_freeb";

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizerp, marpaESLIFValueResultp, deepb);
}

/*****************************************************************************/
static inline short _marpaESLIFValue_marpaESLIFValueResult_freeb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, short deepb)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFValuep->marpaESLIFRecognizerp, marpaESLIFValueResultp, deepb);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_marpaESLIFValueResult_freeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short deepb)
/*****************************************************************************/
{
  if (deepb) {
    return _marpaESLIFRecognizer_pointers_cleanupb(marpaESLIFRecognizerp, marpaESLIFValueResultp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef);
  } else {
    _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, marpaESLIFValueResultp);
    return 1;
  }
}

/*****************************************************************************/
marpaESLIFValueResult_t *marpaESLIFValue_stack_getp(marpaESLIFValue_t *marpaESLIFValuep, int indicei)
/*****************************************************************************/
{
  static const char *funcs  = "marpaESLIFValue_stack_getp";

  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }
  if (indicei < 0) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Indice %d is negative", indicei);
    return 0;
  }

  if (! marpaESLIFValuep->inValuationb) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s must be called only in an action callback", funcs);
    return 0;
  }

  return _marpaESLIFValue_stack_getp(marpaESLIFValuep, indicei);
}

/*****************************************************************************/
static inline short _marpaESLIFValue_eslif2hostb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, void *forcedUserDatavp, marpaESLIFValueImport_t forcedImporterp)
/*****************************************************************************/
{
  return _marpaESLIF_eslif2hostb(marpaESLIFValuep->marpaESLIFp,
                                 marpaESLIFValuep,
                                 marpaESLIFValueResultp,
                                 (forcedImporterp != NULL) ? forcedUserDatavp : marpaESLIFValuep->marpaESLIFValueOption.userDatavp,
                                 (marpaESLIFGenericImport_t) ((forcedImporterp != NULL) ? forcedImporterp : marpaESLIFValuep->marpaESLIFValueOption.importerp),
				 marpaESLIFValuep->marpaESLIFRecognizerp->marpaESLIF_streamp);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_eslif2hostb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, void *forcedUserDatavp, marpaESLIFRecognizerImport_t forcedImporterp)
/*****************************************************************************/
{
  return _marpaESLIF_eslif2hostb(marpaESLIFRecognizerp->marpaESLIFp,
                                 marpaESLIFRecognizerp,
                                 marpaESLIFValueResultp,
                                 (forcedImporterp != NULL) ? forcedUserDatavp : marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp,
                                 (marpaESLIFGenericImport_t) ((forcedImporterp != NULL) ? forcedImporterp : marpaESLIFRecognizerp->marpaESLIFRecognizerOption.importerp),
				 marpaESLIFRecognizerp->marpaESLIF_streamp);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_expectedTerminalsb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *nTerminallp, int **symbolIdArraypp, marpaESLIF_symbol_t ***symbolArrayppp)
/*****************************************************************************/
/* This method requires that all pointers are set.                           */
/*****************************************************************************/
{
  static const char        *funcs = "_marpaESLIFRecognizer_expectedTerminalsb";
  marpaWrapperRecognizer_t *marpaWrapperRecognizerp;
  marpaESLIF_grammar_t     *grammarp;
  size_t                    nTerminall;
  int                      *symbolIdArrayp;
  marpaESLIF_symbol_t     **symbolArraypp;
  size_t                    symboll;
  short                     isExpectedb;
  marpaESLIF_symbol_t      *symbolp;
  short                     rcb;

  /* Ask for expected grammar terminals */
  if (! marpaESLIFRecognizerp->pristineb) {
    marpaWrapperRecognizerp = marpaESLIFRecognizerp->marpaWrapperRecognizerp;
    grammarp                = marpaESLIFRecognizerp->grammarp;
    nTerminall              = 0;
    symbolIdArrayp          = grammarp->expectedTerminalIdArrayp;
    symbolArraypp           = grammarp->expectedTerminalArraypp;

    for (symboll = 0; symboll < grammarp->nTerminall; symboll++) {
      symbolp = grammarp->symbolArraypp[symboll];
      if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_isExpectedb(marpaWrapperRecognizerp, symbolp->idi, &isExpectedb))) {
        goto err;
      }
      if (isExpectedb) {
        symbolArraypp[nTerminall] = symbolp;
        symbolIdArrayp[nTerminall] = symbolp->idi;
        nTerminall++;
      }
    }
  } else {
    nTerminall     = marpaESLIFRecognizerp->nTerminalPristinel;
    symbolIdArrayp = marpaESLIFRecognizerp->terminalIdArrayPristinep;
    symbolArraypp  = marpaESLIFRecognizerp->terminalArrayPristinepp;
  }

  /* By definition, symbol Ids and pointers are already sorted by priority */
  *nTerminallp     = nTerminall;
  *symbolIdArraypp = symbolIdArrayp;
  *symbolArrayppp  = symbolArraypp;

#ifndef MARPAESLIF_NTRACE
  for (symboll = 0; symboll < nTerminall; symboll++) {
    symbolp = symbolArraypp[symboll];
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Expected terminal: %s, priority: %d", symbolp->descp->asciis, symbolp->priorityi);
  }
#endif

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

#if defined(__GNUC__) && __GNUC__ >= 5
#  pragma GCC diagnostic push
#  pragma GCC diagnostic ignored "-Wswitch"
#endif /* __GNUC__ */

/*****************************************************************************/
static inline short _marpaESLIF_eslif2hostb(marpaESLIF_t *marpaESLIFp, void *namespacep, marpaESLIFValueResult_t *marpaESLIFValueResultp, void *userDatavp, marpaESLIFGenericImport_t importerp, marpaESLIF_stream_t *marpaESLIF_streamp)
/*****************************************************************************/
{
  static const char                *funcs                       = "_marpaESLIF_eslif2hostb";
  genericStack_t                    marpaESLIFValueResultStack;
  genericStack_t                   *marpaESLIFValueResultStackp = &(marpaESLIFValueResultStack);
  short                             haveUndefb;
  int                               lazyIndicei;
  short                             rcb;
  size_t                            i;
  marpaESLIFValueResult_t           *marpaESLIFValueResultWorkp;
  marpaESLIFValueResult_t           *marpaESLIFValueResultTmpp;
  marpaESLIFValueResultPair_t       *marpaESLIFValueResultPairp;
  marpaESLIFValueResult_t           marpaESLIFValueResultTmp;
  short                             lazyb;
  size_t                            sizel;

  if (importerp == NULL) {
    /* End user do not mind about the final value */
    rcb = 1;
    goto fast_done;
  }

  GENERICSTACK_INIT(marpaESLIFValueResultStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp initialization failure, %s", strerror(errno));
    marpaESLIFValueResultStackp = NULL;
    goto err;
  }

  GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, marpaESLIFValueResultp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
    goto err;
  }

  while (GENERICSTACK_USED(marpaESLIFValueResultStackp) > 0) {
    marpaESLIFValueResultWorkp = (marpaESLIFValueResult_t *) GENERICSTACK_POP_PTR(marpaESLIFValueResultStackp);

    switch (marpaESLIFValueResultWorkp->type) {
    case MARPAESLIF_VALUE_TYPE_LAZY_NOUNDEF:
      haveUndefb = 0;
      /* Next item is a marpaESLIFValueResult that got lazy'ed */
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_USED(marpaESLIFValueResultStackp) <= 0)) {
        MARPAESLIF_ERROR(marpaESLIFp, "Internal error: lazy marker but nothing else in the work stack");
        errno = ENOENT;
        goto err;
      }
      marpaESLIFValueResultWorkp = (marpaESLIFValueResult_t *) GENERICSTACK_POP_PTR(marpaESLIFValueResultStackp);
      lazyb = 1;
      break;
    case MARPAESLIF_VALUE_TYPE_LAZY_WITHUNDEF:
      haveUndefb = 1;
      /* Next item is a marpaESLIFValueResult that got lazy'ed */
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_USED(marpaESLIFValueResultStackp) <= 0)) {
        MARPAESLIF_ERROR(marpaESLIFp, "Internal error: lazy marker but nothing else in the work stack");
        errno = ENOENT;
        goto err;
      }
      marpaESLIFValueResultWorkp = (marpaESLIFValueResult_t *) GENERICSTACK_POP_PTR(marpaESLIFValueResultStackp);
      lazyb = 1;
      break;
    default:
      lazyb = 0;
      break;
    }

    switch (marpaESLIFValueResultWorkp->type) {
    case MARPAESLIF_VALUE_TYPE_UNDEF:
      if (MARPAESLIF_UNLIKELY(! importerp(namespacep, userDatavp, marpaESLIFValueResultWorkp, 1 /* haveUndefb */))) {
        goto err;
      }
      break;
    case MARPAESLIF_VALUE_TYPE_CHAR:
    case MARPAESLIF_VALUE_TYPE_SHORT:
    case MARPAESLIF_VALUE_TYPE_INT:
    case MARPAESLIF_VALUE_TYPE_LONG:
    case MARPAESLIF_VALUE_TYPE_FLOAT:
    case MARPAESLIF_VALUE_TYPE_DOUBLE:
    case MARPAESLIF_VALUE_TYPE_PTR:
    case MARPAESLIF_VALUE_TYPE_BOOL:
    case MARPAESLIF_VALUE_TYPE_STRING:
    case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:
#ifdef MARPAESLIF_HAVE_LONG_LONG
    case MARPAESLIF_VALUE_TYPE_LONG_LONG:
#endif
    case MARPAESLIF_VALUE_TYPE_ARRAY:
      if (MARPAESLIF_UNLIKELY(! importerp(namespacep, userDatavp, marpaESLIFValueResultWorkp, 0 /* haveUndefb */))) {
        goto err;
      }
      break;
    case MARPAESLIF_VALUE_TYPE_OFFSET_AND_LENGTH:
      /* Like an array, but with an offset */
      marpaESLIFValueResultTmp.contextp           = NULL;
      marpaESLIFValueResultTmp.representationp    = NULL;
      marpaESLIFValueResultTmp.type               = MARPAESLIF_VALUE_TYPE_ARRAY;
      marpaESLIFValueResultTmp.u.a.p              = marpaESLIF_streamp->buffers + marpaESLIFValueResultWorkp->u.o.p;
      marpaESLIFValueResultTmp.u.a.shallowb       = 1;
      marpaESLIFValueResultTmp.u.a.freeUserDatavp = NULL;
      marpaESLIFValueResultTmp.u.a.freeCallbackp  = NULL;
      marpaESLIFValueResultTmp.u.a.sizel          = marpaESLIFValueResultWorkp->u.o.sizel;
      if (MARPAESLIF_UNLIKELY(! importerp(namespacep, userDatavp, &marpaESLIFValueResultTmp, 0 /* haveUndefb */))) {
        goto err;
      }
      break;
    case MARPAESLIF_VALUE_TYPE_ROW:
      if (lazyb) {
        /* haveUndefb was set when testing previous marpaESLIFValueResultWorkp->type */
        if (MARPAESLIF_UNLIKELY(! importerp(namespacep, userDatavp, marpaESLIFValueResultWorkp, haveUndefb))) {
          goto err;
        }
      } else {
        /* Push again current element */
        GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, marpaESLIFValueResultWorkp);
        if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
          goto err;
        }

        /* We assume that most common case: there is no undef */
        haveUndefb = 0;
        GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, &marpaESLIFValueResultLazyNoUndef);
        if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
          goto err;
        }

        /* But if are wrong, remember the lazy indice to change that */
        lazyIndicei = GENERICSTACK_USED(marpaESLIFValueResultStackp) - 1;

        /* Push inner elements in reverse order i.e. 3, 2, 1 so that inner elements are imported in order, i.e. 1, 2, 3 */
        if ((sizel = marpaESLIFValueResultWorkp->u.r.sizel) > 0) {
          for (i = 0, marpaESLIFValueResultTmpp = &(marpaESLIFValueResultWorkp->u.r.p[sizel - 1]);
               i < sizel;
               i++, marpaESLIFValueResultTmpp--) {
            if (! haveUndefb) {
              if (marpaESLIFValueResultTmpp->type == MARPAESLIF_VALUE_TYPE_UNDEF) {
                haveUndefb = 1;
              }
            }
            GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, marpaESLIFValueResultTmpp);
            if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
              MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
              goto err;
            }
          }
        }

        /* Finally, there is an undef value in the ROW */
        if (haveUndefb) {
          GENERICSTACK_SET_PTR(marpaESLIFValueResultStackp, &marpaESLIFValueResultLazyWithUndef, lazyIndicei);
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp set failure, %s", strerror(errno));
            goto err;
          }
        }
      }
      break;
    case MARPAESLIF_VALUE_TYPE_TABLE:
      if (lazyb) {
        /* haveUndefb was set when testing previous marpaESLIFValueResultWorkp->type */
        if (MARPAESLIF_UNLIKELY(! importerp(namespacep, userDatavp, marpaESLIFValueResultWorkp, haveUndefb))) {
          goto err;
        }
      } else {
        /* Push again current element */
        GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, marpaESLIFValueResultWorkp);
        if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
          goto err;
        }

        /* We assume that most common case: there is no undef */
        haveUndefb = 0;
        GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, &marpaESLIFValueResultLazyNoUndef);
        if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
          MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
          goto err;
        }

        /* But if are wrong, remember the lazy indice to change that */
        lazyIndicei = GENERICSTACK_USED(marpaESLIFValueResultStackp) - 1;

        /* We push valn, keyn, ...., val0, key0, so that importer is called in this order: */
        /* key0, val0, ..., keyn, valn */
        if ((sizel = marpaESLIFValueResultWorkp->u.t.sizel) > 0) {
          for (i = 0, marpaESLIFValueResultPairp = &(marpaESLIFValueResultWorkp->u.t.p[sizel - 1]);
               i < sizel;
               i++, marpaESLIFValueResultPairp--) {
            if (! haveUndefb) {
              if (marpaESLIFValueResultPairp->value.type == MARPAESLIF_VALUE_TYPE_UNDEF) {
                haveUndefb = 1;
              }
            }
            GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, &(marpaESLIFValueResultPairp->value));
            if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
              MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
              goto err;
            }
            if (! haveUndefb) {
              if (marpaESLIFValueResultPairp->key.type == MARPAESLIF_VALUE_TYPE_UNDEF) {
                haveUndefb = 1;
              }
            }
            GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, &(marpaESLIFValueResultPairp->key));
            if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
              MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
              goto err;
            }
          }
        }

        /* Finally, there is an undef value in the TABLE */
        if (haveUndefb) {
          GENERICSTACK_SET_PTR(marpaESLIFValueResultStackp, &marpaESLIFValueResultLazyWithUndef, lazyIndicei);
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFp, "marpaESLIFValueResultStackp set failure, %s", strerror(errno));
            goto err;
          }
        }
      }
      break;
    default:
      MARPAESLIF_ERRORF(marpaESLIFp, "Unsupported marpaESLIFValueResult type %d", marpaESLIFValueResultWorkp->type);
      errno = ENOSYS;
      goto err;
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  GENERICSTACK_RESET(marpaESLIFValueResultStackp);

 fast_done:
  return rcb;
}

#if defined(__GNUC__) && __GNUC__ >= 5
#  pragma GCC diagnostic pop
#endif /* __GNUC__ */

/*****************************************************************************/
short marpaESLIFValue_importb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFValue_importb";

  /* Generic importation helper of a marpaESLIFValueResult during valuation */
  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return _marpaESLIFValue_importb(marpaESLIFValuep, marpaESLIFValueResultp);
}

/*****************************************************************************/
short marpaESLIFRecognizer_importb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_importb";
  short              rcb;

  /* Generic importation helper of a marpaESLIFValueResult during recognition */
  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_importb(marpaESLIFRecognizerp, marpaESLIFValueResultp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIF_numberb(marpaESLIF_t *marpaESLIFp, char *s, size_t sizel, marpaESLIFValueResult_t *marpaESLIFValueResultp, short *confidencebp)
/*****************************************************************************/
{
  if ((marpaESLIFp == NULL) || (s == NULL)) {
    errno = EINVAL;
    return 0;
  }

  return _marpaESLIF_numberb(marpaESLIFp, s, sizel, marpaESLIFValueResultp, confidencebp);
}

/*****************************************************************************/
static inline marpaESLIFValueResult_t *_marpaESLIFValue_stack_getp(marpaESLIFValue_t *marpaESLIFValuep, int indicei)
/*****************************************************************************/
{
  /* Special internal version of _marpaESLIFValue_stack_getp that returns the direct pointer into the stack */
  static const char       *funcs = "_marpaESLIFValue_stack_getp";
  marpaESLIFValueResult_t *marpaESLIFValueResultp;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start indicei=%d", indicei);

#ifndef MARPAESLIF_NTRACE
  /* Should never happen */
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_CUSTOM(marpaESLIFValuep->valueResultStackp, indicei))) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "No such indice %d in value result stack", indicei);
    goto err;
  }
#endif
  marpaESLIFValueResultp = GENERICSTACK_GET_CUSTOMP(marpaESLIFValuep->valueResultStackp, indicei);

#ifndef MARPAESLIF_NTRACE
  /* Remove valid warnings for unused label err -; */
  goto done;

 err:
  marpaESLIFValueResultp = NULL;

 done:
#endif
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %p", marpaESLIFValueResultp);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return marpaESLIFValueResultp;
}

/*****************************************************************************/
short marpaESLIFValue_stack_forgetb(marpaESLIFValue_t *marpaESLIFValuep, int indicei)
/*****************************************************************************/
{
  static const char *funcs  = "marpaESLIFValue_stack_forgetb";

  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }
  if (indicei < 0) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Indice %d is negative", indicei);
    return 0;
  }

  if (! marpaESLIFValuep->inValuationb) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s must be called only in an action callback", funcs);
    return 0;
  }

  return _marpaESLIFValue_stack_forgetb(marpaESLIFValuep, indicei);
}

/*****************************************************************************/
static inline short _marpaESLIFValue_stack_forgetb(marpaESLIFValue_t *marpaESLIFValuep, int indicei)
/*****************************************************************************/
{
  static const char       *funcs = "_marpaESLIFValue_stack_forgetb";
  short                    rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_internalStack_i_setb(marpaESLIFValuep->marpaESLIFRecognizerp,
								       marpaESLIFValuep->valueResultStackp,
								       indicei,
								       (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef,
								       1, /* forgetb */
								       NULL /* marpaESLIFValueResultOrigp */))) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;
 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_internalStack_i_setb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, genericStack_t *valueResultStackp, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp, short forgetb, marpaESLIFValueResult_t *marpaESLIFValueResultOrigp)
/*****************************************************************************/
/* If marpaESLIFValueResultOrigp is NULL, then valueResultStackp and indicei must be set */
/* If marpaESLIFValueResultOrigp is not NULL, then valueResultStackp and indicei are not used and can be invalid values */
/* marpaESLIFValueResultp must always be set */
{
  static const char      *funcs    = "_marpaESLIFRecognizer_internalStack_i_setb";
  short                   rcb;
  genericStackItemType_t  itemType;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (marpaESLIFValueResultOrigp == NULL) {
    /* Look at original value */
    /* ---------------------- */
    if (indicei >= GENERICSTACK_USED(valueResultStackp)) {
      /* Replacement on something that does not yet exist - this is not illegal, we do the replacement immediately */
      GENERICSTACK_SET_CUSTOMP(valueResultStackp, marpaESLIFValueResultp, indicei);
#ifndef MARPAESLIF_NTRACE
      MARPAESLIFRECOGNIZER_MARPAESLIFVALUE_TRACE(funcs, marpaESLIFRecognizerp, NULL /* symbolp */, indicei, marpaESLIFValueResultp);
#endif
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(valueResultStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "valueResultStackp set failure at indice %d, %s", indicei, strerror(errno));
        goto err;
      } else {
        rcb = 1;
        goto done;
      }
    } else {
      itemType = GENERICSTACKITEMTYPE(valueResultStackp, indicei);
      if (itemType != GENERICSTACKITEMTYPE_CUSTOM) {
        /* Then it is must be NA */
        if (MARPAESLIF_LIKELY(itemType == GENERICSTACKITEMTYPE_NA)) {
          /* Replacement on something that is NA - this is also not illegal, we do the replacement immediately */
          GENERICSTACK_SET_CUSTOMP(valueResultStackp, marpaESLIFValueResultp, indicei);
#ifndef MARPAESLIF_NTRACE
          MARPAESLIFRECOGNIZER_MARPAESLIFVALUE_TRACE(funcs, marpaESLIFRecognizerp, NULL /* symbolp */, indicei, marpaESLIFValueResultp);
#endif
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(valueResultStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "valueResultStackp set failure at indice %d, %s", indicei, strerror(errno));
            goto err;
          } else {
            rcb = 1;
            goto done;
          }
        } else {
          /* At indicei, this must be a CUSTOM or a NA value */
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "valueResultStackp at indice %d is not CUSTOM nor NA (got %s, value %d)", indicei, _marpaESLIF_genericStack_i_types(valueResultStackp, indicei), GENERICSTACKITEMTYPE(valueResultStackp, indicei));
          goto err;
        }
      }
    }

    /* Get original value */
    /* ------------------ */
    marpaESLIFValueResultOrigp = GENERICSTACK_GET_CUSTOMP(valueResultStackp, indicei);
#ifndef MARPAESLIF_NTRACE /* We made sure indicei is a valid indice - this cannot fail unless memory corruption */
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(valueResultStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "GENERICSTACK_GET_CUSTOMP on valueResultStackp failure, %s", strerror(errno));
      goto err;
    }
#endif
  }

  /* -------------------------------------------------------------------------------------------------- */
  /* Here it is guaranteed that both marpaESLIFValueResultOrigp and marpaESLIFValueResultp are not NULL */
  /* -------------------------------------------------------------------------------------------------- */
#ifndef MARPAESLIF_NTRACE
  MARPAESLIFRECOGNIZER_MARPAESLIFVALUE_TRACE(funcs, marpaESLIFRecognizerp, NULL /* symbolp */, indicei, marpaESLIFValueResultp);
#endif

  /* Free origin unless we are told to forget about it */
  if (! forgetb) {
    if (! _marpaESLIFRecognizer_pointers_cleanupb(marpaESLIFRecognizerp, marpaESLIFValueResultOrigp, marpaESLIFValueResultp)) {
      goto err;
    }
  }

  /* Do the replacement */
  *marpaESLIFValueResultOrigp = *marpaESLIFValueResultp;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFValue_contextb(marpaESLIFValue_t *marpaESLIFValuep, char **symbolsp, int *symbolip, char **rulesp, int *ruleip)
/*****************************************************************************/
{
  static const char *funcs  = "marpaESLIFValue_contextb";
  short              rcb;
  char              *symbols;
  int                symboli;
  char              *rules;
  int                rulei;

  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(! marpaESLIFValuep->inValuationb)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s must be called only in an action callback", funcs);
    goto err;
  }

  if (marpaESLIFValuep->symbolp != NULL) {
    symbols = marpaESLIFValuep->symbolp->descp->asciis;
    symboli = marpaESLIFValuep->symbolp->idi;
    rules = NULL;
    rulei = -1;
  } else if (MARPAESLIF_LIKELY(marpaESLIFValuep->rulep != NULL)) {
    symbols = NULL;
    symboli = -1;
    rules   = marpaESLIFValuep->rulep->descp->asciis;
    rulei   = marpaESLIFValuep->rulep->idi;
  } else {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s found no symbol nor rule in current context", funcs);
    goto err;
  }

  if (symbolsp != NULL) {
    *symbolsp = symbols;
  }
  if (symbolip != NULL) {
    *symbolip = symboli;
  }
  if (rulesp != NULL) {
    *rulesp = rules;
  }
  if (ruleip != NULL) {
    *ruleip = rulei;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIF_generic_literal_transferb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIF_string_t *stringp, int resulti)
/*****************************************************************************/
/* We are transfering a string that is in the grammar. So no allocatation.   */
/*****************************************************************************/
{
  static const char       *funcs = "_marpaESLIF_generic_literal_transferb";
  marpaESLIFValueResult_t  marpaESLIFValueResult;

  marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_STRING;
  marpaESLIFValueResult.contextp           = NULL;
  marpaESLIFValueResult.representationp    = NULL;
  marpaESLIFValueResult.u.s.p              = (unsigned char *) stringp->bytep;
  marpaESLIFValueResult.u.s.shallowb       = 1;
  marpaESLIFValueResult.u.s.sizel          = stringp->bytel;
  marpaESLIFValueResult.u.s.freeUserDatavp = NULL;
  marpaESLIFValueResult.u.s.freeCallbackp  = NULL;
  marpaESLIFValueResult.u.s.encodingasciis = stringp->encodingasciis;
  
  return _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &marpaESLIFValueResult);
}

/*****************************************************************************/
static short _marpaESLIF_symbol_literal_transferb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultNotUsedp, int resulti)
/*****************************************************************************/
{
  return _marpaESLIF_generic_literal_transferb(marpaESLIFValuep, marpaESLIFValuep->stringp, resulti);
}

/*****************************************************************************/
static short _marpaESLIF_rule_literal_transferb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  return _marpaESLIF_generic_literal_transferb(marpaESLIFValuep, marpaESLIFValuep->stringp, resulti);
}

/*****************************************************************************/
static void _marpaESLIF_generic_freeCallbackv(void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  _marpaESLIF_generic_freeCallback_inlinev(userDatavp, marpaESLIFValueResultp);
}

/*****************************************************************************/
static inline void _marpaESLIF_generic_freeCallback_inlinev(void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char   *funcs       = "_marpaESLIF_generic_freeCallback_inlinev";
  marpaESLIF_t        *marpaESLIFp = (marpaESLIF_t *) userDatavp;
  marpaESLIF_string_t  string;

  switch (marpaESLIFValueResultp->type) {
  case MARPAESLIF_VALUE_TYPE_PTR:
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Freeing PTR {%p}", marpaESLIFValueResultp->u.p.p);
    /* This should never happen, but who knows */
    if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.p.shallowb)) {
      MARPAESLIF_WARNF(marpaESLIFp, "Free callback on shallow pointer %p", marpaESLIFValueResultp->u.p.p);
    } else if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.p.p == NULL)) {
      MARPAESLIF_WARN(marpaESLIFp, "Free callback on NULL pointer");
    } else {
      free(marpaESLIFValueResultp->u.p.p);
    }
    break;
  case MARPAESLIF_VALUE_TYPE_ARRAY:
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Freeing ARRAY {%p,%ld}", marpaESLIFValueResultp->u.a.p, (unsigned long) marpaESLIFValueResultp->u.a.sizel);
    /* This should never happen, but who knows */
    if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.a.shallowb)) {
      MARPAESLIF_WARNF(marpaESLIFp, "Free callback on shallow array {%p,%ld}", marpaESLIFValueResultp->u.a.p, (unsigned long) marpaESLIFValueResultp->u.a.sizel);
    } else if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.a.p == NULL)) {
      MARPAESLIF_WARN(marpaESLIFp, "Free callback on NULL array");
    } else {
      free(marpaESLIFValueResultp->u.a.p);
    }
    break;
  case MARPAESLIF_VALUE_TYPE_STRING:
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Freeing STRING {%p,%ld,encoding=%s}", marpaESLIFValueResultp->u.s.p, (unsigned long) marpaESLIFValueResultp->u.s.sizel, marpaESLIFValueResultp->u.s.encodingasciis != NULL ? marpaESLIFValueResultp->u.s.encodingasciis : "(null)");
    /* This should never happen, but who knows */
    if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.s.shallowb)) {
      MARPAESLIF_WARN(marpaESLIFp, "Free callback on shallow string");
    } else if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.s.p == NULL)) {
      MARPAESLIF_WARN(marpaESLIFp, "Free callback on NULL string");
    } else {
      string.bytep          = (char *) marpaESLIFValueResultp->u.s.p;
      string.bytel          = marpaESLIFValueResultp->u.s.sizel;
      string.encodingasciis = marpaESLIFValueResultp->u.s.encodingasciis;
      string.asciis         = NULL;
      _marpaESLIF_string_freev(&string, 1 /* onStackb */);
    }
    break;
  case MARPAESLIF_VALUE_TYPE_ROW:
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Freeing ROW {%p,%ld}", marpaESLIFValueResultp->u.r.p, (unsigned long) marpaESLIFValueResultp->u.r.sizel);
    /* This should never happen, but who knows */
    if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.r.shallowb)) {
      MARPAESLIF_WARNF(marpaESLIFp, "Free callback on shallow row {%p,%ld}", marpaESLIFValueResultp->u.r.p, (unsigned long) marpaESLIFValueResultp->u.r.sizel);
    } else if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.r.p == NULL)) {
      MARPAESLIF_WARN(marpaESLIFp, "Free callback on NULL row");
    } else {
      free(marpaESLIFValueResultp->u.r.p);
    }
    break;
  case MARPAESLIF_VALUE_TYPE_TABLE:
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Freeing TABLE {%p,%ld}", marpaESLIFValueResultp->u.t.p, (unsigned long) marpaESLIFValueResultp->u.t.sizel);
    /* This should never happen, but who knows */
    if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.t.shallowb)) {
      MARPAESLIF_WARNF(marpaESLIFp, "Free callback on shallow table {%p,%ld}", marpaESLIFValueResultp->u.t.p, (unsigned long) marpaESLIFValueResultp->u.t.sizel);
    } else if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->u.t.p == NULL)) {
      MARPAESLIF_WARN(marpaESLIFp, "Free callback on NULL table");
    } else {
      free(marpaESLIFValueResultp->u.t.p);
    }
    break;
  default:
    MARPAESLIF_TRACEF(marpaESLIFp, funcs, "Skipping type %d %s", marpaESLIFValueResultp->type, _marpaESLIF_value_types(marpaESLIFValueResultp->type));
    break;
  }
}

/*****************************************************************************/
static inline marpaESLIFValue_t *_marpaESLIFValue_newp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueOption_t *marpaESLIFValueOptionp, short silentb, short fakeb, short isLexemeb)
/*****************************************************************************/
{
  static const char        *funcs                 = "marpaESLIFValue_newp";
  marpaESLIF_t             *marpaESLIFp           = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIFValue_t        *marpaESLIFValuep      = NULL;
  marpaWrapperValue_t      *marpaWrapperValuep    = NULL;
  marpaWrapperValueOption_t marpaWrapperValueOption;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* MARPAESLIF_TRACE(marpaESLIFp, funcs, "Building Value"); */

  if (MARPAESLIF_UNLIKELY(marpaESLIFValueOptionp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Value option structure must not be NULL");
    goto err;
  }

  marpaESLIFValuep = (marpaESLIFValue_t *) malloc(sizeof(marpaESLIFValue_t));
  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  marpaESLIFValuep->marpaESLIFp                           = marpaESLIFp;
  marpaESLIFValuep->Lsharep                               = marpaESLIFRecognizerp->Lsharep; /* At this stage it is not possible that marpaESLIFRecognizerp is NULL, neither Lsharep */
  marpaESLIFValuep->marpaESLIFRecognizerp                 = marpaESLIFRecognizerp;
  marpaESLIFValuep->marpaESLIFValueOption                 = *marpaESLIFValueOptionp;
  marpaESLIFValuep->marpaWrapperValuep                    = NULL;
  marpaESLIFValuep->valueResultStackp                     = NULL;
  marpaESLIFValuep->inValuationb                          = 0;
  marpaESLIFValuep->symbolp                               = NULL;
  marpaESLIFValuep->rulep                                 = NULL;
  marpaESLIFValuep->actions                               = NULL;
  marpaESLIFValuep->actionp                               = NULL;
  marpaESLIFValuep->stringp                               = NULL;
  marpaESLIFValuep->marpaESLIFLuaValueContextp            = NULL; /* Shallow pointer */
  marpaESLIFValuep->proxyRepresentationp                  = NULL;
  _marpaESLIF_stringGeneratorInitv(marpaESLIFp, &(marpaESLIFValuep->stringGenerator));
  marpaESLIFValuep->stringGeneratorLoggerp                = NULL;
  marpaESLIFValuep->luaprecompiledp                       = NULL;
  marpaESLIFValuep->luaprecompiledl                       = 0;
  marpaESLIFValuep->hideSeparatorb                        = 0;
  marpaESLIFValuep->isLexemeb                             = isLexemeb;

  if (! fakeb) {
    marpaWrapperValueOption.genericLoggerp = silentb ? marpaESLIFp->traceLoggerp : marpaESLIFp->marpaESLIFOption.genericLoggerp;
    marpaWrapperValueOption.highRankOnlyb  = marpaESLIFValueOptionp->highRankOnlyb;
    marpaWrapperValueOption.orderByRankb   = marpaESLIFValueOptionp->orderByRankb;
    marpaWrapperValueOption.ambiguousb     = marpaESLIFValueOptionp->ambiguousb;
    marpaWrapperValueOption.nullb          = marpaESLIFValueOptionp->nullb;
    marpaWrapperValueOption.maxParsesi     = marpaESLIFValueOptionp->maxParsesi;
    marpaWrapperValuep = marpaWrapperValue_newp(marpaESLIFRecognizerp->marpaWrapperRecognizerp, &marpaWrapperValueOption);
    if (MARPAESLIF_UNLIKELY(marpaWrapperValuep == NULL)) {
      goto err;
    }
    marpaESLIFValuep->marpaWrapperValuep = marpaWrapperValuep;

    /* The string generator is only used in non-fake mode */
    marpaESLIFValuep->stringGeneratorLoggerp = GENERICLOGGER_CUSTOM(_marpaESLIF_generateStringWithLoggerCallback, &(marpaESLIFValuep->stringGenerator), GENERICLOGGER_LOGLEVEL_TRACE);
    if (MARPAESLIF_UNLIKELY(marpaESLIFValuep->stringGeneratorLoggerp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "GENERICLOGGER_CUSTOM() initialization failure, %s", strerror(errno));
      goto err;
    }
  }

  goto done;

 err:
  marpaESLIFValue_freev(marpaESLIFValuep);
  marpaESLIFValuep = NULL;

 done:
  /* MARPAESLIF_TRACEF(marpaESLIFp, funcs, "return %p", marpaESLIFValuep); */
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %p", marpaESLIFValuep);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return marpaESLIFValuep;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_stack_newb(marpaESLIFValue_t *marpaESLIFValuep)
/*****************************************************************************/
{
  short rcb;

  /* Initialize the stacks */
  if (marpaESLIFValuep->valueResultStackp == NULL) {
    marpaESLIFValuep->valueResultStackp = &(marpaESLIFValuep->_valueResultStack);
    GENERICSTACK_INIT(marpaESLIFValuep->valueResultStackp);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValuep->valueResultStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "valueResultStackp initialization failure, %s", strerror(errno));
      marpaESLIFValuep->valueResultStackp = NULL;
      goto err;
    }
  }

  rcb = 1;
  goto done;
 err:
  rcb = 0;
 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_stack_freeb(marpaESLIFValue_t *marpaESLIFValuep)
/*****************************************************************************/
{
  static const char      *funcs  = "_marpaESLIFValue_stack_freeb";
  short                   rcb;
  int                     i;
  marpaESLIFRecognizer_t *marpaESLIFRecognizerp;
  genericStack_t         *valueResultStackp;
  int                     usedi;

  if (marpaESLIFValuep != NULL) {
    /* Free the stacks */
    valueResultStackp = marpaESLIFValuep->valueResultStackp;
    if (valueResultStackp != NULL) {

      marpaESLIFRecognizerp = marpaESLIFValuep->marpaESLIFRecognizerp;
      usedi                 = GENERICSTACK_USED(valueResultStackp);

#ifdef MARPAESLIF_NOTICE_ACTION
      MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Freeing value stack", funcs);
#endif
      for (i = 0; i < usedi; i++) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_internalStack_i_setb(marpaESLIFRecognizerp,
									     valueResultStackp,
									     i,
									     (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef,
									     0, /* forgetb */
									     NULL /* marpaESLIFValueResultOrigp */))) {
          goto err;
        }
      }
      GENERICSTACK_RESET(valueResultStackp);
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFValue_stack_setb(marpaESLIFValue_t *marpaESLIFValuep, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char *funcs  = "marpaESLIFValue_stack_setb";

  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(indicei < 0)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Indice %d is negative", indicei);
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFValuep->marpaESLIFp, "marpaESLIFValueResultp is NULL");
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp->contextp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s must be called with a context != NULL", funcs);
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(! marpaESLIFValuep->inValuationb)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s must be called only in an action callback", funcs);
    return 0;
  }

  return _marpaESLIFValue_stack_setb(marpaESLIFValuep, indicei, marpaESLIFValueResultp);
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___shiftb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIF_rule_action___shiftb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  /* ::shift is nothing else but an alias for ::copy[0] */
  rcb = _marpaESLIF_generic_action_copyb(userDatavp, marpaESLIFValuep, arg0i, argni, arg0i, resulti, nullableb);

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIFRecognizer_concat_valueResultCallbackb(void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char                      *funcs                       = "_marpaESLIFRecognizer_concat_valueResultCallbackb";
  marpaESLIF_concat_valueResultContext_t *contextp                    = (marpaESLIF_concat_valueResultContext_t *) userDatavp;
  marpaESLIFValue_t                      *marpaESLIFValuep            = contextp->marpaESLIFValuep;
  marpaESLIF_t                           *marpaESLIFp                 = marpaESLIFValuep->marpaESLIFp;
  marpaESLIF_stringGenerator_t           *marpaESLIF_stringGeneratorp = &(marpaESLIFValuep->stringGenerator);
  char                                    decimalPointc               = marpaESLIFp->decimalPointc;
  marpaESLIF_string_t                    *utf8p                       = NULL;
  genericLogger_t                        *genericLoggerp              = marpaESLIFValuep->stringGeneratorLoggerp;
  short                                   displayNextAsJsonStringb    = 0;
  char                                   *encodingasciitofrees        = NULL;
  short                                   jsonb                       = contextp->jsonb || contextp->jsonfb; /* Note that jsonb implies UTF-8's stringb by construction */
  marpaESLIFRepresentationDispose_t       disposeCallbackp            = NULL;
  short                                   disposeCallbackb            = 0; /* To know if we have to call disposer */
  short                                   stringb;
  char                                   *srcs;
  size_t                                  srcl;
  genericStack_t                          todoStack;
  genericStack_t                         *todoStackp = &(todoStack);
  marpaESLIF_string_t                     string;
  marpaESLIFRepresentation_t              representationp;
  void                                   *representationUserDatavp;
  short                                   rcb;
  size_t                                  i;
  size_t                                  j;
  marpaESLIFValueResult_t                 _marpaESLIFValueResultRepresentation;
  marpaESLIF_uint32_t                     codepointi;
  char                                   *p;
  char                                   *maxp;
  int                                     lengthi;
  char                                   *encodingasciis;
  marpaESLIFValueResult_t                *marpaESLIFValueResultTmpp;
  marpaESLIFValueResultPair_t            *marpaESLIFValueResultPairp;
  short                                   isTrueStringb;
  size_t                                  sizel;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  GENERICSTACK_INIT(todoStackp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp initialization failure, %s", strerror(errno));
    todoStackp = NULL;
    goto err;
  }

  /* Start with an empty string */
  VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "");

  /* Initialize the worklist */
  GENERICSTACK_PUSH_PTR(todoStackp, marpaESLIFValueResultp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
    goto err;
  }

  /* Iterate the worklist */
  while (GENERICSTACK_USED(todoStackp) > 0) {
    marpaESLIFValueResultp = GENERICSTACK_POP_PTR(todoStackp);

    /* Internal marker ? */
    if (marpaESLIFValueResultp->contextp == &_marpaESLIFValueResultNextValueResultMustDisplayAsJsonString) {
      MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "Setting displayNextAsJsonStringb=1");
      displayNextAsJsonStringb = 1;
      continue;
    }

    if ((marpaESLIFValueResultp->type == MARPAESLIF_VALUE_TYPE_PTR) && (marpaESLIFValueResultp->contextp == (void *) MARPAESLIF_EMBEDDED_CONTEXT_LUA)) {
      /* Specific to lua embedded: we use our proxy, then userDatavp is forced to be marpaESLIFValuep */
      representationp = _marpaESLIF_lua_value_representationb;
      representationUserDatavp = marpaESLIFValuep;
    } else {
      /* Origin representation, userDatavp is the one from original context */
      representationp = marpaESLIFValueResultp->representationp;
      representationUserDatavp = contextp->userDatavp;
      /* Representation may be proxied - c.f. json.c */
      if ((representationp != NULL) && (marpaESLIFValuep->proxyRepresentationp != NULL)) {
        representationp = marpaESLIFValuep->proxyRepresentationp;
      }
    }

    /* stringb is the default coming from the context */
    stringb = contextp->stringb;

    /* User representation is used, if any. Then finally the marpaESLIFValueResult is either STRING or ARRAY */
    if (representationp != NULL) {
      srcs = NULL;
      srcl = 0;
      encodingasciis = NULL;
      if (disposeCallbackb) {
	if (disposeCallbackp != NULL) {
	  disposeCallbackp(representationUserDatavp, srcs, srcl, encodingasciis);
	  disposeCallbackp = NULL;
	}
	disposeCallbackb = 0;
      }
      isTrueStringb = 1; /* Default value is always the safe value: caller's representation is truely a string */
      if (MARPAESLIF_UNLIKELY(! representationp(representationUserDatavp, marpaESLIFValueResultp, &srcs, &srcl, &encodingasciis, &disposeCallbackp, &isTrueStringb))) {
        goto err;
      }
      disposeCallbackb = (disposeCallbackp != NULL) ? 1 : 0;
      if ((srcs != NULL) && (srcl > 0)) {
        if (encodingasciis != NULL) {
          MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "Got user string representation");
          _marpaESLIFValueResultRepresentation.type               = MARPAESLIF_VALUE_TYPE_STRING;
          _marpaESLIFValueResultRepresentation.contextp           = NULL;
          _marpaESLIFValueResultRepresentation.representationp    = NULL;
          _marpaESLIFValueResultRepresentation.u.s.p              = (unsigned char *) srcs;
          _marpaESLIFValueResultRepresentation.u.s.shallowb       = 1;
          _marpaESLIFValueResultRepresentation.u.s.sizel          = srcl;
          _marpaESLIFValueResultRepresentation.u.s.encodingasciis = encodingasciis;
          _marpaESLIFValueResultRepresentation.u.s.freeUserDatavp = NULL;
          _marpaESLIFValueResultRepresentation.u.s.freeCallbackp  = NULL;
        } else {
          MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "Got user array representation");
          _marpaESLIFValueResultRepresentation.type               = MARPAESLIF_VALUE_TYPE_ARRAY;
          _marpaESLIFValueResultRepresentation.contextp           = NULL;
          _marpaESLIFValueResultRepresentation.representationp    = NULL;
          _marpaESLIFValueResultRepresentation.u.a.p              = srcs;
          _marpaESLIFValueResultRepresentation.u.a.shallowb       = 1;
          _marpaESLIFValueResultRepresentation.u.a.sizel          = srcl;
          _marpaESLIFValueResultRepresentation.u.a.freeUserDatavp = NULL;
          _marpaESLIFValueResultRepresentation.u.a.freeCallbackp  = NULL;
        }

        /* We take into account isTrueStringb only when the original is opaque, i.e. PTR */
        if (marpaESLIFValueResultp->type == MARPAESLIF_VALUE_TYPE_PTR) {
          stringb = isTrueStringb;
        }
        marpaESLIFValueResultp = &_marpaESLIFValueResultRepresentation;
      }
    }

    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "displayNextAsJsonStringb=%d", (int) displayNextAsJsonStringb);
    switch (marpaESLIFValueResultp->type) {
    case MARPAESLIF_VALUE_TYPE_UNDEF:
      MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "UNDEF");
      /* Undef default representation:
         - string      :      (empty string)
         - json        : null (json null)
         - jsonf       : null (json null)
         - binary mode : N/A  (not applicable)
         - json string : "null"
      */
      if (stringb) {
        if (jsonb) {
          if (displayNextAsJsonStringb) {
            VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"null\"");
          } else {
            VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "null");
          }
        } else {
          VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "");
        }
      } else {
        /* No-op */
      }
      break;
    case MARPAESLIF_VALUE_TYPE_CHAR:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "CHAR %c 0x%02x", isprint((unsigned char) marpaESLIFValueResultp->u.c) ? marpaESLIFValueResultp->u.c : ' ', (unsigned int) marpaESLIFValueResultp->u.c);
      /* Char default representation:
         - string      : %c
         - json        : %c
         - jsonf       : %c
         - binary mode : content
         - json string : "json string"
      */
      if (stringb) {
        if (displayNextAsJsonStringb) {
          VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"");
          VALUERESULTCALLBACK_CODEPOINT_TO_JSON(genericLoggerp, marpaESLIF_stringGeneratorp, marpaESLIFValueResultp->u.c);
          VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"");
        } else {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%c", marpaESLIFValueResultp->u.c);
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.c), sizeof(marpaESLIFValueResultChar_t));
      }
      break;
    case MARPAESLIF_VALUE_TYPE_SHORT:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "SHORT %d", (int) marpaESLIFValueResultp->u.b);
      /* Char default representation:
         - string      : %d
         - json        : %d
         - jsonf       : %d
         - binary mode : content
         - json string : "%d"
      */
      /* MARPAESLIF_NOTICEF(marpaESLIFp, "... Generated string was: %s", marpaESLIF_stringGeneratorp->s); */
      if (stringb) {
        if (displayNextAsJsonStringb) {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%d\"", (int) marpaESLIFValueResultp->u.b);
        } else {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%d", (int) marpaESLIFValueResultp->u.b);
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.b), sizeof(marpaESLIFValueResultShort_t));
      }
      /* MARPAESLIF_NOTICEF(marpaESLIFp, "... Generated string is now: %s", marpaESLIF_stringGeneratorp->s); */
      break;
    case MARPAESLIF_VALUE_TYPE_INT:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "INT %d", marpaESLIFValueResultp->u.i);
      /* Char default representation:
         - string      : %d
         - json        : %d
         - jsonf       : %d
         - binary mode : content
         - json string : "%d"
      */
      if (stringb) {
        if (displayNextAsJsonStringb) {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%d\"", marpaESLIFValueResultp->u.i);
        } else {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%d", marpaESLIFValueResultp->u.i);
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.i), sizeof(marpaESLIFValueResultInt_t));
      }
      break;
    case MARPAESLIF_VALUE_TYPE_LONG:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "LONG %ld", marpaESLIFValueResultp->u.l);
      /* Long default representation:
         - string      : %ld
         - json        : %ld
         - jsonf       : %ld
         - binary mode : content
         - json string : "%ld"
      */
      if (stringb) {
        if (displayNextAsJsonStringb) {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%ld\"", marpaESLIFValueResultp->u.l);
        } else {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%ld", marpaESLIFValueResultp->u.l);
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.l), sizeof(marpaESLIFValueResultLong_t));
      }
      break;
    case MARPAESLIF_VALUE_TYPE_FLOAT:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "FLOAT %f", (double) marpaESLIFValueResultp->u.f);
      /* Float default representation:
         - string      : marpaESLIF_ftos()
         - json        : marpaESLIF_ftos() if it is not +/-Infinity or NaN, else null
         - jsonf       : marpaESLIF_ftos()
         - binary mode : content
         - json string : "marpaESLIF_ftos()" or "+Infinity" or "-Infinity" or "[+-]NaN"

           Note that output of marpaESLIF_ftos() is explicitly looked at to replace decimal digit with '.' if it is NOT already the '.' character
      */
      if (stringb) {
        if (contextp->jsonb) {
          if (MARPAESLIF_ISINF(marpaESLIFValueResultp->u.f) || MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.f)) {
            if (displayNextAsJsonStringb) {
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"null\"");
            } else {
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "null");
            }
          } else {
            VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, f, marpaESLIFValueResultp->u.f, decimalPointc, '.');
          }
        } else if (contextp->jsonfb) {
          if (MARPAESLIF_ISINF(marpaESLIFValueResultp->u.f)) {
            if (displayNextAsJsonStringb) {
              VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%sInfinity\"", (marpaESLIFValueResultp->u.f < 0) ? "-" : "+");
            } else {
              VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%sInfinity", (marpaESLIFValueResultp->u.f < 0) ? "-" : "+");
            }
          } else if (MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.f)) {
            if (displayNextAsJsonStringb) {
#ifdef C_SIGNBIT
              if (C_SIGNBIT(marpaESLIFValueResultp->u.f) == 0) {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"+NaN\"");
              } else {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"-NaN\"");
              }
#else
              /* Let's do not put the "+" sign, an indication that we really do not know -; */
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"NaN\"");
#endif
            } else {
#ifdef C_SIGNBIT
              if (C_SIGNBIT(marpaESLIFValueResultp->u.f) == 0) {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "+NaN");
              } else {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "-NaN");
              }
#else
              /* Let's do not put the "+" sign, an indication that we really do not know -; */
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "NaN");
#endif
            }
          } else {
            VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, f, marpaESLIFValueResultp->u.f, decimalPointc, '.');
          }
        } else {
          VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, f, marpaESLIFValueResultp->u.f, '\0', '\0');
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.f), sizeof(marpaESLIFValueResultFloat_t));
      }
      break;
    case MARPAESLIF_VALUE_TYPE_DOUBLE:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "DOUBLE %f", marpaESLIFValueResultp->u.d);
      /* Double default representation:
         - string      : marpaESLIF_dtos()
         - json        : marpaESLIF_dtos() if it is not +/-Infinity or NaN, else null
         - jsonf       : marpaESLIF_dtos()
         - binary mode : content
         - json string : "marpaESLIF_dtos()" if it is not +/-Infinity or NaN, else this is an error

           Note that output of marpaESLIF_dtos() is explicitly looked at to replace decimal digit with '.' if it is NOT already the '.' character
      */
      if (stringb) {
        if (contextp->jsonb) {
          if (MARPAESLIF_ISINF(marpaESLIFValueResultp->u.d) || MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.d)) {
            if (displayNextAsJsonStringb) {
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"null\"");
            } else {
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "null");
            }
          } else {
            VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, d, marpaESLIFValueResultp->u.d, decimalPointc, '.');
          }
        } else if (contextp->jsonfb) {
          if (MARPAESLIF_ISINF(marpaESLIFValueResultp->u.d)) {
            if (displayNextAsJsonStringb) {
              VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%sInfinity\"", (marpaESLIFValueResultp->u.f < 0) ? "-" : "+");
            } else {
              VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%sInfinity", (marpaESLIFValueResultp->u.d < 0) ? "-" : "+");
            }
          } else if (MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.d)) {
            if (displayNextAsJsonStringb) {
#ifdef C_SIGNBIT
              if (C_SIGNBIT(marpaESLIFValueResultp->u.d) == 0) {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"+NaN\"");
              } else {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"-NaN\"");
              }
#else
              /* Let's do not put the "+" sign, an indication that we really do not know -; */
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"NaN\"");
#endif
            } else {
#ifdef C_SIGNBIT
              if (C_SIGNBIT(marpaESLIFValueResultp->u.d) == 0) {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "+NaN");
              } else {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "-NaN");
              }
#else
              /* Let's do not put the "+" sign, an indication that we really do not know -; */
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "NaN");
#endif
            }
          } else {
            VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, d, marpaESLIFValueResultp->u.d, decimalPointc, '.');
          }
        } else {
          VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, d, marpaESLIFValueResultp->u.d, '\0', '\0');
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.d), sizeof(marpaESLIFValueResultDouble_t));
      }
      break;
    case MARPAESLIF_VALUE_TYPE_PTR:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "PTR %p", marpaESLIFValueResultp->u.p.p);
      /* Ptr default representation:
         - string      : %p
         - json        : %?? (depend on sizeof(void *))
         - jsonf       : %?? (depend on sizeof(void *))
         - binary mode : content
         - json string : "%??" (depend on sizeof(void *))
      */
      if (stringb) {
        if (jsonb) {
          if (displayNextAsJsonStringb) {
#if SIZEOF_VOID_STAR == SIZEOF_CHAR
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%c\"", (char) marpaESLIFValueResultp->u.p.p);
#else
#  if (SIZEOF_VOID_STAR == SIZEOF_SHORT) || (SIZEOF_VOID_STAR == SIZEOF_INT)
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%d\"", (int) marpaESLIFValueResultp->u.p.p);
#  else
#    if SIZEOF_VOID_STAR == SIZEOF_LONG
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%ld\"", (long) marpaESLIFValueResultp->u.p.p);
#    else
#      ifdef MARPAESLIF_HAVE_LONG_LONG
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"" MARPAESLIF_LONG_LONG_FMT "\"", (unsigned MARPAESLIF_LONG_LONG) marpaESLIFValueResultp->u.p.p);
#      else
            /* This may generate a warning */
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%ld\"", (long) marpaESLIFValueResultp->u.p.p);
#      endif
#    endif
#  endif
#endif
          } else {
#if SIZEOF_VOID_STAR == SIZEOF_CHAR
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%c", (char) marpaESLIFValueResultp->u.p.p);
#else
#  if (SIZEOF_VOID_STAR == SIZEOF_SHORT) || (SIZEOF_VOID_STAR == SIZEOF_INT)
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%d", (int) marpaESLIFValueResultp->u.p.p);
#  else
#    if SIZEOF_VOID_STAR == SIZEOF_LONG
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%ld", (long) marpaESLIFValueResultp->u.p.p);
#    else
#      ifdef MARPAESLIF_HAVE_LONG_LONG
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, MARPAESLIF_LONG_LONG_FMT, (unsigned MARPAESLIF_LONG_LONG) marpaESLIFValueResultp->u.p.p);
#      else
            /* This may generate a warning */
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%ld", (long) marpaESLIFValueResultp->u.p.p);
#      endif
#    endif
#  endif
#endif
          }
        } else {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%p", marpaESLIFValueResultp->u.p.p);
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.p.p), sizeof(void *));
      }
      break;
    case MARPAESLIF_VALUE_TYPE_ARRAY:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "ARRAY {%p,%ld}", marpaESLIFValueResultp->u.a.p, (unsigned long) marpaESLIFValueResultp->u.a.sizel);
      /* Array default representation:
         - string      : binary content
         - json        : "binary content"
         - jsonf       : "binary content"
         - binary mode : binary content
         - json string : "binary content"
      */
      if (stringb) {
        if (jsonb) {
          VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"");
          if ((marpaESLIFValueResultp->u.a.p != NULL) && (marpaESLIFValueResultp->u.a.sizel > 0)) {
            p = marpaESLIFValueResultp->u.a.p;
            maxp = p + marpaESLIFValueResultp->u.a.sizel;
            while (p < maxp) {
              VALUERESULTCALLBACK_CODEPOINT_TO_JSON(genericLoggerp, marpaESLIF_stringGeneratorp, *p);
              p++;
            }
          }
          VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"");
        } else {
          if ((marpaESLIFValueResultp->u.a.p != NULL) && (marpaESLIFValueResultp->u.a.sizel > 0)) {
            VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, marpaESLIFValueResultp->u.a.p, marpaESLIFValueResultp->u.a.sizel);
          }
        }
      } else {
        if ((marpaESLIFValueResultp->u.a.p != NULL) && (marpaESLIFValueResultp->u.a.sizel > 0)) {
          VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, marpaESLIFValueResultp->u.a.p, marpaESLIFValueResultp->u.a.sizel);
        }
      }
      break;
    case MARPAESLIF_VALUE_TYPE_BOOL:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "BOOL %d", (int) marpaESLIFValueResultp->u.y);
      /* Bool default representation:
         - string      : content
         - json        : true or false
         - jsonf       : true or false
         - binary mode : content
         - json string : "true" or "false"
      */
      if (stringb) {
        if (jsonb) {
          if (displayNextAsJsonStringb) {
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%s\"", (marpaESLIFValueResultp->u.y == MARPAESLIFVALUERESULTBOOL_TRUE) ? "true" : "false");
          } else {
            VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%s", (marpaESLIFValueResultp->u.y == MARPAESLIFVALUERESULTBOOL_TRUE) ? "true" : "false");
          }
        } else {
          VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.y), sizeof(marpaESLIFValueResultBool_t));
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.y), sizeof(marpaESLIFValueResultBool_t));
      }
      break;
    case MARPAESLIF_VALUE_TYPE_STRING:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "STRING {%p,%ld}, encoding %s", marpaESLIFValueResultp->u.s.p, (unsigned long) marpaESLIFValueResultp->u.s.sizel, marpaESLIFValueResultp->u.s.encodingasciis);
      /* String default representation:
         - string      : content
         - json        : "json string"
         - jsonf       : "json string"
         - binary mode : content
         - json string : "json string"

         In string mode, output is ALWAYS UTF-8 encoded. Up to the caller to do transformation to another encoding.
      */
      if (stringb) {
        string.bytep          = (char *) marpaESLIFValueResultp->u.s.p;
        string.bytel          = marpaESLIFValueResultp->u.s.sizel;
        string.encodingasciis = marpaESLIFValueResultp->u.s.encodingasciis;
        string.asciis         = NULL;
        if (utf8p != &string) {
          _marpaESLIF_string_freev(utf8p, 0 /* onStackb */);
        }
        utf8p = _marpaESLIF_string2utf8p(marpaESLIFp, &string, 0 /* tconvsilentb */);
        if (MARPAESLIF_UNLIKELY(utf8p == NULL)) {
          goto err;
        }
        if (jsonb) {
          VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"");
          p = utf8p->bytep;
          maxp = p + utf8p->bytel;
          while (p < maxp) {
            lengthi = _marpaESLIF_utf82ordi((PCRE2_SPTR8) p, &codepointi, (PCRE2_SPTR8) maxp);
            if (MARPAESLIF_UNLIKELY(lengthi <= 0)) {
              /* Well, this is a paranoid test: this should never happen since utf8p did not fail, so we do not bother to give any detail */
              MARPAESLIF_ERROR(marpaESLIFp, "Malformed UTF-8 byte");
              errno = EINVAL;
              goto err;
            }
            VALUERESULTCALLBACK_CODEPOINT_TO_JSON(genericLoggerp, marpaESLIF_stringGeneratorp, codepointi);
            p += lengthi;
          }
          VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"");
        } else {
          VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, utf8p->bytep, utf8p->bytel);
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) marpaESLIFValueResultp->u.s.p, marpaESLIFValueResultp->u.s.sizel);
      }
      break;
    case MARPAESLIF_VALUE_TYPE_ROW:
      /* String default representation: concatenation of sub-members representation, in reverse order for intuitive representation -; */
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "ROW {%p,%ld}", marpaESLIFValueResultp->u.r.p, (unsigned long) marpaESLIFValueResultp->u.r.sizel);
      GENERICSTACK_PUSH_PTR(todoStackp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultRightSquare);
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
        goto err;
      }
      if ((sizel = marpaESLIFValueResultp->u.r.sizel) > 0) {
        for (i = 0, j = sizel - 1, marpaESLIFValueResultTmpp = &(marpaESLIFValueResultp->u.r.p[j]);
             i < sizel;
             i++, j--, marpaESLIFValueResultTmpp--) {
          GENERICSTACK_PUSH_PTR(todoStackp, marpaESLIFValueResultTmpp);
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
            goto err;
          }
          if (j > 0) {
            /* , */
            GENERICSTACK_PUSH_PTR(todoStackp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultComma);
            if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
              MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
              goto err;
            }
          }
        }
      }
      GENERICSTACK_PUSH_PTR(todoStackp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultLeftSquare);
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
        goto err;
      }
      break;
    case MARPAESLIF_VALUE_TYPE_TABLE:
      /* Nothing else but a row with an even number of elements, in reverse order for intuitive representation -; */
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "TABLE {%p,%ld}", marpaESLIFValueResultp->u.t.p, (unsigned long) marpaESLIFValueResultp->u.t.sizel);
      GENERICSTACK_PUSH_PTR(todoStackp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultRightBracket);
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
        goto err;
      }
      if ((sizel = marpaESLIFValueResultp->u.t.sizel) > 0) {
        for (i = 0, j = sizel - 1, marpaESLIFValueResultPairp = &(marpaESLIFValueResultp->u.t.p[j]);
             i < sizel;
             i++, j--, marpaESLIFValueResultPairp--) {
          /* Value */
          GENERICSTACK_PUSH_PTR(todoStackp, &(marpaESLIFValueResultPairp->value));
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
            goto err;
          }
          /* : */
          GENERICSTACK_PUSH_PTR(todoStackp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultColon);
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
            goto err;
          }
          /* Key */
          GENERICSTACK_PUSH_PTR(todoStackp, &(marpaESLIFValueResultPairp->key));
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
            goto err;
          }
          if (jsonb) {
            /* In JSON mode, key is always a string. We preceede the test at the beginning of the loop */
            /* by ensuring this is the case, by pushing an internal marker */
            GENERICSTACK_PUSH_PTR(todoStackp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultNextValueResultMustDisplayAsJsonString);
            if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
              MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
              goto err;
            }
          }
          if (j > 0) {
            /* , */
            GENERICSTACK_PUSH_PTR(todoStackp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultComma);
            if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
              MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
              goto err;
            }
          }
        }
      }
      GENERICSTACK_PUSH_PTR(todoStackp, (marpaESLIFValueResult_t *) &marpaESLIFValueResultLeftBracket);
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
        goto err;
      }
      break;
    case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "LONG_DOUBLE %Lf", marpaESLIFValueResultp->u.ld);
      /* Long double default representation:
         - string      : marpaESLIF_ldtos()
         - json        : marpaESLIF_ldtos() if it is not +/-Infinity or NaN, else null
         - jsonf       : marpaESLIF_ldtos()
         - binary mode : content
         - json string : "marpaESLIF_ldtos()" if it is not +/-Infinity or NaN, else this is an error

           Note that output of marpaESLIF_ldtos() is explicitly looked at to replace decimal digit with '.' if it is NOT already the '.' character
      */
      if (stringb) {
        if (contextp->jsonb) {
          if (MARPAESLIF_ISINF(marpaESLIFValueResultp->u.ld) || MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.ld)) {
            if (displayNextAsJsonStringb) {
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"null\"");
            } else {
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "null");
            }
          } else {
            VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, ld, marpaESLIFValueResultp->u.ld, decimalPointc, '.');
          }
        } else if (contextp->jsonfb) {
          if (MARPAESLIF_ISINF(marpaESLIFValueResultp->u.ld)) {
            if (displayNextAsJsonStringb) {
              VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"%sInfinity\"", (marpaESLIFValueResultp->u.f < 0) ? "-" : "+");
            } else {
              VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "%sInfinity", (marpaESLIFValueResultp->u.ld < 0) ? "-" : "+");
            }
          } else if (MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.ld)) {
            if (displayNextAsJsonStringb) {
#ifdef C_SIGNBIT
              if (C_SIGNBIT(marpaESLIFValueResultp->u.ld) == 0) {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"+NaN\"");
              } else {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"-NaN\"");
              }
#else
              /* Let's do not put the "+" sign, an indication that we really do not know -; */
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "\"NaN\"");
#endif
            } else {
#ifdef C_SIGNBIT
              if (C_SIGNBIT(marpaESLIFValueResultp->u.ld) == 0) {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "+NaN");
              } else {
                VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "-NaN");
              }
#else
              /* Let's do not put the "+" sign, an indication that we really do not know -; */
              VALUERESULTCALLBACK_TRACE(genericLoggerp, marpaESLIF_stringGeneratorp, "NaN");
#endif
            }
          } else {
            VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, ld, marpaESLIFValueResultp->u.ld, decimalPointc, '.');
          }
        } else {
          VALUERESULTCALLBACK_FTOS(marpaESLIFp, genericLoggerp, marpaESLIF_stringGeneratorp, ld, marpaESLIFValueResultp->u.ld, '\0', '\0');
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.ld), sizeof(marpaESLIFValueResultLongDouble_t));
      }
      break;
#ifdef MARPAESLIF_HAVE_LONG_LONG
    case MARPAESLIF_VALUE_TYPE_LONG_LONG:
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "LONG_LONG " MARPAESLIF_LONG_LONG_FMT, marpaESLIFValueResultp->u.ll);
      /* Long long default representation:
         - string      : %ld
         - json        : %ld
         - jsonf       : %ld
         - binary mode : content
         - json string : "%ld"
      */
      if (stringb) {
        if (displayNextAsJsonStringb) {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, "\"" MARPAESLIF_LONG_LONG_FMT "\"", marpaESLIFValueResultp->u.ll);
        } else {
          VALUERESULTCALLBACK_TRACEF(genericLoggerp, marpaESLIF_stringGeneratorp, MARPAESLIF_LONG_LONG_FMT, marpaESLIFValueResultp->u.ll);
        }
      } else {
        VALUERESULTCALLBACK_OPAQUE(marpaESLIF_stringGeneratorp, (char *) &(marpaESLIFValueResultp->u.ll), sizeof(marpaESLIFValueResultLongLong_t));
      }
      break;
#endif
    default:
      MARPAESLIF_ERRORF(marpaESLIFp, "Unsupported marpaESLIFValueResult type %d", marpaESLIFValueResultp->type);
      errno = ENOSYS;
      goto err;
    }

    displayNextAsJsonStringb = 0;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  GENERICSTACK_RESET(todoStackp);
  if (utf8p != &string) {
    _marpaESLIF_string_freev(utf8p, 0 /* onStackb */);
  }
  if (disposeCallbackb) {
    if (disposeCallbackp != NULL) {
      disposeCallbackp(representationUserDatavp, srcs, srcl, encodingasciis);
      disposeCallbackp = NULL;
    }
    disposeCallbackb = 0;
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIF_generic_action___concatb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultLexemep, int arg0i, int argni, int resulti, short nullableb, char *toEncodings, short jsonb, short jsonfb)
/*****************************************************************************/
{
  /* This method guarantees to push either UNDEF, or an ARRAY, or an ASCII NUL terminated buffer PTR (caller makes sure to set ptrb and toEncodings appropriately)  */

  static const char                      *funcs                 = "_marpaESLIF_generic_action___concatb";
  marpaESLIFRecognizer_t                 *marpaESLIFRecognizerp = marpaESLIFValuep->marpaESLIFRecognizerp;
  marpaESLIF_t                           *marpaESLIFp           = marpaESLIFValuep->marpaESLIFp;
  marpaESLIF_stringGenerator_t           *stringGeneratorp      = &(marpaESLIFValuep->stringGenerator);
  char                                   *toEncodingDups        = NULL;
  int                                     argi;
  marpaESLIF_concat_valueResultContext_t  context;
  marpaESLIFValueResult_t                 marpaESLIFValueResult;
  marpaESLIFValueResult_t                *marpaESLIFValueResultp;
  char                                   *converteds;
  size_t                                  convertedl;
  short                                   rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (nullableb) {
    /* No choice: result is undef */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef))) {
      goto err;
    }
  } else {

    /* Prepare a string generator */
    _marpaESLIF_stringGeneratorResetv(stringGeneratorp);

    context.userDatavp       = userDatavp;
    context.marpaESLIFValuep = marpaESLIFValuep;
    context.stringb          = (toEncodings != NULL) ? 1 : 0;
    context.jsonb            = jsonb;
    context.jsonfb           = jsonfb;

    converteds = NULL;

    if (marpaESLIFValueResultLexemep != NULL) {
      /* Symbol action */
      marpaESLIFValueResult           = *marpaESLIFValueResultLexemep;
      /* If it is a pointer, make it shallow in any case */
      MARPAESLIF_MAKE_MARPAESLIFVALUERESULT_SHALLOW(marpaESLIFValueResult);
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_value_validb(marpaESLIFRecognizerp, &marpaESLIFValueResult, &context, _marpaESLIFRecognizer_concat_valueResultCallbackb))) {
        goto err;
      }
    } else {
      /* Rule action */
      for (argi = arg0i; argi <= argni; argi++) {
        marpaESLIFValueResultp = _marpaESLIFValue_stack_getp(marpaESLIFValuep, argi);
        if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp == NULL)) {
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_value_validb(marpaESLIFRecognizerp, marpaESLIFValueResultp, &context, _marpaESLIFRecognizer_concat_valueResultCallbackb))) {
          goto err;
        }
      }
    }

    if (stringGeneratorp->l >= 1) { /* Because of the implicit NULL byte */
      if (toEncodings != NULL) {
        if (stringGeneratorp->l > 1) {
          /* Call for conversion in any case, this is a way to validate UTF-8 correctness if the destination encoding is also UTF-8 */
          converteds = _marpaESLIF_charconvb(marpaESLIFp,
                                             toEncodings,
                                             (char *) MARPAESLIF_UTF8_STRING, /* We request that representations always produce UTF-8 strings */
                                             stringGeneratorp->s,
                                             stringGeneratorp->l - 1, /* Skip the automatic NUL byte in the source */
                                             &convertedl,
                                             NULL, /* fromEncodingsp */
                                             NULL, /* tconvpp */
                                             1, /* eofb */
                                             NULL, /* byteleftsp */
                                             NULL, /* byteleftlp */
                                             NULL, /* byteleftalloclp */
                                             0, /* tconvsilentb */
                                             NULL, /* defaultEncodings */
                                             NULL /* fallbackEncodings */);
          if (MARPAESLIF_UNLIKELY(converteds == NULL)) {
            goto err;
          }
          /* We send the whole data in one go: we ignore the fact that _marpaESLIF_string_removebomb() may return -1 */
          if (MARPAESLIF_UNLIKELY(! _marpaESLIF_string_removebomb(marpaESLIFp, converteds, &(convertedl), toEncodings, NULL /* bomsizelp */))) {
            goto err;
          }
        } else {
          /* Empty string: no conversion */
          converteds = stringGeneratorp->s;
          convertedl = 0;
          /* No free: just transfered */
          stringGeneratorp->s = NULL;
        }

        /* Duplicate toEncodings */
        toEncodingDups = strdup(toEncodings);
        if (MARPAESLIF_UNLIKELY(toEncodingDups == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
          goto err;
        }
        marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_STRING;
        marpaESLIFValueResult.contextp           = NULL;
        marpaESLIFValueResult.representationp    = NULL;
        marpaESLIFValueResult.u.s.p              = (unsigned char *) converteds;
        marpaESLIFValueResult.u.s.shallowb       = 0;
        marpaESLIFValueResult.u.s.encodingasciis = toEncodingDups;
        marpaESLIFValueResult.u.s.freeUserDatavp = marpaESLIFRecognizerp->marpaESLIFp;
        marpaESLIFValueResult.u.s.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;
        marpaESLIFValueResult.u.s.sizel          = convertedl;
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &marpaESLIFValueResult))) {
          goto err;
        }
        /* converteds is now in the stack */
        converteds = NULL;
        /* toEncodingDups as well */
        toEncodingDups = NULL;
      } else {
        marpaESLIFValueResult.type            = MARPAESLIF_VALUE_TYPE_ARRAY;
        marpaESLIFValueResult.contextp        = NULL;
        marpaESLIFValueResult.representationp = NULL;
        marpaESLIFValueResult.u.a.p           = stringGeneratorp->s;
        marpaESLIFValueResult.u.a.shallowb    = 0;
        marpaESLIFValueResult.u.a.freeUserDatavp = marpaESLIFRecognizerp->marpaESLIFp;
        marpaESLIFValueResult.u.a.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;
        marpaESLIFValueResult.u.a.sizel       = stringGeneratorp->l - 1;

        if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &marpaESLIFValueResult))) {
          goto err;
        }
        /* stringGeneratorp->s is now in the stack */
        stringGeneratorp->s = NULL;
      }
    } else {
      if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef))) {
        goto err;
      }
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  /* No need to do any of these tests when this is a nullable */
  if (! nullableb) {
    if (converteds != NULL) {
      free(converteds);
    }
    if (toEncodingDups != NULL) {
      free(toEncodingDups);
    }
  }

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_generic_action_copyb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int argi, int resulti, short nullableb)
/*****************************************************************************/
{
  static const char         *funcs = "_marpaESLIF_generic_action_copyb";
  int                        argorigi;
  marpaESLIFValueResult_t    marpaESLIFValueResult;
  marpaESLIFValueResult_t   *marpaESLIFValueResultp;
  short                      forgetb;
  short                      rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  if (nullableb) {
    marpaESLIFValueResultp = (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef;
    forgetb = 0;
  } else {

    /* Use the perl formalism for negative indices */
    argorigi = argi;
    if (argi < 0) {
      argi = argni + 1 + argi;
    }

    if (MARPAESLIF_UNLIKELY((argi < arg0i) || (argi > argni))) {
      if (argorigi < 0) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Indice %d converted to %d is out of range [%d..%d]", argorigi, argi, arg0i, argni);
      } else {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Indice %d is out of range [%d..%d]", argi, arg0i, argni);
      }
      goto err;
    }

    /* When argi is resulti, this is a no-op */
    if (argi == resulti) {
#ifdef MARPAESLIF_NOTICE_ACTION
      MARPAESLIF_NOTICEF(marpaESLIFValuep->marpaESLIFp, "%s: Action %s is a no-op for stack at indice %d", funcs, marpaESLIFValuep->actions, resulti);
#endif
      MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "No-op");
      rcb = 1;
      goto done;
    }

    if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_getAndForgetb(marpaESLIFValuep, argi, &marpaESLIFValueResult))) {
      goto err;
    }
    marpaESLIFValueResultp = &marpaESLIFValueResult;
    forgetb = 1;
  }

  rcb = _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, marpaESLIFValueResultp);
  /*
   * If this failed, since we are not atomic, try to restore the original, ignoring failure or not
   */
  if (MARPAESLIF_UNLIKELY((! rcb) && forgetb)) {
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_setb(marpaESLIFValuep, argi, marpaESLIFValueResultp))) {
      MARPAESLIF_WARNF(marpaESLIFValuep->marpaESLIFp, "Failure to restore original value at indice %d", argi);
    }
  }
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___concatb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  return _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, NULL /* marpaESLIFValueResultLexemep */, arg0i, argni, resulti, nullableb, NULL /* toEncodings */, 0 /* jsonb */, 0 /* jsonfb */);
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___copyb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  /* We want to copy in resulti the stack item at ::copy[THIS] */
  static const char      *funcs   = "_marpaESLIF_rule_action___copyb";
  char                   *actions = marpaESLIFValuep->actions;
  int                     rhsi;
  short                   rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(actions == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFValuep->marpaESLIFp, "actions is NULL, cannot guess indice to copy");
    goto err;
  }

  rhsi = atoi(actions + copyl + 1); /* Because copyl is the length of "::copy" */

  rcb = _marpaESLIF_generic_action_copyb(userDatavp, marpaESLIFValuep, arg0i, argni, arg0i + rhsi, resulti, nullableb);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___undefb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIF_rule_action___undefb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef);

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___trueb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIF_rule_action___trueb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &(marpaESLIFValuep->marpaESLIFp->marpaESLIFValueResultTrue));

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___falseb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIF_rule_action___trueb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &(marpaESLIFValuep->marpaESLIFp->marpaESLIFValueResultFalse));

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___jsonb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  return _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, NULL /* marpaESLIFValueResultLexemep */, arg0i, argni, resulti, nullableb, "UTF-8", 1 /* jsonb */, 0 /* jsonfb */);
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___jsonfb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  return _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, NULL /* marpaESLIFValueResultLexemep */, arg0i, argni, resulti, nullableb, "UTF-8", 0 /* jsonb */, 1 /* jsonfb */);
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___rowb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  short                    rcb;
  size_t                   i;
  int                      indicei;
  marpaESLIFValueResult_t  marpaESLIFValueResult;
  marpaESLIFValueResult_t  item;

  marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_ROW;
  marpaESLIFValueResult.contextp           = NULL;
  marpaESLIFValueResult.representationp    = NULL;
  marpaESLIFValueResult.u.r.p              = NULL;
  marpaESLIFValueResult.u.r.shallowb       = 0;
  /* Eventual trailing separator in case of proper => 0 is automatically off with the division */
  marpaESLIFValueResult.u.r.sizel          = nullableb ? 0 : (marpaESLIFValuep->hideSeparatorb ? ((argni - arg0i) / 2) + 1: (argni - arg0i + 1));
  marpaESLIFValueResult.u.r.freeUserDatavp = marpaESLIFValuep->marpaESLIFp;
  marpaESLIFValueResult.u.r.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;

  if (marpaESLIFValueResult.u.r.sizel > 0) {
    if (marpaESLIFValuep->marpaESLIFp->ZeroIntegerisZeroBytesb) {
      /* We do explicitely a calloc instead of a malloc, so that inner types are */
      /* automatically set to MARPAESLIF_VALUE_TYPE_UNDEF.                       */
      if (MARPAESLIF_UNLIKELY((marpaESLIFValueResult.u.r.p = (marpaESLIFValueResult_t *) calloc(marpaESLIFValueResult.u.r.sizel, sizeof(marpaESLIFValueResult_t))) == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "calloc failure, %s", strerror(errno));
        goto err;
      }
    } else {
      if (MARPAESLIF_UNLIKELY((marpaESLIFValueResult.u.r.p = (marpaESLIFValueResult_t *) malloc(marpaESLIFValueResult.u.r.sizel * sizeof(marpaESLIFValueResult_t))) == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      for (i = 0; i < marpaESLIFValueResult.u.r.sizel; i++) {
        marpaESLIFValueResult.u.r.p[i].type = MARPAESLIF_VALUE_TYPE_UNDEF;
      }
    }
    if (! marpaESLIFValuep->hideSeparatorb) {
      /* Take all items */
      for (i = 0, indicei = arg0i; i < marpaESLIFValueResult.u.r.sizel; i++, indicei++) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_getAndForgetb(marpaESLIFValuep, indicei, &item))) {
          goto err;
        }
        marpaESLIFValueResult.u.r.p[i] = item;
      }
    } else {
      /* Skip the separator (c.f. the += 2) */
      for (i = 0, indicei = arg0i; i < marpaESLIFValueResult.u.r.sizel; i++, indicei += 2) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_getAndForgetb(marpaESLIFValuep, indicei, &item))) {
          goto err;
        }
        marpaESLIFValueResult.u.r.p[i] = item;
      }
    }
  }

  /* If this fails, we will leak at most */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &marpaESLIFValueResult))) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  if (marpaESLIFValueResult.u.r.p != NULL) {
    free(marpaESLIFValueResult.u.r.p);
  }
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___tableb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
/* Exactly the same logic as for row except that the target is of type table and that we require an even number of elements */
/*****************************************************************************/
{
  short                    rcb;
  size_t                   i;
  int                      indicei;
  size_t                   j;
  size_t                   jmax;
  size_t                   argsl;
  marpaESLIFValueResult_t  marpaESLIFValueResult;
  marpaESLIFValueResult_t  item;
  short                    keyb;

  marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_TABLE;
  marpaESLIFValueResult.contextp           = NULL;
  marpaESLIFValueResult.representationp    = NULL;
  marpaESLIFValueResult.u.t.p              = NULL;
  marpaESLIFValueResult.u.t.shallowb       = 0;
  /* Eventual trailing separator in case of proper => 0 is automatically off with the division */
  argsl                                    = nullableb ? 0 : (marpaESLIFValuep->hideSeparatorb ? ((argni - arg0i) / 2) + 1: (argni - arg0i + 1));
  marpaESLIFValueResult.u.t.freeUserDatavp = marpaESLIFValuep->marpaESLIFp;
  marpaESLIFValueResult.u.t.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;

  if (MARPAESLIF_UNLIKELY((argsl % 2) != 0)) {
    MARPAESLIF_ERROR(marpaESLIFValuep->marpaESLIFp, "::table rule action requires an even number of arguments");
    goto err;
  }

  marpaESLIFValueResult.u.t.sizel = argsl / 2;
  if (marpaESLIFValueResult.u.t.sizel > 0) {
    if (marpaESLIFValuep->marpaESLIFp->ZeroIntegerisZeroBytesb) {
      /* We do explicitely a calloc instead of a malloc, so that inner key */
      /* and value type are automatically MARPAESLIF_VALUE_TYPE_UNDEF.     */
      if (MARPAESLIF_UNLIKELY((marpaESLIFValueResult.u.t.p = (marpaESLIFValueResultPair_t *) calloc(marpaESLIFValueResult.u.t.sizel, sizeof(marpaESLIFValueResultPair_t))) == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "calloc failure, %s", strerror(errno));
        goto err;
      }
    } else {
      if (MARPAESLIF_UNLIKELY((marpaESLIFValueResult.u.t.p = (marpaESLIFValueResultPair_t *) malloc(marpaESLIFValueResult.u.t.sizel * sizeof(marpaESLIFValueResultPair_t))) == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }

      jmax = argsl / 2;
      for (j = 0; j < jmax; j++) {
        marpaESLIFValueResult.u.t.p[j].key.type = MARPAESLIF_VALUE_TYPE_UNDEF;
        marpaESLIFValueResult.u.t.p[j].value.type = MARPAESLIF_VALUE_TYPE_UNDEF;
      }
    }

    if (! marpaESLIFValuep->hideSeparatorb) {
      /* Take all pairs */
      keyb = 1;
      for (i = 0, indicei = arg0i, j = 0; i < argsl; i++, indicei++, keyb = !keyb) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_getAndForgetb(marpaESLIFValuep, indicei, &item))) {
          goto err;
        }

        if (keyb) {
          marpaESLIFValueResult.u.t.p[j].key = item;
        } else {
          marpaESLIFValueResult.u.t.p[j++].value = item;
        }
      }
    } else {
      /* Skip the separator (c.f. the += 2) */
      keyb = 1;
      for (i = 0, indicei = arg0i, j = 0; i < argsl; i++, indicei += 2, keyb = !keyb) {
        if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_getAndForgetb(marpaESLIFValuep, indicei, &item))) {
          goto err;
        }

        if (keyb) {
          marpaESLIFValueResult.u.t.p[j].key = item;
        } else {
          marpaESLIFValueResult.u.t.p[j++].value = item;
        }
      }
    }
  }

  /* If this fails, we will leak at most */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &marpaESLIFValueResult))) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  if (marpaESLIFValueResult.u.t.p != NULL) {
    free(marpaESLIFValueResult.u.t.p);
  }
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___astb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
/* almost like ::row, except that this is a table where single key is rule   */
/* name and single value is the list of values.                              */
/*****************************************************************************/
{
  short                    rcb;
  size_t                   i;
  marpaESLIFValueResult_t  marpaESLIFValueResult;
  marpaESLIFValueResult_t *marpaESLIFValueResultp;
  marpaESLIFValueResult_t *keyp;
  marpaESLIFValueResult_t *valuep;
  short                   *origshallowbp;
  marpaESLIF_symbol_t     *symbolp;
  size_t                   sizel;

  marpaESLIFValueResult.type               = MARPAESLIF_VALUE_TYPE_TABLE;
  marpaESLIFValueResult.contextp           = NULL;
  marpaESLIFValueResult.representationp    = NULL;
  marpaESLIFValueResult.u.t.p              = NULL;
  marpaESLIFValueResult.u.t.shallowb       = 0;
  marpaESLIFValueResult.u.t.sizel          = 0;
  marpaESLIFValueResult.u.t.freeUserDatavp = marpaESLIFValuep->marpaESLIFp;
  marpaESLIFValueResult.u.t.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;

  if (MARPAESLIF_UNLIKELY((marpaESLIFValueResult.u.t.p = (marpaESLIFValueResultPair_t *) malloc(sizeof(marpaESLIFValueResultPair_t))) == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  keyp   = &(marpaESLIFValueResult.u.t.p[0].key);
  valuep = &(marpaESLIFValueResult.u.t.p[0].value);

  /* Per definition, current rule is in marpaESLIFValuep->rulep it is a rule action callback, symbolp otherwise (case of a nullable symbol action) */
  symbolp = marpaESLIFValuep->rulep != NULL ? marpaESLIFValuep->rulep->lhsp : marpaESLIFValuep->symbolp;
  keyp->type               = MARPAESLIF_VALUE_TYPE_STRING;
  keyp->contextp           = NULL;
  keyp->representationp    = NULL;
  keyp->u.s.p              = (unsigned char *) symbolp->descp->bytep;
  keyp->u.s.shallowb       = 1;
  keyp->u.s.freeUserDatavp = NULL;
  keyp->u.s.freeCallbackp  = NULL;
  keyp->u.s.sizel          = symbolp->descp->bytel;
  keyp->u.s.encodingasciis = symbolp->descp->encodingasciis;

  *valuep = marpaESLIFValueResultUndef;

  marpaESLIFValueResult.u.t.sizel   = 1;

  if (! nullableb) {
    sizel = argni - arg0i + 1;

    valuep->type               = MARPAESLIF_VALUE_TYPE_ROW;
    valuep->contextp           = NULL;
    valuep->representationp    = NULL;
    valuep->u.r.p              = NULL;
    valuep->u.r.shallowb       = 0;
    valuep->u.r.sizel          = sizel;
    valuep->u.r.freeUserDatavp = marpaESLIFValuep->marpaESLIFp;
    valuep->u.r.freeCallbackp  = _marpaESLIF_generic_freeCallbackv;

    if (sizel > 0) {
      if (MARPAESLIF_UNLIKELY((valuep->u.r.p = (marpaESLIFValueResult_t *) malloc(sizel * sizeof(marpaESLIFValueResult_t))) == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      for (i = 0; i < sizel; i++) {
        marpaESLIFValueResultp = _marpaESLIFValue_stack_getp(marpaESLIFValuep, (int) (arg0i + i));
        if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Failed to fetch value result at stack indice %d", resulti);
          goto err;
        }

        /* We have to take care of members's shallow status: the array becomes the owner in any case */
        origshallowbp = NULL;
        switch (marpaESLIFValueResultp->type) {
        case MARPAESLIF_VALUE_TYPE_PTR:
          origshallowbp = &(marpaESLIFValueResultp->u.p.shallowb);
          break;
        case MARPAESLIF_VALUE_TYPE_ARRAY:
          origshallowbp = &(marpaESLIFValueResultp->u.a.shallowb);
          break;
        case MARPAESLIF_VALUE_TYPE_STRING:
          origshallowbp = &(marpaESLIFValueResultp->u.s.shallowb);
          break;
        case MARPAESLIF_VALUE_TYPE_ROW:
          origshallowbp = &(marpaESLIFValueResultp->u.r.shallowb);
          break;
        case MARPAESLIF_VALUE_TYPE_TABLE:
          origshallowbp = &(marpaESLIFValueResultp->u.t.shallowb);
          break;
        default:
          break;
        }

        valuep->u.r.p[i] = *marpaESLIFValueResultp;

        if (origshallowbp != NULL) {
          *origshallowbp = 1;
        }
      }
    }
  }

  /* If this fails, we will leak at most */
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &marpaESLIFValueResult))) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  if (marpaESLIFValueResult.u.t.p != NULL) {
    if ((valuep->type == MARPAESLIF_VALUE_TYPE_ROW) && (valuep->u.r.p != NULL)) {
      free(valuep->u.r.p);
    }
  }
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___asciib(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  return _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, NULL /* marpaESLIFValueResultLexemep */, arg0i, argni, resulti, nullableb, "ASCII", 0 /* jsonb */, 0 /* jsonfb */);
}

/*****************************************************************************/
static short _marpaESLIF_rule_action___convertb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, int arg0i, int argni, int resulti, short nullableb)
/*****************************************************************************/
{
  /* We want to copy in resulti the result of ::convert[THIS] */
  static const char *funcs    = "_marpaESLIF_rule_action___convertb";
  char              *actions  = marpaESLIFValuep->actions;
  char              *converts = NULL;
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(actions == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFValuep->marpaESLIFp, "actions is NULL, cannot guess convert encoding");
    goto err;
  }

  converts = strdup(actions);
  if (MARPAESLIF_UNLIKELY(converts == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "strdup failure, %s", strerror(errno));
    goto err;
  }

  /* By definition, converts is "::convert[THIS]" */
  converts[strlen(converts) - 1] = '\0';  /* Remove the last "]" */

  rcb = _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, NULL /* marpaESLIFValueResultLexemep */, arg0i, argni, resulti, nullableb, converts + convertl + 1, 0 /* jsonb */, 0 /* jsonfb */);
  goto done;

 err:
  rcb = 0;

 done:
  if (converts != NULL) {
    free(converts);
  }
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___concatb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
{
  return _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, marpaESLIFValueResultp, -1 /* arg0i */, -1 /* argni */, resulti, 0 /* nullableb */, NULL /* toEncodings */, 0 /* jsonb */, 0 /* jsonfb */);
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___trueb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
{
  return _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &(marpaESLIFValuep->marpaESLIFp->marpaESLIFValueResultTrue));
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___falseb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
{
  return _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, &(marpaESLIFValuep->marpaESLIFp->marpaESLIFValueResultFalse));
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___jsonb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
{
  return _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, marpaESLIFValueResultp, -1 /* arg0i */, -1 /* argni */, resulti, 0 /* nullableb */, "UTF-8", 1 /* jsonb */, 0 /* jsonfb */);
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___jsonfb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
{
  return _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, marpaESLIFValueResultp, -1 /* arg0i */, -1 /* argni */, resulti, 0 /* nullableb */, "UTF-8", 0 /* jsonb */, 1 /* jsonfb */);
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___transferb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
/* This method can be called in only one case: this is the top recognizer    */
/* that wants to put in its value stack a lexeme's marpaESLIFValueResultp.   */
/*****************************************************************************/
{
  static const char      *funcs = "_marpaESLIF_symbol_action___transferb";
  short                   rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start, resulti=%d", resulti);

  /* Two cases: the lexeme comes from external, or from the grammar */
  /* It is easy to distinguish the two cases using the context:     */
  /* - Internal lexemes have a NULL context, are always of type ARRAY */
  /* - External lexemes have a non-NULL context */
  /* Whatever the case, the original can be shallowed. */
  rcb = _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, marpaESLIFValueResultp);
  if (rcb) {
    MARPAESLIF_MAKE_MARPAESLIFVALUERESULTP_SHALLOW(marpaESLIFValueResultp);
  }

  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___undefb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
{
  return _marpaESLIFValue_stack_setb(marpaESLIFValuep, resulti, (marpaESLIFValueResult_t *) &marpaESLIFValueResultUndef);
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___asciib(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
{
  return _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, marpaESLIFValueResultp, -1 /* arg0i */, -1 /* argni */, resulti, 0 /* nullableb */, "ASCII", 0 /* jsonb */, 0 /* jsonfb */);
}

/*****************************************************************************/
static short _marpaESLIF_symbol_action___convertb(void *userDatavp, marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp, int resulti)
/*****************************************************************************/
{
  /* We want to copy in resulti the result of ::convert[THIS] */
  static const char      *funcs    = "_marpaESLIF_symbol_action___convertb";
  char                   *actions  = marpaESLIFValuep->actions;
  char                   *converts = NULL;
  short                   rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFValuep->marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(actions == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFValuep->marpaESLIFp, "actions is NULL, cannot guess convert encoding");
    goto err;
  }

  converts = strdup(actions);
  if (MARPAESLIF_UNLIKELY(converts == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "strdup failure, %s", strerror(errno));
    goto err;
  }

  /* By definition, converts is "::convert[THIS]" */
  converts[strlen(converts) - 1] = '\0';  /* Remove the last "]" */

  rcb = _marpaESLIF_generic_action___concatb(userDatavp, marpaESLIFValuep, marpaESLIFValueResultp, -1 /* arg0i */, -1 /* argni */, resulti, 0 /* nullableb */, converts + convertl + 1, 0 /* jsonb */, 0 /* jsonfb */);
  goto done;

 err:
  rcb = 0;

 done:
  if (converts != NULL) {
    free(converts);
  }
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFValuep->marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFValue_stack_getAndForgetb(marpaESLIFValue_t *marpaESLIFValuep, int indicei, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFValue_stack_getAndForgetb";
  
  if (MARPAESLIF_UNLIKELY(marpaESLIFValuep == NULL)) {
    errno = EINVAL;
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(indicei < 0)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Indice %d is negative", indicei);
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFValuep->marpaESLIFp, "marpaESLIFValueResultp is NULL");
    return 0;
  }

  if (MARPAESLIF_UNLIKELY(! marpaESLIFValuep->inValuationb)) {
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s must be called only in an action callback", funcs);
    return 0;
  }

  return _marpaESLIFValue_stack_getAndForgetb(marpaESLIFValuep, indicei, marpaESLIFValueResultp);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_readb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **inputsp, size_t *inputlp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_readb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(! __marpaESLIFRecognizer_readb(marpaESLIFRecognizerp))) {
    goto err;
  }

  rcb = marpaESLIFRecognizer_inputb(marpaESLIFRecognizerp, inputsp, inputlp);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_readb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **inputsp, size_t *inputlp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_readb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_readb(marpaESLIFRecognizerp, inputsp, inputlp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_inputb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **inputsp, size_t *inputlp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_inputb";

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "inputs=%p", marpaESLIFRecognizerp->marpaESLIF_streamp->inputs);
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "inputl=%ld", (unsigned long) marpaESLIFRecognizerp->marpaESLIF_streamp->inputl);

  if (inputsp != NULL) {
    *inputsp = marpaESLIFRecognizerp->marpaESLIF_streamp->inputs;
  }
  if (inputlp != NULL) {
    *inputlp = marpaESLIFRecognizerp->marpaESLIF_streamp->inputl;
  }

  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "return 1");
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);

  return 1;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_scanb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short initialEventsb, short *continuebp, short *isExhaustedbp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_scanb";
  short              rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp->scanb)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Scan can be done only once");
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(! marpaESLIFRecognizerp->grammarp->latmb)) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp,
                      "Scan requires your grammar at level %d (%s) to have: latm => 1",
                      marpaESLIFRecognizerp->grammarp->leveli,
                      marpaESLIFRecognizerp->grammarp->descp->asciis
                      );
    goto err;
  }

  marpaESLIFRecognizerp->scanb = 1;
  rcb = __marpaESLIFRecognizer_resumeb(marpaESLIFRecognizerp, 0 /* deltaLengthl */, initialEventsb, continuebp, isExhaustedbp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_inputb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **inputsp, size_t *inputlp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_inputb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_inputb(marpaESLIFRecognizerp, inputsp, inputlp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_errorb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_errorb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  _marpaESLIFRecognizer_errorv(marpaESLIFRecognizerp);
  rcb = 1;
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_locationb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *linelp, size_t *columnlp)
/*****************************************************************************/
{
  static const char   *funcs = "marpaESLIFRecognizer_locationb";
  marpaESLIF_stream_t *marpaESLIF_streamp;
  short                rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;

  if (linelp != NULL) {
    *linelp = marpaESLIF_streamp->linel;
  }
  if (columnlp != NULL) {
    *columnlp = marpaESLIF_streamp->columnl;
  }

  rcb = 1;
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_last_symbolDatab(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *symbols, char **bytesp, size_t *bytelp, marpaESLIF_symbol_data_t **symbolDatapp, short forPauseb, marpaESLIF_symbol_type_t type, short onlyLhsb, short onlyRhsb)
/*****************************************************************************/
{
  marpaESLIF_t              *marpaESLIFp = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIF_grammar_t      *grammarp    = marpaESLIFRecognizerp->grammarp;
  marpaESLIF_symbol_t       *symbolp;
  marpaESLIF_symbol_data_t  *symbolDatap;
  short                      conditionb;
  char                      *bytes;
  size_t                     bytel;
  short                      rcb;

  /* A symbol that is matched must be an RHS in the current grammar */
  symbolp = _marpaESLIF_symbol_findp(marpaESLIFp, grammarp, symbols, -1, NULL /* symbolip */, 1 /* silentb */, onlyLhsb, onlyRhsb, type);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Failed to find symbol <%s> used only as an RHS", symbols);
    goto err;
  }

  if (forPauseb) {
    /* Any lexeme that as an event (grammar validation made sure that only symbols can have such events) */
    conditionb = (symbolp->eventBefores != NULL) || (symbolp->eventAfters != NULL);
  } else {
    /* Any symbol that is a lexeme or a terminal or the :discard entry */
    conditionb = MARPAESLIF_IS_LEXEME_OR_TERMINAL(symbolp) || MARPAESLIF_IS_DISCARD(symbolp);
  }

  symbolDatap = symbolDatapp[symbolp->idi];
  if (symbolDatap == NULL) {
    /* This is an error unless conditionb is true - then it means it was not set */
    if (MARPAESLIF_UNLIKELY(! conditionb)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "Symbol <%s> has no data setting", symbols);
      errno = EINVAL;
      goto err;
    }
    bytes = NULL;
    bytel = 0;
  } else {
    bytes = symbolDatap->bytes;
    bytel = symbolDatap->bytel;
  }
  
  if (bytesp != NULL) {
    *bytesp = bytes;
  }
  if (bytelp != NULL) {
    *bytelp = bytel;
  }
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_discard_lastb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **bytesp, size_t *bytelp)
/*****************************************************************************/
{
  short rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  if (bytesp != NULL) {
    *bytesp = marpaESLIFRecognizerp->lastDiscards;
  }
  if (bytelp != NULL) {
    *bytelp = marpaESLIFRecognizerp->lastDiscardl;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_name_last_pauseb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, char **pausesp, size_t *pauselp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_name_last_pauseb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  if (MARPAESLIF_UNLIKELY(names == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Name is NULL");
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_name_last_pauseb(marpaESLIFRecognizerp, names, pausesp, pauselp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_name_last_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, char **trysp, size_t *trylp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_name_last_tryb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  if (MARPAESLIF_UNLIKELY(names == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "Name is NULL");
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_name_last_tryb(marpaESLIFRecognizerp, names, trysp, trylp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_name_last_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, char **trysp, size_t *trylp)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_last_symbolDatab(marpaESLIFRecognizerp, names, trysp, trylp, marpaESLIFRecognizerp->lastTrypp, 0 /* forPauseb */, MARPAESLIF_SYMBOL_TYPE_NA, 0 /* onlyLhsb */, 1 /* onlyRhsb */);
}

/*****************************************************************************/
short marpaESLIFRecognizer_discard_last_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **trysp, size_t *trylp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_discard_last_tryb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_discard_last_tryb(marpaESLIFRecognizerp, trysp, trylp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_discard_lastb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **trysp, size_t *trylp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_discard_lastb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_discard_lastb(marpaESLIFRecognizerp, trysp, trylp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static INLINE_QSORT int _marpaESLIF_event_sorti(const void *p1, const void *p2)
/*****************************************************************************/
{
  marpaESLIFEvent_t *event1p = (marpaESLIFEvent_t *) p1;
  marpaESLIFEvent_t *event2p = (marpaESLIFEvent_t *) p2;
  int                rci;
  /* The order is:

     MARPAESLIF_EVENTTYPE_PREDICTED
     MARPAESLIF_EVENTTYPE_BEFORE
     MARPAESLIF_EVENTTYPE_NULLED
     MARPAESLIF_EVENTTYPE_AFTER
     MARPAESLIF_EVENTTYPE_COMPLETED
     MARPAESLIF_EVENTTYPE_DISCARD
     MARPAESLIF_EVENTTYPE_EXHAUSTED
     else
       no order
  */

  switch (event1p->type) {
  case MARPAESLIF_EVENTTYPE_NONE: /* Happen when we clear grammar events and repush them */
    /* This should be rci == 0 when event2p->type is NONE, but this has no consequence:  */
    /* NONE is at the very end - by doing this we avoid a sub-switch -; */
    rci = 1;
    /*
    switch (event2p->type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_BEFORE:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_NULLED:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_AFTER:      rci =  1; break;
    case MARPAESLIF_EVENTTYPE_COMPLETED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_DISCARD:    rci =  1; break;
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_NONE:       rci =  0; break;
    default:                              rci =  0; break;
    }
    */
    break;
  case MARPAESLIF_EVENTTYPE_PREDICTED:
    switch (event2p->type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:  rci =  0; break;
    case MARPAESLIF_EVENTTYPE_BEFORE:     rci = -1; break;
    case MARPAESLIF_EVENTTYPE_NULLED:     rci = -1; break;
    case MARPAESLIF_EVENTTYPE_AFTER:      rci = -1; break;
    case MARPAESLIF_EVENTTYPE_COMPLETED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_DISCARD:    rci = -1; break;
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_NONE:       rci = -1; break;
    default:                              rci =  0; break; /* Should never happen */
    }
    break;
  case MARPAESLIF_EVENTTYPE_BEFORE:
    switch (event2p->type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_BEFORE:     rci =  0; break;
    case MARPAESLIF_EVENTTYPE_NULLED:     rci = -1; break;
    case MARPAESLIF_EVENTTYPE_AFTER:      rci = -1; break;
    case MARPAESLIF_EVENTTYPE_COMPLETED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_DISCARD:    rci = -1; break;
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_NONE:       rci = -1; break;
    default:                              rci =  0; break; /* Should never happen */
    }
    break;
  case MARPAESLIF_EVENTTYPE_NULLED:
    switch (event2p->type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_BEFORE:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_NULLED:     rci =  0; break;
    case MARPAESLIF_EVENTTYPE_AFTER:      rci = -1; break;
    case MARPAESLIF_EVENTTYPE_COMPLETED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_DISCARD:    rci = -1; break;
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_NONE:       rci = -1; break;
    default:                              rci =  0; break; /* Should never happen */
    }
    break;
  case MARPAESLIF_EVENTTYPE_AFTER:
    switch (event2p->type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_BEFORE:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_NULLED:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_AFTER:      rci =  0; break;
    case MARPAESLIF_EVENTTYPE_COMPLETED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_DISCARD:    rci = -1; break;
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_NONE:       rci = -1; break;
    default:                              rci =  0; break; /* Should never happen */
    }
    break;
  case MARPAESLIF_EVENTTYPE_COMPLETED:
    switch (event2p->type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_BEFORE:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_NULLED:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_AFTER:      rci =  1; break;
    case MARPAESLIF_EVENTTYPE_COMPLETED:  rci =  0; break;
    case MARPAESLIF_EVENTTYPE_DISCARD:    rci = -1; break;
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_NONE:       rci = -1; break;
    default:                              rci =  0; break; /* Should never happen */
    }
    break;
  case MARPAESLIF_EVENTTYPE_DISCARD:
    switch (event2p->type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_BEFORE:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_NULLED:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_AFTER:      rci =  1; break;
    case MARPAESLIF_EVENTTYPE_COMPLETED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_DISCARD:    rci =  0; break;
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:  rci = -1; break;
    case MARPAESLIF_EVENTTYPE_NONE:       rci = -1; break;
    default:                              rci =  0; break; /* Should never happen */
    }
    break;
  case MARPAESLIF_EVENTTYPE_EXHAUSTED: /* Always at the very end, except if event2p->type is NONE */
    switch (event2p->type) {
    case MARPAESLIF_EVENTTYPE_PREDICTED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_BEFORE:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_NULLED:     rci =  1; break;
    case MARPAESLIF_EVENTTYPE_AFTER:      rci =  1; break;
    case MARPAESLIF_EVENTTYPE_COMPLETED:  rci =  1; break;
    case MARPAESLIF_EVENTTYPE_DISCARD:    rci =  1; break;
    case MARPAESLIF_EVENTTYPE_EXHAUSTED:  rci =  0; break;
    case MARPAESLIF_EVENTTYPE_NONE:       rci = -1; break;
    default:                              rci =  0; break; /* Should never happen */
    }
    break;
  default: /* Should never happen */
    rci = 0;
    break;
  }

  return rci;
}

/*****************************************************************************/
static inline int _marpaESLIF_event_sort_inlinedi(marpaESLIFEvent_t *p1, marpaESLIFEvent_t *p2)
/*****************************************************************************/
{
  /* The only thing of interest for inlined qsort is when one element is less than another */
  return (_marpaESLIF_event_sorti((const void *) p1, (const void *) p2)) < 0 ? 1 : 0;
}

/*****************************************************************************/
static INLINE_QSORT int _marpaESLIF_symbol_priority_sorti(const void *p1, const void *p2)
/*****************************************************************************/
{
  static const char   *funcs                = "_marpaESLIF_symbol_priority_sorti";
  marpaESLIF_symbol_t *marpaESLIF_symbol_1p = * (marpaESLIF_symbol_t **) p1;
  marpaESLIF_symbol_t *marpaESLIF_symbol_2p = * (marpaESLIF_symbol_t **) p2;
  int                  priority1i           = marpaESLIF_symbol_1p->priorityi;
  int                  priority2i           = marpaESLIF_symbol_2p->priorityi;

  /* We want to sort by priority descending */
  return (priority1i == priority2i) ? 0 : (priority1i > priority2i) ? -1 : 1;
}

/*****************************************************************************/
static inline int _marpaESLIF_symbol_priority_sort_inlinedi(marpaESLIF_symbol_t **p1, marpaESLIF_symbol_t **p2)
/*****************************************************************************/
{
  /* The only thing of interest for inlined qsort is when one element is less than another */
  return (_marpaESLIF_symbol_priority_sorti(p1, p2)) < 0 ? 1 : 0;
}

/*****************************************************************************/
static int _marpaESLIF_cleanup_sorti(const void *p1, const void *p2)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIF_cleanup_sorti";
  /* C.f. _marpaESLIFRecognizer_pointers_tracki:                                */
  /* It is pushing PTRs that are pointers to marpaESLIFValueResult_t structures */
  marpaESLIFValueResult_t *marpaESLIFValueResult1p = ((genericStackItem_t *) p1)->u.p;
  marpaESLIFValueResult_t *marpaESLIFValueResult2p = ((genericStackItem_t *) p2)->u.p;
  void                    *q1                      = MARPAESLIFVALUERESULT_TO_P(marpaESLIFValueResult1p);
  void                    *q2                      = MARPAESLIFVALUERESULT_TO_P(marpaESLIFValueResult2p);

  return (q1 < q2) ? -1 : ((q1 > q2) ? 1 : 0);
}

/*****************************************************************************/
static inline int _marpaESLIF_cleanup_sort_inlinedi(genericStackItem_t *p1, genericStackItem_t *p2)
/*****************************************************************************/
{
  /* The only thing of interest for inlined qsort is when one element is less than another */
  return (_marpaESLIF_cleanup_sorti((const void *) p1, (const void *) p2)) < 0 ? 1 : 0;
}

/*****************************************************************************/
short marpaESLIFRecognizer_last_completedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, char **offsetpp, size_t *lengthlp)
/*****************************************************************************/
{
  /* This method work only for the CURRENT grammar of CURRENT recognizer */
  static const char                *funcs = "marpaESLIFRecognizer_last_completedb";
  marpaESLIF_t                     *marpaESLIFp;
  marpaWrapperRecognizer_t         *marpaWrapperRecognizerp;
  marpaESLIF_grammar_t             *grammarp;
  genericStack_t                   *set2InputStackp;
  marpaESLIF_symbol_t              *symbolp;
  short                             rcb;
  int                               latestEarleySetIdi;
  int                               earleySetIdi;
  marpaWrapperRecognizerProgress_t *progressp;
  size_t                            nProgressl;
  size_t                            progressl;
  int                               rulei;
  int                               positioni;
  int                               origini;
  int                               firstOrigini;
  int                               lhsRuleStacki;
  genericStack_t                   *lhsRuleStackp;
  short                             lhsRuleStackb;
  marpaESLIF_rule_t                *rulep;
  int                               starti;
  int                               lengthi;
  int                               endi;
  char                             *offsetp;
  size_t                            lengthl;
  GENERICSTACKITEMTYPE2TYPE_ARRAY   array[2];
  char                             *firstStartPositionp;
  char                             *lastStartPositionp;
  size_t                            lastLengthl;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIFp             = marpaESLIFRecognizerp->marpaESLIFp;
  marpaWrapperRecognizerp = marpaESLIFRecognizerp->marpaWrapperRecognizerp;
  if (MARPAESLIF_UNLIKELY(! marpaESLIFRecognizerp->marpaESLIFRecognizerOption.trackb)) {
    /* Is that information available ? */
    MARPAESLIF_ERROR(marpaESLIFp, "Last completion information is available only if recognizer is instanciated with the trackb option on");
    errno = ENOSYS;
    goto err;
  }
  
  grammarp                = marpaESLIFRecognizerp->grammarp;
  set2InputStackp         = marpaESLIFRecognizerp->set2InputStackp;

  if (MARPAESLIF_UNLIKELY(names == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "Symbol name is NULL");
    errno = EINVAL;
    goto err;
  }

  /* First look for this symbol */
  symbolp = _marpaESLIF_symbol_findp(marpaESLIFp, grammarp, names, -1, NULL /* symbolip */, 0 /* silentb */, 0 /* onlyLhsb */, 0 /* onlyRhsb */, MARPAESLIF_SYMBOL_TYPE_META);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "No such symbol <%s>", names);
    goto err;
  }
  lhsRuleStackp = symbolp->lhsRuleStackp;

  if (MARPAESLIF_UNLIKELY(!  marpaWrapperRecognizer_latestb(marpaWrapperRecognizerp, &latestEarleySetIdi))) {
    goto err;
  }
  earleySetIdi = latestEarleySetIdi;

  /* Initialize to one past the end, so we can tell if there were no hits */
  firstOrigini = latestEarleySetIdi + 1;
  while (earleySetIdi >= 0) {
    if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_progressb(marpaWrapperRecognizerp, earleySetIdi, -1, &nProgressl, &progressp))) {
      goto err;
    }
    for (progressl = 0; progressl < nProgressl; progressl++) {
      rulei     = progressp[progressl].rulei;
      positioni = progressp[progressl].positioni;
      origini   = progressp[progressl].earleySetOrigIdi;

      if (positioni != -1) {
        continue;
      }
      lhsRuleStackb = 0;
      for (lhsRuleStacki = 0; lhsRuleStacki < GENERICSTACK_USED(lhsRuleStackp); lhsRuleStacki++) {
        rulep = (marpaESLIF_rule_t *) GENERICSTACK_GET_PTR(lhsRuleStackp, lhsRuleStacki);
        if (rulep->idi == rulei) {
          lhsRuleStackb = 1;
          break;
        }
      }
      if (! lhsRuleStackb) {
        continue;
      }
      if (origini >= firstOrigini) {
        continue;
      }
      firstOrigini = origini;
    }
    if (firstOrigini <= latestEarleySetIdi) {
      break;
    }
    earleySetIdi--;
  }

  if (MARPAESLIF_UNLIKELY(earleySetIdi < 0)) {
    /* Not found */
    MARPAESLIF_ERRORF(marpaESLIFp, "No match for <%s> in input stack", names);
    errno = ENOENT;
    goto err;
  }

  starti  = firstOrigini;
  lengthi = earleySetIdi - firstOrigini;
  endi    = firstOrigini + lengthi - 1;

#ifndef MARPAESLIF_NTRACE
  /* Should never happen */
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_ARRAY(set2InputStackp, starti))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "No entry in set2InputStackp at indice %d", starti);
    goto err;
  }
  if (MARPAESLIF_UNLIKELY(! GENERICSTACK_IS_ARRAY(set2InputStackp, endi))) {
    MARPAESLIF_ERRORF(marpaESLIFp, "No entry in set2InputStackp at indice %d", endi);
    goto err;
  }
#endif

  array[0] = GENERICSTACK_GET_ARRAY(set2InputStackp, starti);
  array[1] = GENERICSTACK_GET_ARRAY(set2InputStackp, endi);

  firstStartPositionp = (char *) GENERICSTACK_ARRAY_PTR(array[0]);
  lastStartPositionp  = (char *) GENERICSTACK_ARRAY_PTR(array[1]);
  lastLengthl         =          GENERICSTACK_ARRAY_LENGTH(array[1]);

  offsetp = (char *) firstStartPositionp;
  lengthl = (size_t) (lastStartPositionp + lastLengthl - firstStartPositionp);

  if (offsetpp != NULL) {
    *offsetpp = offsetp;
  }
  if (lengthlp != NULL) {
    *lengthlp = lengthl;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_hook_discardb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short discardOnOffb)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_hook_discardb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_hook_discardb(marpaESLIFRecognizerp, discardOnOffb);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_hook_discardb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short discardOnOffb)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_hook_discardb";

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Setting marpaESLIFRecognizerp->discardOnOffb to %d", (int) discardOnOffb ? 1 : 0);

  marpaESLIFRecognizerp->discardOnOffb = discardOnOffb ? 1 : 0;

  return 1;
}

/*****************************************************************************/
short marpaESLIFRecognizer_hook_discard_switchb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_hook_discard_switchb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  /* Not allowed unless this is an interactive recognizer */
  if (! MARPAESLIFRECOGNIZER_IS_INTERACTIVE(marpaESLIFRecognizerp)) {
    errno = EPERM;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_hook_discard_switchb(marpaESLIFRecognizerp);
  goto done;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_hook_discard_switchb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_hook_discard_switchb";

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Setting marpaESLIFRecognizerp->discardOnOffb to %d", (int) marpaESLIFRecognizerp->discardOnOffb);

  marpaESLIFRecognizerp->discardOnOffb = marpaESLIFRecognizerp->discardOnOffb ? 0 : 1;

  return 1;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_value_validb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, void *userDatavp, _marpaESLIFRecognizer_valueResultCallback_t callbackp)
/*****************************************************************************/
{
  static const char           *funcs = "_marpaESLIFRecognizer_value_validb";
  short                        rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* We consider that a value produced by us or the integrated Lua do not need to be valid */
  if ((marpaESLIFValueResultp->contextp != NULL)
      &&
      (marpaESLIFValueResultp->contextp != (void *) MARPAESLIF_EMBEDDED_CONTEXT_LUA)
      &&
      ((marpaESLIFValueResultp->contextp < (void *) MARPAESLIF_BOOTSTRAP_STACK_TYPE_NA) || (marpaESLIFValueResultp->contextp > (void *) MARPAESLIF_BOOTSTRAP_STACK_TYPE_ACTION))
      ) {
    if (! __marpaESLIFRecognizer_value_validb(marpaESLIFRecognizerp, marpaESLIFValueResultp)) {
      goto err;
    }
  }

  rcb = (callbackp != NULL) ? callbackp(userDatavp, marpaESLIFValueResultp) : 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/****************************************************************************/
static inline short __marpaESLIFRecognizer_value_validb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/****************************************************************************/
{
  static const char           *funcs      = "__marpaESLIFRecognizer_value_validb";
  genericStack_t              *todoStackp = marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp;
  short                        rcb;
  size_t                       i;
  marpaESLIFValueResult_t     *marpaESLIFValueResultWorkp;
  marpaESLIFValueResult_t     *marpaESLIFValueResultTmpp;
  marpaESLIFValueResultPair_t *marpaESLIFValueResultPairp;
  size_t                       sizel;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  GENERICSTACK_RELAX(todoStackp);

  /* - We want to make sure this is a known type */
  /* - We want to avoid recursion within the _marpaESLIF_generic_action___concatb() method */
  /*   that is working in both lexeme and value modes. */
  /* In any case, the important thing is: */
  /* - an alternative cannot refer to an alternative and so on. */

  /* Initialize the worklist */
  GENERICSTACK_PUSH_PTR(todoStackp, marpaESLIFValueResultp);
  if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
    goto err;
  }

  /* Iterate the worklist */
  while (GENERICSTACK_USED(todoStackp) > 0) {
    marpaESLIFValueResultWorkp = (marpaESLIFValueResult_t *) GENERICSTACK_POP_PTR(todoStackp);

    switch (marpaESLIFValueResultWorkp->type) {
    case MARPAESLIF_VALUE_TYPE_UNDEF:
    case MARPAESLIF_VALUE_TYPE_CHAR:
    case MARPAESLIF_VALUE_TYPE_SHORT:
    case MARPAESLIF_VALUE_TYPE_INT:
    case MARPAESLIF_VALUE_TYPE_LONG:
    case MARPAESLIF_VALUE_TYPE_FLOAT:
    case MARPAESLIF_VALUE_TYPE_DOUBLE:
    case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:
#ifdef MARPAESLIF_HAVE_LONG_LONG
    case MARPAESLIF_VALUE_TYPE_LONG_LONG:
#endif
      break;
    case MARPAESLIF_VALUE_TYPE_PTR:
      if (marpaESLIFValueResultWorkp->u.p.p != NULL) {
        if (MARPAESLIF_UNLIKELY((! marpaESLIFValueResultWorkp->u.p.shallowb) && (marpaESLIFValueResultWorkp->u.p.freeCallbackp == NULL))) {
          MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_PTR: non-shallow pointer is set but free callback is not set");
          errno = EINVAL;
          goto err;
        }
      }
      break;
    case MARPAESLIF_VALUE_TYPE_ARRAY:
      if (marpaESLIFValueResultWorkp->u.a.p != NULL) {
        if (MARPAESLIF_UNLIKELY((! marpaESLIFValueResultWorkp->u.a.shallowb) && (marpaESLIFValueResultWorkp->u.a.freeCallbackp == NULL))) {
          MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_ARRAY: non-shallow pointer is set but free callback is not set");
          errno = EINVAL;
          goto err;
        }
      } else {
        if (marpaESLIFValueResultWorkp->u.a.sizel > 0) {
          /* This is legal only when there is no parent recognizer: sub recognizers uses this illegal value */
          if (MARPAESLIF_UNLIKELY(MARPAESLIFRECOGNIZER_IS_TOP(marpaESLIFRecognizerp))) {
            MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_ARRAY: pointer is not set but array size is set to %ld", (unsigned long) marpaESLIFValueResultWorkp->u.a.sizel);
            errno = EINVAL;
            goto err;
          }
        }
      }
      break;
    case MARPAESLIF_VALUE_TYPE_BOOL:
      break;
    case MARPAESLIF_VALUE_TYPE_STRING:
      /* A string MUST have p and encodingasciis != NULL, even when this is an empty string */
      /* (in which case the caller can allocate a dummy one byte, or return a fixed address) */
      if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultWorkp->u.s.p == NULL)) {
        MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_STRING: pointer is not set");
        errno = EINVAL;
        goto err;
      }
      if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultWorkp->u.s.encodingasciis == NULL)) {
        MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_STRING: encoding is not set");
        errno = EINVAL;
        goto err;
      }
      if (MARPAESLIF_UNLIKELY((! marpaESLIFValueResultWorkp->u.s.shallowb) && (marpaESLIFValueResultWorkp->u.s.freeCallbackp == NULL))) {
        MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_STRING: non-shallow flag is set but free callback is not set");
        errno = EINVAL;
        goto err;
      }
      /* In any case, even for an empty string, encoding must be set */
      break;
    case MARPAESLIF_VALUE_TYPE_ROW:
      if (marpaESLIFValueResultWorkp->u.r.p != NULL) {
        if (MARPAESLIF_UNLIKELY((! marpaESLIFValueResultWorkp->u.r.shallowb) && (marpaESLIFValueResultWorkp->u.r.freeCallbackp == NULL))) {
          MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_ROW: non-shallow pointer is set but free callback is not set");
          errno = EINVAL;
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultWorkp->u.r.sizel <= 0)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_ROW: pointer is set but size is %ld", (unsigned long) marpaESLIFValueResultWorkp->u.r.sizel);
          goto err;
        }
      } else {
        if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultWorkp->u.r.sizel > 0)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_ROW: pointer is not set but size is %ld", (unsigned long) marpaESLIFValueResultWorkp->u.r.sizel);
          goto err;
        }
      }

      if ((sizel = marpaESLIFValueResultWorkp->u.r.sizel) > 0) {
        for (i = 0, marpaESLIFValueResultTmpp = marpaESLIFValueResultWorkp->u.r.p;
             i < sizel;
             i++, marpaESLIFValueResultTmpp++) {
          GENERICSTACK_PUSH_PTR(todoStackp, marpaESLIFValueResultTmpp);
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
            goto err;
          }
        }
      }
      break;
    case MARPAESLIF_VALUE_TYPE_TABLE:
      if (marpaESLIFValueResultWorkp->u.t.p != NULL) {
        if (MARPAESLIF_UNLIKELY((! marpaESLIFValueResultWorkp->u.t.shallowb) && (marpaESLIFValueResultWorkp->u.t.freeCallbackp == NULL))) {
          MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_TABLE: non-shallow pointer is set but free callback is not set");
          errno = EINVAL;
          goto err;
        }
        if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultWorkp->u.t.sizel <= 0)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_TABLE: pointer is set but size is %ld", (unsigned long) marpaESLIFValueResultWorkp->u.t.sizel);
          goto err;
        }
      } else {
        if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultWorkp->u.t.sizel > 0)) {
          MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "MARPAESLIF_VALUE_TYPE_TABLE: pointer is not set but size is %ld", (unsigned long) marpaESLIFValueResultWorkp->u.t.sizel);
          goto err;
        }
      }

      if ((sizel = marpaESLIFValueResultWorkp->u.t.sizel) > 0) {
        for (i = 0, marpaESLIFValueResultPairp = marpaESLIFValueResultWorkp->u.t.p;
             i < sizel;
             i++, marpaESLIFValueResultPairp++) {
          GENERICSTACK_PUSH_PTR(todoStackp, &(marpaESLIFValueResultPairp->key));
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
            goto err;
          }
          GENERICSTACK_PUSH_PTR(todoStackp, &(marpaESLIFValueResultPairp->value));
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(todoStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "todoStackp push failure, %s", strerror(errno));
            goto err;
          }
        }
      }
      break;
    default:
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFValueResultWorkp->type is not supported (got %d, %s)", marpaESLIFValueResultWorkp->type, _marpaESLIF_value_types(marpaESLIFValueResultWorkp->type));
      errno = EINVAL;
      goto err;
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/****************************************************************************/
static inline unsigned long _marpaESLIF_djb2_s(unsigned char *str, size_t lengthl)
/****************************************************************************/
{
  unsigned long hash = 5381;
  int           c;
  size_t        i;

  for (i = 0; i < lengthl; i++) {
    c = *str++;
    hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
  }

  return hash;
}

#if SIZEOF_VOID_STAR <= 4
/****************************************************************************/
static inline int _marpaESLIF_inlined_ptrhashi(void *p)
/****************************************************************************/
{
  /* C.f. https://nullprogram.com/blog/2018/07/31/ */
  marpaESLIF_uint32_t u32 = (marpaESLIF_uint32_t) p;

  u32 ^= u32 >> 16;
  u32 *= 0x7feb352d;
  u32 ^= u32 >> 15;
  u32 *= 0x846ca68b;
  u32 ^= u32 >> 16;

  return (int) (u32 % MARPAESLIF_HASH_SIZE);
}
#else
/****************************************************************************/
static inline int _marpaESLIF_inlined_ptrhashi(void *p)
/****************************************************************************/
{
  /* C.f. https://stackoverflow.com/questions/53110781/whats-the-fastest-portable-way-to-hash-pointers-we-know-are-pointer-aligned-to?noredirect=1&lq=1 */
  marpaESLIF_uint64_t u64 = (marpaESLIF_uint64_t) p;

  u64 ^= (u64 >> 33);
  u64 *= 0xff51afd7ed558ccd;
  u64 ^= (u64 >> 33);
  u64 *= 0xc4ceb9fe1a85ec53;
  u64 ^= (u64 >> 33);

  return (int) (u64 % MARPAESLIF_HASH_SIZE);
}
#endif

/****************************************************************************/
int _marpaESLIF_ptrhashi(void *userDatavp, genericStackItemType_t itemType, void **pp)
/****************************************************************************/
{
  /* We know what we are doing, i.e. that *pp is a void* */
  return _marpaESLIF_inlined_ptrhashi(*pp);
}


/****************************************************************************/
int _marpaESLIF_string_hash_callbacki(void *userDatavp, genericStackItemType_t itemType, void **pp)
/****************************************************************************/
{
  /* We know what we are doing, i.e. that *pp is marpaESLIF_string_t pointer */
  marpaESLIF_string_t *p = * (marpaESLIF_string_t **) pp;
  /* i.e. we can use that array of bytes as if it is a ( char *) - the lexer made sure it ends with a hiden NUL byte */
  return (int) (_marpaESLIF_djb2_s((unsigned char *) p->bytep, p->bytel) % MARPAESLIF_HASH_SIZE);
}

/****************************************************************************/
short _marpaESLIF_string_cmp_callbackb(void *userDatavp, void **pp1, void **pp2)
/****************************************************************************/
{
  marpaESLIF_string_t *p1 = * (marpaESLIF_string_t **) pp1;
  marpaESLIF_string_t *p2 = * (marpaESLIF_string_t **) pp2;

  return _marpaESLIF_string_eqb(p1, p2);
}

/****************************************************************************/
void *_marpaESLIF_string_copy_callbackp(void *userDatavp, void **pp)
/****************************************************************************/
{
  marpaESLIF_t        *marpaESLIFp = (marpaESLIF_t *) userDatavp;
  marpaESLIF_string_t *p           = * (marpaESLIF_string_t **) pp;

  return _marpaESLIF_string_clonep(marpaESLIFp, p);
}

/****************************************************************************/
void _marpaESLIF_string_free_callbackv(void *userDatavp, void **pp)
/****************************************************************************/
{
  marpaESLIF_string_t *p = * (marpaESLIF_string_t **) pp;
  _marpaESLIF_string_freev(p, 0 /* onStstackb */);
}

/****************************************************************************/
static void _marpaESLIFRecognizerHash_free_callbackv(void *userDatavp, void **pp)
/****************************************************************************/
{
  genericStack_t         *marpaESLIFRecognizerStackp = * (genericStack_t **) pp;
  marpaESLIFRecognizer_t *marpaESLIFRecognizerp;

  if (marpaESLIFRecognizerStackp != NULL) {
    while (GENERICSTACK_USED(marpaESLIFRecognizerStackp) > 0) {
      if (GENERICSTACK_IS_PTR(marpaESLIFRecognizerStackp, GENERICSTACK_USED(marpaESLIFRecognizerStackp) - 1)) {
	marpaESLIFRecognizerp = (marpaESLIFRecognizer_t *) GENERICSTACK_POP_PTR(marpaESLIFRecognizerStackp);
        if (marpaESLIFRecognizerp != NULL) {
          /* MARPAESLIF_DEBUGF(marpaESLIFRecognizerp->marpaESLIFp, "Recognizer %p popped from reusable stack of recognizers for grammar %p (length %d)", marpaESLIFRecognizerp, marpaESLIFRecognizerp->marpaWrapperGrammarp, GENERICSTACK_USED(marpaESLIFRecognizerStackp)); */
          _marpaESLIFRecognizer_freev(marpaESLIFRecognizerp, 1 /* forceb */);
        }
      } else {
	GENERICSTACK_USED(marpaESLIFRecognizerStackp)--;
      }
    }
    GENERICSTACK_FREE(marpaESLIFRecognizerStackp);
  }
}

/****************************************************************************/
static void _lexemeGrammarHash_free_callbackv(void *userDatavp, void **pp)
/****************************************************************************/
{
  marpaESLIFGrammar_t *marpaESLIFGrammarp = * (marpaESLIFGrammar_t **) pp;

  _marpaESLIFGrammar_freev(marpaESLIFGrammarp, 0 /* onStackb */);
}

/*****************************************************************************/
static inline void _marpaESLIF_stream_disposev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  marpaESLIF_stream_t *marpaESLIF_streamp;

  if (marpaESLIFRecognizerp != NULL) {
    marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
    if (marpaESLIF_streamp == &(marpaESLIFRecognizerp->_marpaESLIF_stream)) {

      if (marpaESLIF_streamp->buffers != NULL) {
        free(marpaESLIF_streamp->buffers);
      }
      if (marpaESLIF_streamp->bytelefts != NULL) {
        free(marpaESLIF_streamp->bytelefts);
      }
      if (marpaESLIF_streamp->encodings != NULL) {
        free(marpaESLIF_streamp->encodings);
      }
      if (marpaESLIF_streamp->tconvp != NULL) {
        tconv_close(marpaESLIF_streamp->tconvp);
      }
    }
  }
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_freev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short forceb)
/*****************************************************************************/
{
  static const char      *funcs                       = "_marpaESLIFRecognizer_freev";
  marpaESLIFRecognizer_t *marpaESLIFRecognizerParentp = marpaESLIFRecognizerp->marpaESLIFRecognizerParentp;
  marpaESLIF_stream_t    *marpaESLIF_streamp          = marpaESLIFRecognizerp->marpaESLIF_streamp;
  short                  *discardEventStatebp;
  short                  *beforeEventStatebp;
  short                  *afterEventStatebp;
    
  /* We may decide to not free but say we can be reused, unless caller definitely want us to get out */
  if (! forceb) {
    if (_marpaESLIFRecognizer_putPristineToCacheb(marpaESLIFRecognizerp)) {
      return;
    }
  }

  /* This is a normal free -; */
  
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Freeing recognizer %p for grammar %p", marpaESLIFRecognizerp, marpaESLIFRecognizerp->marpaWrapperGrammarp);

  if (marpaESLIFRecognizerp->isExpectedArraybp != NULL) {
    free(marpaESLIFRecognizerp->isExpectedArraybp);
  }
#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Freeing lexeme stack", funcs);
#endif
  _marpaESLIFRecognizer_lexemeStack_freev(marpaESLIFRecognizerp);
#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Freeing alternative stack", funcs);
#endif
  _marpaESLIFRecognizer_alternativeStack_freev(marpaESLIFRecognizerp, marpaESLIFRecognizerp->alternativeStackSymbolp);
#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Freeing commited alternative stack", funcs);
#endif
  GENERICSTACK_RESET(marpaESLIFRecognizerp->commitedAlternativeStackSymbolp); /* Take care, this is a pointer to a stack inside recognizer's structure */
  if (marpaESLIFRecognizerp->marpaESLIFRecognizerOption.trackb) {
    GENERICSTACK_RESET(marpaESLIFRecognizerp->set2InputStackp); /* Take care, this is a pointer to a stack inside recognizer's structure */
  }
  if (marpaESLIFRecognizerp->namesArrayp != NULL) {
    free(marpaESLIFRecognizerp->namesArrayp);
  }
  if (marpaESLIFRecognizerp->marpaWrapperRecognizerp != NULL) {
    marpaWrapperRecognizer_freev(marpaESLIFRecognizerp->marpaWrapperRecognizerp);
  }
  if (marpaESLIFRecognizerp->eventArrayp != NULL) {
    free(marpaESLIFRecognizerp->eventArrayp);
  }

  _marpaESLIFRecognizer_lastPause_freev(marpaESLIFRecognizerp);
  _marpaESLIFRecognizer_lastTry_freev(marpaESLIFRecognizerp);

  discardEventStatebp = marpaESLIFRecognizerp->discardEventStatebp;
  if (discardEventStatebp != NULL) {
    free(discardEventStatebp);
  }

  beforeEventStatebp = marpaESLIFRecognizerp->beforeEventStatebp;
  if (beforeEventStatebp != NULL) {
    free(beforeEventStatebp);
  }

  afterEventStatebp = marpaESLIFRecognizerp->afterEventStatebp;
  if (afterEventStatebp != NULL) {
    free(afterEventStatebp);
  }

  _marpaESLIF_stream_disposev(marpaESLIFRecognizerp);

  if (marpaESLIFRecognizerParentp == NULL) {
    if (marpaESLIFRecognizerp->marpaESLIFRecognizerHashp != NULL) {
      /* This will free all cached recognizers in cascade -; */
      GENERICHASH_RESET(marpaESLIFRecognizerp->marpaESLIFRecognizerHashp, marpaESLIFRecognizerp->marpaESLIFp);
    }
  } else {
    /* Parent's "current" position have to be updated */
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Restoring parent stream from linel=%ld columnl=%ld at {%p,%ld} to linel=%ld columnl=%ld at {%p,%ld}", (unsigned long) marpaESLIFRecognizerp->marpaESLIF_streamp->linel, (unsigned long) marpaESLIFRecognizerp->marpaESLIF_streamp->columnl, marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputs, (unsigned long) marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputl, (unsigned long) marpaESLIFRecognizerp->parentLinel, (unsigned long) marpaESLIFRecognizerp->parentColumnl, marpaESLIFRecognizerParentp->marpaESLIF_streamp->buffers + marpaESLIFRecognizerp->parentDeltal, (unsigned long) (marpaESLIFRecognizerParentp->marpaESLIF_streamp->bufferl - marpaESLIFRecognizerp->parentDeltal));
    marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputs  = marpaESLIFRecognizerParentp->marpaESLIF_streamp->buffers + marpaESLIFRecognizerp->parentDeltal;
    marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputl  = marpaESLIFRecognizerParentp->marpaESLIF_streamp->bufferl - marpaESLIFRecognizerp->parentDeltal;
    marpaESLIFRecognizerParentp->marpaESLIF_streamp->linel   = marpaESLIFRecognizerp->parentLinel;
    marpaESLIFRecognizerParentp->marpaESLIF_streamp->columnl = marpaESLIFRecognizerp->parentColumnl;
  }

  if (marpaESLIFRecognizerp->lastDiscards != NULL) {
    free(marpaESLIFRecognizerp->lastDiscards);
  }

  /* Internal stacks for pointers cleanup */
  if (marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp != NULL) {
    GENERICSTACK_RESET(marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp);
  }
  if (marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp != NULL) {
    GENERICSTACK_RESET(marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp);
  }
  if (marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp != NULL) {
    GENERICSTACK_RESET(marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp);
  }
  _marpaESLIFCalloutBlock_disposev(marpaESLIFRecognizerp);

  if (marpaESLIFRecognizerp->progressp != NULL) {
    free(marpaESLIFRecognizerp->progressp);
  }

  if (marpaESLIFRecognizerp->luaprecompiledp != NULL) {
    free(marpaESLIFRecognizerp->luaprecompiledp);
  }

  _marpaESLIF_action_freev(marpaESLIFRecognizerp->getContextActionp);
  _marpaESLIF_action_freev(marpaESLIFRecognizerp->setContextActionp);
  _marpaESLIF_action_freev(marpaESLIFRecognizerp->popContextActionp);

  _marpaESLIF_lua_recognizer_freev(marpaESLIFRecognizerp);

  GENERICLOGGER_FREE(marpaESLIFRecognizerp->genericLoggerp);

  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "return");
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);

  free(marpaESLIFRecognizerp);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_getPristineFromCachep(marpaESLIF_t *marpaESLIFp, marpaESLIF_grammar_t *grammarp, short discardb, short noEventb, short silentb, marpaESLIFRecognizer_t *marpaESLIFRecognizerParentp, short fakeb, marpaESLIFRecognizer_t **marpaESLIFRecognizerpp, short isLexemeb)
/*****************************************************************************/
{
  static const char      *funcs                 = "_marpaESLIFRecognizer_getPristineFromCachep";
  marpaESLIFRecognizer_t *marpaESLIFRecognizerp = NULL;
  marpaWrapperGrammar_t  *marpaWrapperGrammarp;
  genericHash_t          *marpaESLIFRecognizerHashp;
  genericStack_t         *marpaESLIFRecognizerStackp;
  short                   findResultb;
  short                   rcb;

  /* Why is marpaESLIFRecognizerOptionp not in the parameters ? Because when marpaESLIFRecognizerParentp is != NULL */
  /* marpaESLIF always use the same marpaESLIFRecognizerOptionp: disableThresholdb is 1, and exhaustionEventb is 1. */
  /* genericLoggerp is per def the same as in marpaESLIFp. So *marpaESLIFRecognizerOptionp is a constant. */

  if ((! fakeb) && (marpaESLIFRecognizerParentp != NULL)) {
    if (discardb) {
      marpaWrapperGrammarp = noEventb ? grammarp->marpaWrapperGrammarDiscardNoEventp : grammarp->marpaWrapperGrammarDiscardp;
    } else {
      marpaWrapperGrammarp = noEventb ? grammarp->marpaWrapperGrammarStartNoEventp : grammarp->marpaWrapperGrammarStartp;
    }

    /* Key is marpaWrapperGrammarp, value is a stack of reusable recognizers */
    /* The only problematic reuse of pristine recognizers would be those that are based */
    /* on a grammar that have INITIAL events. But this can happen only once: the very top grammar */
    /* which, by definition, is always used only once for the whole lifetime of the recognizer */
    findResultb = 0;
    marpaESLIFRecognizerHashp = marpaESLIFRecognizerParentp->marpaESLIFRecognizerHashp; /* Owned by the top-level recognizer */
    marpaESLIFRecognizerStackp = NULL;
    GENERICHASH_FIND(marpaESLIFRecognizerHashp,
                     NULL, /* userDatavp */
                     PTR,
                     marpaWrapperGrammarp,
                     PTR,
                     &marpaESLIFRecognizerStackp,
                     findResultb);
#ifndef MARPAESLIF_NTRACE
    if (findResultb && (marpaESLIFRecognizerStackp == NULL)) {
      MARPAESLIF_ERROR(marpaESLIFp, "marpaESLIFRecognizerStackp is NULL");
      goto err;
    }
#endif
    if (findResultb) {
      if (GENERICSTACK_USED(marpaESLIFRecognizerStackp) > 0) {
        marpaESLIFRecognizerp = (marpaESLIFRecognizer_t *) GENERICSTACK_POP_PTR(marpaESLIFRecognizerStackp);
#ifndef MARPAESLIF_NTRACE
        if (findResultb && (marpaESLIFRecognizerp == NULL)) {
          MARPAESLIF_ERROR(marpaESLIFp, "GENERICSTACK_POP_PTR(marpaESLIFRecognizerStackp) returned NULL");
          goto err;
        }
#endif
        /* Re-associate needed members */
        /* marpaESLIFRecognizerp->marpaESLIFp                  = marpaESLIFp; */
        /* marpaESLIFRecognizerp->marpaESLIFRecognizerOption   = *marpaESLIFRecognizerOptionp; */
        /* marpaESLIFRecognizerp->marpaWrapperRecognizerp      = NULL; */
        /* marpaESLIFRecognizerp->marpaWrapperGrammarp         = NULL; */
        marpaESLIFRecognizerp->isLexemeb                       = isLexemeb;
        /* marpaESLIFRecognizerp->lexemeStackp                 = NULL; */
        /* marpaESLIFRecognizerp->eventArrayp                  = NULL; */
        /* marpaESLIFRecognizerp->eventArrayl                  = 0; */
        /* marpaESLIFRecognizerp->eventArraySizel              = 0; */
        marpaESLIFRecognizerp->marpaESLIFRecognizerParentp     = marpaESLIFRecognizerParentp;
        /* marpaESLIFRecognizerp->lastCompletionEvents         = NULL; */
        /* marpaESLIFRecognizerp->lastCompletionSymbolp        = NULL; */
        /* marpaESLIFRecognizerp->lastCompletionEvente         = MARPAESLIF_INTERNAL_EVENT_ACTION_NA; */
        /* marpaESLIFRecognizerp->discardEvents                = NULL; */
        /* marpaESLIFRecognizerp->discardSymbolp               = NULL; */
        /* marpaESLIFRecognizerp->discardEvente                = MARPAESLIF_INTERNAL_EVENT_ACTION_NA; */
        marpaESLIFRecognizerp->resumeCounteri               = 0;
        /* marpaESLIFRecognizerp->callstackCounteri            = 0; */
        /* marpaESLIFRecognizerp->callstackCounterGlobali      = 0; */
        marpaESLIFRecognizerp->leveli                       = marpaESLIFRecognizerParentp->leveli + 1;
        marpaESLIFRecognizerp->marpaESLIFRecognizerHashp    = marpaESLIFRecognizerParentp->marpaESLIFRecognizerHashp;
        marpaESLIFRecognizerp->marpaESLIF_streamp           = marpaESLIFRecognizerParentp->marpaESLIF_streamp;
        marpaESLIFRecognizerp->parentDeltal                 = marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputs - marpaESLIFRecognizerParentp->marpaESLIF_streamp->buffers;
        marpaESLIFRecognizerp->parentLinel                  = marpaESLIFRecognizerParentp->marpaESLIF_streamp->linel;
        marpaESLIFRecognizerp->parentColumnl                = marpaESLIFRecognizerParentp->marpaESLIF_streamp->columnl;
        marpaESLIFRecognizerp->scanb                        = 0;
        /* marpaESLIFRecognizerp->noEventb                     = noEventb; */
        /* marpaESLIFRecognizerp->discardb                     = discardb; */
        marpaESLIFRecognizerp->silentb                      = silentb;
        /* marpaESLIFRecognizerp->haveLexemeb                  = 0; */
        /* These variables are resetted at every _resume_oneb() */
        /* marpaESLIFRecognizerp->completedb                   = 0; */
        /* marpaESLIFRecognizerp->forceExhaustedb                 = 0; */
        /* marpaESLIFRecognizerp->cannotcontinueb                 = 0; */
        /* marpaESLIFRecognizerp->alternativeStackSymbolp         = NULL; */
        /* marpaESLIFRecognizerp->commitedAlternativeStackSymbolp = NULL; */
        /* marpaESLIFRecognizerp->lastPausepp                     = NULL; */
        /* marpaESLIFRecognizerp->lastTrypp                       = NULL; */
        /* marpaESLIFRecognizerp->set2InputStackp                 = NULL; */
        /* marpaESLIFRecognizerp->namesArrayp                     = NULL; */
        /* marpaESLIFRecognizerp->namesArrayAllocl                = 0; */
        /* marpaESLIFRecognizerp->discardEventStatebp             = NULL; */
        /* marpaESLIFRecognizerp->beforeEventStatebp              = NULL; */
        /* marpaESLIFRecognizerp->afterEventStatebp               = NULL; */
        /* marpaESLIFRecognizerp->discardOnOffb                   = 1; */
        /* marpaESLIFRecognizerp->pristineb                       = 1; */
        /* marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard                   = marpaESLIFRecognizerp->marpaESLIFRecognizerOption; */
        /* marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard.disableThresholdb = 1; */
        /* marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard.exhaustedb        = 1; */
        /* marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard.newlineb          = 0; */
        /* marpaESLIFRecognizerp->marpaESLIFRecognizerOptionDiscard.trackb            = 0; */
        /* marpaESLIFRecognizerp->marpaESLIFValueOptionDiscard                        = marpaESLIFValueOption_default_template; */
        /* marpaESLIFRecognizerp->marpaESLIFValueOptionDiscard.userDatavp             = (void *) marpaESLIFRecognizerp; */
        marpaESLIFRecognizerp->last_discard_loopb                  = 0;

        marpaESLIFRecognizerp->marpaESLIFRecognizerTopp            = marpaESLIFRecognizerParentp->marpaESLIFRecognizerTopp;

        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Recognizer %p coming from reusable stack of recognizers for grammar %p (remains %d of them)", marpaESLIFRecognizerp, marpaWrapperGrammarp, GENERICSTACK_USED(marpaESLIFRecognizerStackp));
      }
    }
  }

  *marpaESLIFRecognizerpp = marpaESLIFRecognizerp; /* marpaESLIFRecognizerp may be NULL */
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_getLexemeGrammarFromCachep(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIF_string_t *utf8p, marpaESLIFGrammar_t **marpaESLIFGrammarCachedpp)
/*****************************************************************************/
{
  static const char      *funcs                    = "_marpaESLIFRecognizer_getLexemeGrammarFromCachep";
  marpaESLIFGrammar_t    *marpaESLIFGrammarCachedp = NULL;
  short                   findResultb             = 0;
  short                   rcb;

  /* Key is utf8p, value is marpaESLIFGrammar_t pointer */
  GENERICHASH_FIND(marpaESLIFGrammarp->lexemeGrammarHashp,
                   marpaESLIFGrammarp->marpaESLIFp, /* userDatavp */
                   PTR,
                   utf8p,
                   PTR,
                   &marpaESLIFGrammarCachedp,
                   findResultb);
#ifndef MARPAESLIF_NTRACE
  if (findResultb && (marpaESLIFGrammarCachedp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFGrammarp->marpaESLIFp, "marpaESLIFGrammarp is NULL");
    goto err;
  }
#endif

  *marpaESLIFGrammarCachedpp = marpaESLIFGrammarCachedp;
  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_putPristineToCacheb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char         *funcs                       = "_marpaESLIFRecognizer_putPristineToCacheb";
  marpaESLIFRecognizer_t    *marpaESLIFRecognizerParentp = marpaESLIFRecognizerp->marpaESLIFRecognizerParentp;
  marpaESLIF_stream_t       *marpaESLIF_streamp          = marpaESLIFRecognizerp->marpaESLIF_streamp;
  genericHash_t             *marpaESLIFRecognizerHashp   = marpaESLIFRecognizerp->marpaESLIFRecognizerHashp;
  marpaWrapperGrammar_t     *marpaWrapperGrammarp        = marpaESLIFRecognizerp->marpaWrapperGrammarp;
  genericStack_t            *marpaESLIFRecognizerStackp;
  short                      findResultb;
  short                      rcb;

  if ((marpaESLIFRecognizerParentp != NULL) &&
      (marpaWrapperGrammarp != NULL)        &&
      (marpaESLIFRecognizerHashp != NULL)   &&
      (marpaESLIFRecognizerp->pristineb == 1)) {

    /* Eventually create a stack if nothing yet exist in the hash */
    findResultb = 0;
    marpaESLIFRecognizerStackp = NULL;
    GENERICHASH_FIND(marpaESLIFRecognizerHashp,
                     NULL, /* userDatavp */
                     PTR,
                     marpaWrapperGrammarp,
                     PTR,
                     &marpaESLIFRecognizerStackp,
                     findResultb);
#ifndef MARPAESLIF_NTRACE
    if (MARPAESLIF_UNLIKELY(findResultb && (marpaESLIFRecognizerStackp == NULL))) {
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "findResultb is true but marpaESLIFRecognizerStackp is NULL");
      goto err;
    }
    if (MARPAESLIF_UNLIKELY((! findResultb) && (marpaESLIFRecognizerStackp != NULL))) {
      MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "findResultb is false but marpaESLIFRecognizerStackp is != NULL");
      goto err;
    }
#endif
    if (! findResultb) {
      GENERICSTACK_NEW(marpaESLIFRecognizerStackp);
      if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFRecognizerStackp initialization failure, %s", strerror(errno));
        goto err;
      }
      GENERICHASH_SET(marpaESLIFRecognizerHashp, NULL, PTR, marpaWrapperGrammarp, PTR, marpaESLIFRecognizerStackp);
      if (MARPAESLIF_UNLIKELY(GENERICHASH_ERROR(marpaESLIFRecognizerHashp))) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFRecognizerHashp failure, %s", strerror(errno));
        GENERICSTACK_FREE(marpaESLIFRecognizerStackp);
        goto err;
      }
    }
    /* Here in any the entry in the hash exist and is a generic stack */
    GENERICSTACK_PUSH_PTR(marpaESLIFRecognizerStackp, marpaESLIFRecognizerp);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFRecognizerStackp))) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFRecognizerStackp push failure, %s", strerror(errno));
        goto err;
    }
    /* Before disconnecting from the parent, we update its "current" position */
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Restoring parent stream from {%p,%ld} to {%p,%ld}", marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputs, marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputl, marpaESLIFRecognizerParentp->marpaESLIF_streamp->buffers + marpaESLIFRecognizerp->parentDeltal, marpaESLIFRecognizerParentp->marpaESLIF_streamp->bufferl - marpaESLIFRecognizerp->parentDeltal);
    marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputs  = marpaESLIFRecognizerParentp->marpaESLIF_streamp->buffers + marpaESLIFRecognizerp->parentDeltal;
    marpaESLIFRecognizerParentp->marpaESLIF_streamp->inputl  = marpaESLIFRecognizerParentp->marpaESLIF_streamp->bufferl - marpaESLIFRecognizerp->parentDeltal;
    marpaESLIFRecognizerParentp->marpaESLIF_streamp->linel   = marpaESLIFRecognizerp->parentLinel;
    marpaESLIFRecognizerParentp->marpaESLIF_streamp->columnl = marpaESLIFRecognizerp->parentColumnl;
    /* Now we can disconnect */
    marpaESLIFRecognizerp->marpaESLIFRecognizerParentp = NULL;
    marpaESLIFRecognizerp->marpaESLIF_streamp = NULL;
    /* And do not forget to disconnect also the shallow pointer of recognizer's cache */
    marpaESLIFRecognizerp->marpaESLIFRecognizerHashp = NULL;
    MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Recognizer %p pushed to reusable stack of recognizers for grammar %p (length %d)", marpaESLIFRecognizerp, marpaWrapperGrammarp, GENERICSTACK_USED(marpaESLIFRecognizerStackp));
    rcb = 1;
  } else {
    rcb = 0;
  }

  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_putLexemeGrammarToCacheb(marpaESLIFGrammar_t *marpaESLIFGrammarp, marpaESLIF_string_t *utf8p, marpaESLIFGrammar_t *marpaESLIFGrammarCachedp)
/*****************************************************************************/
{
  short          rcb;

  GENERICHASH_SET(marpaESLIFGrammarp->lexemeGrammarHashp,
                  marpaESLIFGrammarp->marpaESLIFp,
                  PTR,
                  utf8p,
                  PTR,
                  marpaESLIFGrammarCachedp);
  if (MARPAESLIF_UNLIKELY(GENERICHASH_ERROR(marpaESLIFGrammarp->lexemeGrammarHashp))) {
    MARPAESLIF_ERRORF(marpaESLIFGrammarp->marpaESLIFp, "lexemeGrammarHashp set failure, %s", strerror(errno));
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline char *_marpaESLIF_action2asciis(marpaESLIF_action_t *actionp)
/*****************************************************************************/
{
  /* Caller have to make sure we are NEVER called with actionp == NULL */
  switch (actionp->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    return actionp->u.names;
  case MARPAESLIF_ACTION_TYPE_STRING:
    return actionp->u.stringp->asciis;
  case MARPAESLIF_ACTION_TYPE_LUA:
    return actionp->u.luas;
  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    return actionp->u.luaFunction.actions;
  default:
    return (char *) MARPAESLIF_UNKNOWN_STRING;
  }
}

/*****************************************************************************/
static inline short _marpaESLIF_action_validb(marpaESLIF_t *marpaESLIFp, marpaESLIF_action_t *actionp)
/*****************************************************************************/
{
  short rcb;

  if (MARPAESLIF_UNLIKELY(actionp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFp, "action is NULL");
    goto err;
  }

  switch (actionp->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    if (MARPAESLIF_UNLIKELY(actionp->u.names == NULL)) {
      MARPAESLIF_ERROR(marpaESLIFp, "actionp->type is MARPAESLIF_ACTION_TYPE_NAME but actionp->u.names is NULL");
      goto err;    
    }
    break;
  case MARPAESLIF_ACTION_TYPE_STRING:
    /* This is invalid for a free action */
    if (MARPAESLIF_UNLIKELY(actionp->u.stringp == NULL)) {
      MARPAESLIF_ERROR(marpaESLIFp, "actionp->type is MARPAESLIF_ACTION_TYPE_STRING but actionp->u.stringp is NULL");
      goto err;    
    }
    break;
  case MARPAESLIF_ACTION_TYPE_LUA:
    if (MARPAESLIF_UNLIKELY(actionp->u.luas == NULL)) {
      MARPAESLIF_ERROR(marpaESLIFp, "actionp->type is MARPAESLIF_ACTION_TYPE_LUA but actionp->u.luas is NULL");
      goto err;
    }
    break;
  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    if (MARPAESLIF_UNLIKELY(actionp->u.luaFunction.luas == NULL)) {
      MARPAESLIF_ERROR(marpaESLIFp, "actionp->type is MARPAESLIF_ACTION_TYPE_LUA_FUNCTION but actionp->u.luaFunction.luas is NULL");
      goto err;
    }
    if (MARPAESLIF_UNLIKELY(actionp->u.luaFunction.actions == NULL)) {
      MARPAESLIF_ERROR(marpaESLIFp, "actionp->type is MARPAESLIF_ACTION_TYPE_LUA_FUNCTION but actionp->u.luaFunction.actions is NULL");
      goto err;
    }
    /* Only the stripped version is guaranteed to never be NULL */
    if (MARPAESLIF_UNLIKELY(actionp->u.luaFunction.luacstripp == NULL)) {
      MARPAESLIF_ERROR(marpaESLIFp, "actionp->type is MARPAESLIF_ACTION_TYPE_LUA_FUNCTION but actionp->u.luaFunction.luacstripp is NULL");
      goto err;
    }
    break;
  default:
    MARPAESLIF_ERRORF(marpaESLIFp, "Invalid actionp->type %d", actionp->type);
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIF_action_eqb(marpaESLIF_action_t *action1p, marpaESLIF_action_t *action2p)
/*****************************************************************************/
{
  if (action1p == NULL) {
    return (action2p == NULL);
  } else {
    if (action2p == NULL) {
      return 0;
    }
  }

  /* Here both action1p and action2p are != NULL */
  /* Safety check */
  if (action1p->type != action2p->type) {
    return 0;
  }

  /* Here types are equal */
  switch (action1p->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    return (strcmp(action1p->u.names, action2p->u.names) == 0) ? 1 : 0;
  case MARPAESLIF_ACTION_TYPE_STRING:
    return _marpaESLIF_string_utf8_eqb(action1p->u.stringp, action2p->u.stringp);
  case MARPAESLIF_ACTION_TYPE_LUA:
    return (strcmp(action1p->u.luas, action2p->u.luas) == 0) ? 1 : 0;
  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    /* For inline functions, we compare the stripped binary - no check on binary length, it is ok by definition at this stage */
    return
      (
       (action1p->u.luaFunction.luacstripl == action2p->u.luaFunction.luacstripl) &&
       (memcmp(action1p->u.luaFunction.luacstripp, action2p->u.luaFunction.luacstripp, action2p->u.luaFunction.luacstripl) == 0)
       ) ? 1 : 0;
  default:
    return 0;
  }
}

/*****************************************************************************/
static inline marpaESLIF_action_t *_marpaESLIF_action_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIF_action_t *actionp)
/*****************************************************************************/
{
  marpaESLIF_action_t *dup;

  dup = (marpaESLIF_action_t *) malloc(sizeof(marpaESLIF_action_t));
  if (MARPAESLIF_UNLIKELY(dup == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  dup->type = actionp->type;

  switch (dup->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    dup->u.names = strdup(actionp->u.names);
    if (MARPAESLIF_UNLIKELY(dup->u.names == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
    break;
  case MARPAESLIF_ACTION_TYPE_STRING:
    dup->u.stringp = _marpaESLIF_string_clonep(marpaESLIFp, actionp->u.stringp);
    if (MARPAESLIF_UNLIKELY(dup->u.stringp == NULL)) {
      goto err;
    }
    break;
  case MARPAESLIF_ACTION_TYPE_LUA:
    dup->u.luas = strdup(actionp->u.luas);
    if (MARPAESLIF_UNLIKELY(dup->u.luas == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
    break;
  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    dup->u.luaFunction.luas       = NULL;
    dup->u.luaFunction.actions    = NULL;
    dup->u.luaFunction.luacb      = actionp->u.luaFunction.luacb;
    dup->u.luaFunction.luacp      = NULL;
    dup->u.luaFunction.luacl      = 0;
    dup->u.luaFunction.luacstripp = NULL;
    dup->u.luaFunction.luacstripl = 0;

    dup->u.luaFunction.luas = strdup(actionp->u.luaFunction.luas);
    if (MARPAESLIF_UNLIKELY(dup->u.luaFunction.luas == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
    dup->u.luaFunction.actions = strdup(actionp->u.luaFunction.actions);
    if (MARPAESLIF_UNLIKELY(dup->u.luaFunction.actions == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
      goto err;
    }
    if (actionp->u.luaFunction.luacp != NULL) {
      dup->u.luaFunction.luacp = (char *) malloc(actionp->u.luaFunction.luacl);
      if (MARPAESLIF_UNLIKELY(dup->u.luaFunction.luacp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      memcpy(dup->u.luaFunction.luacp, actionp->u.luaFunction.luacp, actionp->u.luaFunction.luacl);
    }
    if (actionp->u.luaFunction.luacstripp != NULL) {
      dup->u.luaFunction.luacstripp = (char *) malloc(actionp->u.luaFunction.luacstripl);
      if (MARPAESLIF_UNLIKELY(dup->u.luaFunction.luacstripp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      memcpy(dup->u.luaFunction.luacstripp, actionp->u.luaFunction.luacstripp, actionp->u.luaFunction.luacstripl);
    }
    break;
  default:
    MARPAESLIF_ERRORF(marpaESLIFp, "Invalid actionp->type %d", actionp->type);
    goto err;    
  }

  goto done;

 err:
  _marpaESLIF_action_freev(dup);
  dup = NULL;

 done:
  return dup;
}

/*****************************************************************************/
static inline void _marpaESLIF_action_freev(marpaESLIF_action_t *actionp)
/*****************************************************************************/
{
  if (actionp != NULL) {
    switch (actionp->type) {
    case MARPAESLIF_ACTION_TYPE_NAME:
      if (actionp->u.names != NULL) {
        free(actionp->u.names);
      }
      break;
    case MARPAESLIF_ACTION_TYPE_STRING:
      _marpaESLIF_string_freev(actionp->u.stringp, 0 /* onStackb */);
      break;
    case MARPAESLIF_ACTION_TYPE_LUA:
      if (actionp->u.luas != NULL) {
        free(actionp->u.luas);
      }
      break;
    case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
      if (actionp->u.luaFunction.luas != NULL) {
        free(actionp->u.luaFunction.luas);
      }
      if (actionp->u.luaFunction.actions != NULL) {
        free(actionp->u.luaFunction.actions);
      }
      if (actionp->u.luaFunction.luacp != NULL) {
        free(actionp->u.luaFunction.luacp);
      }
      if (actionp->u.luaFunction.luacstripp != NULL) {
        free(actionp->u.luaFunction.luacstripp);
      }
      break;
    default:
      break;
    }
    free(actionp);
  }
}

/*****************************************************************************/
static inline short _marpaESLIFValue_ruleActionCallbackb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueRuleCallback_t *ruleCallbackpp, char *asciishows, marpaESLIF_action_t *actionp, marpaESLIF_internal_rule_action_t rule_actione)
/*****************************************************************************/
{
  static const char                   *funcs                 = "_marpaESLIFValue_ruleActionCallbackb";
  marpaESLIFValueRuleActionResolver_t  ruleActionResolverp   = marpaESLIFValuep->marpaESLIFValueOption.ruleActionResolverp;
  marpaESLIFRecognizer_t              *marpaESLIFRecognizerp = marpaESLIFValuep->marpaESLIFRecognizerp;
  marpaESLIF_grammar_t                *grammarp              = marpaESLIFRecognizerp->grammarp;
  marpaESLIFValueRuleCallback_t        ruleCallbackp;
  short                                rcb;

  if (MARPAESLIF_UNLIKELY(actionp == NULL)) {
    /* Still no action ? */
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "At grammar level %d (%s): %s requires: action => action_name, or that your grammar have: :default ::= action => action_name",
                      grammarp->leveli,
                      grammarp->descp->asciis,
                      asciishows);
    goto err;
  }

  switch (actionp->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    {
      /* Action is a normal name */
      char *names;

      marpaESLIFValuep->actions            = actionp->u.names;
      marpaESLIFValuep->actionp            = NULL;
      marpaESLIFValuep->stringp            = NULL;

      /* Get the callback pointer */

      /* If this is a built-in action, we do not need the resolver */
      names = marpaESLIFValuep->actions;
      switch (rule_actione) {
      case MARPAESLIF_INTERNAL_RULE_ACTION___SHIFT:
        ruleCallbackp = _marpaESLIF_rule_action___shiftb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___UNDEF:
        ruleCallbackp = _marpaESLIF_rule_action___undefb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___ASCII:
        ruleCallbackp = _marpaESLIF_rule_action___asciib;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___CONVERT:
        ruleCallbackp = _marpaESLIF_rule_action___convertb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___CONCAT:
        ruleCallbackp = _marpaESLIF_rule_action___concatb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___COPY:
        ruleCallbackp = _marpaESLIF_rule_action___copyb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___TRUE:
        ruleCallbackp = _marpaESLIF_rule_action___trueb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___FALSE:
        ruleCallbackp = _marpaESLIF_rule_action___falseb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___JSON:
        ruleCallbackp = _marpaESLIF_rule_action___jsonb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___JSONF:
        ruleCallbackp = _marpaESLIF_rule_action___jsonfb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___ROW:
        ruleCallbackp = _marpaESLIF_rule_action___rowb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___TABLE:
        ruleCallbackp = _marpaESLIF_rule_action___tableb;
        break;
      case MARPAESLIF_INTERNAL_RULE_ACTION___AST:
        ruleCallbackp = _marpaESLIF_rule_action___astb;
        break;
      default:
        /* Not a built-in: ask to the resolver */
        if (MARPAESLIF_UNLIKELY(ruleActionResolverp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Cannot execute action \"%s\": no rule action resolver", names);
          goto err;
        }
        ruleCallbackp = ruleActionResolverp(marpaESLIFValuep->marpaESLIFValueOption.userDatavp, marpaESLIFValuep, names);
        break;
      }

      if (MARPAESLIF_UNLIKELY(ruleCallbackp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s: action \"%s\" resolved to NULL", asciishows, names);
        goto err;
      } else {
        MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: action \"%s\" resolved to %p", asciishows, names, ruleCallbackp);
      }
    }
    break;

  case MARPAESLIF_ACTION_TYPE_STRING:
    /* String literal: this is a built-in */
    /* Action name is the ASCII best-effort translation */
    ruleCallbackp                        = _marpaESLIF_rule_literal_transferb;
    marpaESLIFValuep->actions            = actionp->u.stringp->asciis;
    marpaESLIFValuep->actionp            = NULL;
    marpaESLIFValuep->stringp            = actionp->u.stringp;
    break;

  case MARPAESLIF_ACTION_TYPE_LUA:
    /* Lua action: this is a built-in */
    ruleCallbackp                        = _marpaESLIF_lua_value_actionb;
    marpaESLIFValuep->actions            = actionp->u.luas;
    marpaESLIFValuep->actionp            = NULL;
    marpaESLIFValuep->stringp            = NULL;
    break;

  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    /* Lua function: this is a built-in */
    ruleCallbackp                        = _marpaESLIF_lua_value_action_functionb;
    marpaESLIFValuep->actions            = actionp->u.luaFunction.luas;
    marpaESLIFValuep->actionp            = actionp;
    marpaESLIFValuep->stringp            = NULL;
    break;

  default:
    MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Invalid action type %d", actionp->type);
    goto err;
  }

  *ruleCallbackpp = ruleCallbackp; /* Never NULL */

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_symbolActionCallbackb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueSymbolCallback_t *symbolCallbackpp, short nullableb, marpaESLIFValueRuleCallback_t *ruleCallbackpp, marpaESLIF_symbol_t *symbolp)
/*****************************************************************************/
{
  /* In case of a nullable a symbol callback can fallback to a rule callback */
  static const char                    *funcs                 = "_marpaESLIFValue_symbolActionCallbackb";
  marpaESLIF_grammar_t                 *grammarp;
  marpaESLIFValueSymbolActionResolver_t symbolActionResolverp;
  marpaESLIFValueSymbolCallback_t       symbolCallbackp;
  marpaESLIFValueRuleCallback_t         ruleCallbackp;
  short                                 rcb;

  if (nullableb) {
    /* This will be in reality a rule callback */
    symbolCallbackp = NULL;
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFValue_ruleActionCallbackb(marpaESLIFValuep, &ruleCallbackp, symbolp->descp->asciis, symbolp->effectiveNullableActionp, symbolp->effectiveNullableActione))) {
      goto err;
    }
  } else {
    /* This will truely be a symbol callback */
    ruleCallbackp   = NULL;
    if (MARPAESLIF_UNLIKELY(symbolp->effectiveSymbolActionp == NULL)) {
      /* Still no action ? */
      grammarp = marpaESLIFValuep->marpaESLIFRecognizerp->grammarp;
      MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "At grammar level %d (%s): %s requires symbol-action => action_name",
                        grammarp->leveli,
                        grammarp->descp->asciis,
                        symbolp->descp->asciis);
      goto err;
    }

    switch (symbolp->effectiveSymbolActionp->type) {
    case MARPAESLIF_ACTION_TYPE_NAME:
      {
        /* Action is a normal name */
        char *names;

        marpaESLIFValuep->actions            = symbolp->effectiveSymbolActionp->u.names;
        marpaESLIFValuep->actionp            = symbolp->effectiveSymbolActionp;
        marpaESLIFValuep->stringp            = NULL;

        /* Get the callback pointer */

        /* If this is a built-in action, we do not need the resolver */
        names = marpaESLIFValuep->actions;
        switch (symbolp->effectiveSymbolActione) {
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___TRANSFER:
          symbolCallbackp = _marpaESLIF_symbol_action___transferb;
          break;
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___UNDEF:
          symbolCallbackp = _marpaESLIF_symbol_action___undefb;
          break;
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___ASCII:
          symbolCallbackp = _marpaESLIF_symbol_action___asciib;
          break;
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___CONVERT:
          symbolCallbackp = _marpaESLIF_symbol_action___convertb;
          break;
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___CONCAT:
          symbolCallbackp = _marpaESLIF_symbol_action___concatb;
          break;
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___TRUE:
          symbolCallbackp = _marpaESLIF_symbol_action___trueb;
          break;
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___FALSE:
          symbolCallbackp = _marpaESLIF_symbol_action___falseb;
          break;
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___JSON:
          symbolCallbackp = _marpaESLIF_symbol_action___jsonb;
          break;
        case MARPAESLIF_INTERNAL_SYMBOL_ACTION___JSONF:
          symbolCallbackp = _marpaESLIF_symbol_action___jsonfb;
          break;
        default:
          /* Not a built-in: ask to the resolver */
          symbolActionResolverp = marpaESLIFValuep->marpaESLIFValueOption.symbolActionResolverp;
          if (MARPAESLIF_UNLIKELY(symbolActionResolverp == NULL)) {
            MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Cannot execute symbol action \"%s\": no symbol action resolver", names);
            goto err;
          }
          symbolCallbackp = symbolActionResolverp(marpaESLIFValuep->marpaESLIFValueOption.userDatavp, marpaESLIFValuep, names);
          break;
        }

        if (MARPAESLIF_UNLIKELY(symbolCallbackp == NULL)) {
          MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "%s: action \"%s\" resolved to NULL", symbolp->descp->asciis, names);
          goto err;
        } else {
          MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFValuep->marpaESLIFRecognizerp, funcs, "%s: action \"%s\" resolved to %p", symbolp->descp->asciis, names, symbolCallbackp);
        }
      }
      break;

    case MARPAESLIF_ACTION_TYPE_STRING:
      /* String literal: this is a built-in */
      /* Action name is the ASCII best-effort translation */
      symbolCallbackp           = _marpaESLIF_symbol_literal_transferb;
      marpaESLIFValuep->actions = symbolp->effectiveSymbolActionp->u.stringp->asciis;
      marpaESLIFValuep->actionp = symbolp->effectiveSymbolActionp;
      marpaESLIFValuep->stringp = symbolp->effectiveSymbolActionp->u.stringp;
      break;

    case MARPAESLIF_ACTION_TYPE_LUA:
      /* Lua action: this is a built-in */
      symbolCallbackp           = _marpaESLIF_lua_value_symbolb;
      marpaESLIFValuep->actions = symbolp->effectiveSymbolActionp->u.luas;
      marpaESLIFValuep->actionp = symbolp->effectiveSymbolActionp;
      marpaESLIFValuep->stringp = NULL;
      break;

    case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
      /* Lua function: this is a built-in */
      symbolCallbackp           = _marpaESLIF_lua_value_symbol_functionb;
      marpaESLIFValuep->actions = symbolp->effectiveSymbolActionp->u.luaFunction.luas;
      marpaESLIFValuep->actionp = symbolp->effectiveSymbolActionp;
      marpaESLIFValuep->stringp = NULL;
      break;

    default:
      MARPAESLIF_ERRORF(marpaESLIFValuep->marpaESLIFp, "Invalid action type %d", symbolp->effectiveSymbolActionp->type);
      goto err;
    }
  }

  *symbolCallbackpp = symbolCallbackp; /* Can be NULL */
  *ruleCallbackpp   = ruleCallbackp;   /* Can be NULL (but both cannot be NULL) */

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_recognizerIfActionCallbackb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *asciishows, marpaESLIF_action_t *ifActionp, marpaESLIFRecognizerIfCallback_t *ifCallbackpp)
/*****************************************************************************/
{
  static const char                      *funcs             = "_marpaESLIFRecognizer_recognizerIfActionCallbackb";
  marpaESLIFRecognizerIfActionResolver_t  ifActionResolverp = marpaESLIFRecognizerp->marpaESLIFRecognizerOption.ifActionResolverp;
  marpaESLIFRecognizerIfCallback_t        ifCallbackp       = NULL;
  char                                   *ifactions;
  short                                   rcb;

  switch (ifActionp->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    /* Action is a normal name */
    ifactions = ifActionp->u.names;
    /* Get the callback pointer */
    if (MARPAESLIF_UNLIKELY(ifActionResolverp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Cannot execute if action \"%s\": no if action resolver", ifactions);
      goto err;
    }
    ifCallbackp = ifActionResolverp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, marpaESLIFRecognizerp, ifactions);
    if (MARPAESLIF_UNLIKELY(ifCallbackp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: action \"%s\" resolved to NULL", asciishows, ifactions);
      goto err;
    } else {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: action \"%s\" resolved to %p", asciishows, ifactions, ifCallbackp);
    }
    marpaESLIFRecognizerp->actionp = ifActionp;
    break;
  case MARPAESLIF_ACTION_TYPE_LUA:
    /* Lua action: this is a built-in */
    ifCallbackp                    = _marpaESLIF_lua_recognizer_ifactionb;
    marpaESLIFRecognizerp->actions = ifActionp->u.luas;
    marpaESLIFRecognizerp->actionp = ifActionp;
    break;
  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    /* Lua inline function: this is a built-in */
    ifCallbackp                    = _marpaESLIF_lua_recognizer_ifaction_functionb;
    marpaESLIFRecognizerp->actions = ifActionp->u.luaFunction.luas;
    marpaESLIFRecognizerp->actionp = ifActionp;
    break;
  default:
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Invalid action type %d", ifActionp->type);
    goto err;
  }

  *ifCallbackpp = ifCallbackp;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_recognizerRegexActionCallbackb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *asciishows, marpaESLIF_action_t *regexActionp, marpaESLIFRecognizerRegexCallback_t *regexCallbackpp)
/*****************************************************************************/
{
  static const char                         *funcs                = "_marpaESLIFRecognizer_recognizerRegexActionCallbackb";
  marpaESLIFRecognizerRegexActionResolver_t  regexActionResolverp = marpaESLIFRecognizerp->marpaESLIFRecognizerOption.regexActionResolverp;
  marpaESLIFRecognizerRegexCallback_t        regexCallbackp       = NULL;
  char                                      *regexactions;
  short                                      rcb;

  switch (regexActionp->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    /* Action is a normal name */
    regexactions = regexActionp->u.names;
    /* Get the callback pointer */
    if (MARPAESLIF_UNLIKELY(regexActionResolverp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Cannot execute regex action \"%s\": no regex action resolver", regexactions);
      goto err;
    }
    regexCallbackp = regexActionResolverp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, marpaESLIFRecognizerp, regexactions);
    if (MARPAESLIF_UNLIKELY(regexCallbackp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: action \"%s\" resolved to NULL", asciishows, regexactions);
      goto err;
    } else {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: action \"%s\" resolved to %p", asciishows, regexactions, regexCallbackp);
    }
    marpaESLIFRecognizerp->actionp = regexActionp;
    break;
  case MARPAESLIF_ACTION_TYPE_LUA:
    /* Lua action: this is a built-in */
    regexCallbackp                 = _marpaESLIF_lua_recognizer_regexactionb;
    marpaESLIFRecognizerp->actions = regexActionp->u.luas;
    marpaESLIFRecognizerp->actionp = regexActionp;
    break;
  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    /* Lua action: this is a built-in */
    regexCallbackp                 = _marpaESLIF_lua_recognizer_regexaction_functionb;
    marpaESLIFRecognizerp->actions = regexActionp->u.luaFunction.luas;
    marpaESLIFRecognizerp->actionp = regexActionp;
    break;
  default:
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Invalid action type %d", regexActionp->type);
    goto err;
  }

  *regexCallbackpp = regexCallbackp;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_recognizerGeneratorActionCallbackb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *asciishows, marpaESLIF_action_t *generatorActionp, marpaESLIFRecognizerGeneratorCallback_t *generatorCallbackpp)
/*****************************************************************************/
{
  static const char                             *funcs                    = "_marpaESLIFRecognizer_recognizerGeneratorActionCallbackb";
  marpaESLIFRecognizerGeneratorActionResolver_t  generatorActionResolverp = marpaESLIFRecognizerp->marpaESLIFRecognizerOption.generatorActionResolverp;
  marpaESLIFRecognizerGeneratorCallback_t        generatorCallbackp       = NULL;
  char                                          *generatoractions;
  short                                          rcb;

  switch (generatorActionp->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    /* Action is a normal name */
    generatoractions = generatorActionp->u.names;
    /* Get the callback pointer */
    if (MARPAESLIF_UNLIKELY(generatorActionResolverp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Cannot execute symbol generator action \"%s\": no symbol generator action resolver", generatoractions);
      goto err;
    }
    generatorCallbackp = generatorActionResolverp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, marpaESLIFRecognizerp, generatoractions);
    if (MARPAESLIF_UNLIKELY(generatorCallbackp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "%s: action \"%s\" resolved to NULL", asciishows, generatoractions);
      goto err;
    } else {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "%s: action \"%s\" resolved to %p", asciishows, generatoractions, generatorCallbackp);
    }
    marpaESLIFRecognizerp->actionp = generatorActionp;
    break;
  case MARPAESLIF_ACTION_TYPE_LUA:
    /* Lua action: this is a built-in */
    generatorCallbackp       = _marpaESLIF_lua_recognizer_generatoractionb;
    marpaESLIFRecognizerp->actions = generatorActionp->u.luas;
    marpaESLIFRecognizerp->actionp = generatorActionp;
    break;
  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    /* Lua action: this is a built-in */
    generatorCallbackp       = _marpaESLIF_lua_recognizer_generatoraction_functionb;
    marpaESLIFRecognizerp->actions = generatorActionp->u.luaFunction.luas;
    marpaESLIFRecognizerp->actionp = generatorActionp;
    break;
  default:
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Invalid action type %d", generatorActionp->type);
    goto err;
  }

  *generatorCallbackpp = generatorCallbackp;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_recognizerEventActionCallbackb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIF_action_t *eventActionp, marpaESLIFRecognizerEventCallback_t *eventCallbackpp)
/*****************************************************************************/
{
  static const char                         *funcs                = "_marpaESLIFRecognizer_recognizerEventActionCallbackb";
  marpaESLIFRecognizerEventActionResolver_t  eventActionResolverp = marpaESLIFRecognizerp->marpaESLIFRecognizerOption.eventActionResolverp;
  marpaESLIFRecognizerEventCallback_t        eventCallbackp       = NULL;
  char                                      *eventactions;
  short                                      rcb;

  switch (eventActionp->type) {
  case MARPAESLIF_ACTION_TYPE_NAME:
    /* Action is a normal name */
    eventactions = eventActionp->u.names;
    /* Get the callback pointer */
    if (MARPAESLIF_UNLIKELY(eventActionResolverp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Cannot execute event action \"%s\": no event action resolver", eventactions);
      goto err;
    }
    eventCallbackp = eventActionResolverp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, marpaESLIFRecognizerp, eventactions);
    if (MARPAESLIF_UNLIKELY(eventCallbackp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Action \"%s\" resolved to NULL", eventactions);
      goto err;
    } else {
      MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "Action \"%s\" resolved to %p", eventactions, eventCallbackp);
    }
    marpaESLIFRecognizerp->actionp = eventActionp;
    break;
  case MARPAESLIF_ACTION_TYPE_LUA:
    /* Lua action: this is a built-in */
    eventCallbackp                 = _marpaESLIF_lua_recognizer_eventactionb;
    marpaESLIFRecognizerp->actions = eventActionp->u.luas;
    marpaESLIFRecognizerp->actionp = eventActionp;
    break;
  case MARPAESLIF_ACTION_TYPE_LUA_FUNCTION:
    /* Lua action: this is a built-in */
    eventCallbackp                 = _marpaESLIF_lua_recognizer_eventaction_functionb;
    marpaESLIFRecognizerp->actions = eventActionp->u.luaFunction.luas;
    marpaESLIFRecognizerp->actionp = eventActionp;
    break;
  default:
    MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "Invalid action type %d", eventActionp->type);
    goto err;
  }

  *eventCallbackpp = eventCallbackp;

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
char *marpaESLIF_charconvp(marpaESLIF_t *marpaESLIFp, char *toEncodings, char *fromEncodings, char *srcs, size_t srcl, size_t *dstlp)
/*****************************************************************************/
{
  return _marpaESLIF_charconvb(marpaESLIFp, toEncodings, fromEncodings, srcs, srcl, dstlp, NULL /* fromEncodingsp */, NULL /* tconvpp */, 1 /* eofb */, NULL /* byteleftsp */, NULL /* byteleftlp */, NULL /* byteleftalloclp */, 0 /* tconvsilentb */, NULL /* defaultEncodings */, NULL /* fallbackEncodings */);
}

/*****************************************************************************/
static inline marpaESLIF_string_t *_marpaESLIF_string2utf8p(marpaESLIF_t *marpaESLIFp, marpaESLIF_string_t *stringp, short tconvsilentb)
/*****************************************************************************/
/* Take care: this method can return stringp */
/*****************************************************************************/
{
  static const char   *funcs = "_marpaESLIF_string2utf8p";
  marpaESLIF_string_t *rcp   = NULL;
  char                *fromencodingasciis;
  int                  utf82ordi;
  char                *maxp;
  char                *p;
  marpaESLIF_uint32_t  codepointi;
  short                utf8b;

  if (MARPAESLIF_UNLIKELY(stringp == NULL)) {
    errno = EINVAL;
    MARPAESLIF_ERRORF(marpaESLIFp, "%s failure, %s", funcs, strerror(errno));
    goto err;
  }

  /* When stringp->encodingasciis is MARPAESLIF_UTF8_STRING this is a string that marpaESLIF generated. */
  /* Then we know it is a valid UTF-8. No need to validate it. */
  if (stringp->encodingasciis == (char *) MARPAESLIF_UTF8_STRING) {
    rcp = stringp;
  } else {
    rcp = (marpaESLIF_string_t *) malloc(sizeof(marpaESLIF_string_t));
    if (MARPAESLIF_UNLIKELY(rcp == NULL)) {
      MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
      goto err;
    }

    if ((stringp->bytep == NULL) || (stringp->bytel <= 0)) {
      /* Empty string */
      rcp->bytep          = (char *) MARPAESLIF_EMPTY_STRING;
      rcp->bytel          = 0;
      rcp->encodingasciis = (char *) MARPAESLIF_UTF8_STRING;
      rcp->asciis         = (char *) MARPAESLIF_EMPTY_STRING;
    } else {
      rcp->bytep          = NULL;
      rcp->bytel          = 0;
      rcp->encodingasciis = NULL;
      rcp->asciis         = NULL;

      /* When there is no encoding, we know that if the buffer is too small charset detection */
      /* can fail. We protect against this case in known situations. */
      fromencodingasciis = stringp->encodingasciis;
      if (fromencodingasciis == NULL) {
        p = stringp->bytep;
        maxp = p + stringp->bytel;
        utf8b = 1;
        while (p < maxp) {
          utf82ordi = _marpaESLIF_utf82ordi((PCRE2_SPTR8) p, &codepointi, (PCRE2_SPTR8) maxp);
          if (utf82ordi <= 0) {
            utf8b = 0;
            break;
          }
          p += utf82ordi;
        }
        if (utf8b) {
          MARPAESLIF_TRACE(marpaESLIFp, funcs, "UTF-8 string detected using byte lookup");
          fromencodingasciis = (char *) MARPAESLIF_UTF8_STRING;
        }
      }

      /* No need of rcp->asciis, this is why we do not use _marpaESLIF_string_newp() */
      if (MARPAESLIF_UNLIKELY((rcp->bytep = _marpaESLIF_charconvb(marpaESLIFp, (char *) MARPAESLIF_UTF8_STRING, fromencodingasciis, stringp->bytep, stringp->bytel, &(rcp->bytel), &(rcp->encodingasciis), NULL /* tconvpp */, 1 /* eofb */, NULL /* byteleftsp */, NULL /* byteleftlp */, NULL /* byteleftalloclp */, tconvsilentb, NULL /* defaultEncodings */, NULL /* fallbackEncodings */)) == NULL)) {
        goto err;
      }

        /* We send the whole data in one go: we ignore the fact that _marpaESLIF_string_removebomb() may return -1 */
      if (MARPAESLIF_UNLIKELY(! _marpaESLIF_string_removebomb(marpaESLIFp, rcp->bytep, &(rcp->bytel), (char *) MARPAESLIF_UTF8_STRING, NULL /* bomsizelp */))) {
        goto err;
      }
    }
  }

  goto done;

 err:
  if ((rcp != NULL) && (rcp != stringp)) {
    _marpaESLIF_string_freev(rcp, 0 /* onStackb */);
    rcp = NULL;
  }

 done:
  return rcp;
}

/*****************************************************************************/
static inline short _marpaESLIF_string_removebomb(marpaESLIF_t *marpaESLIFp, char *bytep, size_t *bytelp, char *encodingasciis, size_t *bomsizelp)
/*****************************************************************************/
/* Take care: it returns -1 if there is no failure BUT not enough bytes */
/*****************************************************************************/
{
  size_t  bytel                = (bytelp != NULL) ? *bytelp : 0;
  size_t  bomsizel             = 0;
  char   *encodingasciitofrees = NULL;
  char   *bytetofreep          = NULL;
  char   *tmpp;
  size_t  encodingasciil;
  short   rcb;

  if ((bytep != NULL) && (bytel > 0)) {
    if (encodingasciis == NULL) {
      /* Guess the encoding by converting to UTF-8 */
      if (MARPAESLIF_UNLIKELY((tmpp = _marpaESLIF_charconvb(marpaESLIFp, (char *) MARPAESLIF_UTF8_STRING /* toEncodings */, NULL /* fromEncodings */, bytep, bytel, NULL /* bytelp */, &(encodingasciitofrees) /* fromEncodingsp */, NULL /* tconvpp */, 1 /* eofb */, NULL /* byteleftsp */, NULL /* byteleftlp */, NULL /* byteleftalloclp */, 0 /* tconvsilentb */, NULL /* defaultEncodings */, NULL /* fallbackEncodings */)) == NULL)) {
	goto err;
      }
      /* Per def here encodingasciitofrees is != NULL */
      encodingasciis = encodingasciitofrees;
      free(tmpp);
    }

    encodingasciil = strlen(encodingasciis);
    if (MARPAESLIF_ENCODING_IS_UTF8(encodingasciis, encodingasciil)) {
      if (bytel >= 3) {
        if (((unsigned char) bytep[0] == (unsigned char) 0xEF) &&
            ((unsigned char) bytep[1] == (unsigned char) 0xBB) &&
            ((unsigned char) bytep[2] == (unsigned char) 0xBF)) {
          bomsizel = 3;
        }
        rcb = 1;
      } else {
        rcb = -1;
      }
    }
    else if (MARPAESLIF_ENCODING_IS_UTF16(encodingasciis, encodingasciil)) {
      if (bytel >= 2) {
        if (((unsigned char) bytep[0] == (unsigned char) 0xFE) &&
            ((unsigned char) bytep[1] == (unsigned char) 0xFF)) {
          bomsizel = 2;
        } else if (((unsigned char) bytep[0] == (unsigned char) 0xFF) &&
                   ((unsigned char) bytep[1] == (unsigned char) 0xFE)) {
          bomsizel = 2;
	}
        rcb = 1;
      } else {
        rcb = -1;
      }
    }
    else if (MARPAESLIF_ENCODING_IS_UTF32(encodingasciis, encodingasciil)) {
      if (bytel >= 4) {
        if (((unsigned char) bytep[0] == (unsigned char) 0x00) &&
            ((unsigned char) bytep[1] == (unsigned char) 0x00) &&
            ((unsigned char) bytep[2] == (unsigned char) 0xFE) &&
            ((unsigned char) bytep[3] == (unsigned char) 0xFF)) {
          bomsizel = 4;
        } else if (((unsigned char) bytep[0] == (unsigned char) 0xFF) &&
                   ((unsigned char) bytep[1] == (unsigned char) 0xFE) &&
                   ((unsigned char) bytep[2] == (unsigned char) 0x00) &&
                   ((unsigned char) bytep[3] == (unsigned char) 0x00)) {
          bomsizel = 4;
        }
        rcb = 1;
      } else {
        rcb = -1;
      }
    } else {
      rcb = 1;
    }
  
    if (bomsizel > 0) {
      memmove(bytep, bytep + bomsizel, bytel - bomsizel + 1); /* +1 for the hiden NUL byte */
      /* Per def bytelp is != NULL here */
      *bytelp -= bomsizel;
    }
  } else {
    rcb = -1;
  }

  if (rcb > 0) {
    if (bomsizelp != NULL) {
      *bomsizelp = bomsizel;
    }
  }
  goto done;

 err:
  rcb = 0;

 done:
  if (encodingasciitofrees != NULL) {
    free(encodingasciitofrees);
  }
  return rcb;
}

/*****************************************************************************/
char *marpaESLIF_encodings(marpaESLIF_t *marpaESLIFp, char *bytep, size_t bytel)
/*****************************************************************************/
{
  static const char   *funcs     = "marpaESLIF_encodings";
  char                *encodings = NULL;
  marpaESLIF_string_t *utf8p     = NULL;
  marpaESLIF_string_t  string;

  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  string.bytep          = bytep;
  string.bytel          = bytel;
  string.encodingasciis = NULL;
  string.asciis         = NULL;

  utf8p = _marpaESLIF_string2utf8p(marpaESLIFp, &string, 1 /* tconvsilentb */);
  if (MARPAESLIF_UNLIKELY(utf8p == NULL)) {
    goto err;
  }

  encodings = strdup(utf8p->encodingasciis);
  if (MARPAESLIF_UNLIKELY(encodings == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
    goto err;
  }

  goto done;

 err:
  if (encodings != NULL) {
    free(encodings);
    encodings = NULL;
  }

 done:
  _marpaESLIF_string_freev(utf8p, 0 /* onStackb */);
  return encodings;
}

/*****************************************************************************/
static inline int _marpaESLIFRecognizer_pointers_tracki(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp, genericStack_t *marpaESLIFValueResultStackp)
/*****************************************************************************/
/* If output is < 0, there is an error, else this is the number of elements. */
/*****************************************************************************/
{
  static const char           *funcs                           = "_marpaESLIFRecognizer_pointers_tracki";
  genericStack_t              *marpaESLIFValueResultWorkStackp = marpaESLIFRecognizerp->marpaESLIFValueResultWorkStackp; /* Work area */
  marpaESLIFValueResult_t     *marpaESLIFValueResultTmpp;
  marpaESLIFValueResult_t     *marpaESLIFValueResultTmp2p;
  marpaESLIFValueResultPair_t *marpaESLIFValueResultPairp;
  marpaESLIFValueType_t        type;
  size_t                       sizel;
  size_t                       rowl;
  size_t                       pairl;
  void                        *p;
  short                        shallowb;
  int                          rci = 0;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* Relax the work stack */
  GENERICSTACK_RELAX(marpaESLIFValueResultWorkStackp);

  /* Relax the output */
  GENERICSTACK_RELAX(marpaESLIFValueResultStackp);

  /* We start with the initial marpaESLIFValueResultp - no need to start with the  */
  /* PUSH because it is immediately followed by a POP.                             */
  marpaESLIFValueResultTmpp = marpaESLIFValueResultp;
  goto innerloop;

  while (GENERICSTACK_USED(marpaESLIFValueResultWorkStackp) > 0) {
    marpaESLIFValueResultTmpp = GENERICSTACK_POP_PTR(marpaESLIFValueResultWorkStackp);

  innerloop:
    switch (type = marpaESLIFValueResultTmpp->type) {
    case MARPAESLIF_VALUE_TYPE_PTR:
    case MARPAESLIF_VALUE_TYPE_ARRAY:
    case MARPAESLIF_VALUE_TYPE_STRING:
    case MARPAESLIF_VALUE_TYPE_ROW:
    case MARPAESLIF_VALUE_TYPE_TABLE:
      if (! (shallowb = MARPAESLIFVALUERESULT_TO_SHALLOWB(marpaESLIFValueResultTmpp))) {
        p = MARPAESLIFVALUERESULT_TO_P(marpaESLIFValueResultTmpp);
      }
      break;
    default:
      shallowb = 1;
      break;
    }

    /* shallowb is not set ? */
    if (shallowb) {
      continue;
    }

    /* It may be non-shallowed but is an empty container */
    if (p == NULL) {
      continue;
    }

    /* Remember it */
    rci++;

#ifdef MARPAESLIF_NOTICE_ACTION
    MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: push %s (inner ptr %p)", funcs, _marpaESLIF_value_types(type), p);
#endif
    GENERICSTACK_PUSH_PTR(marpaESLIFValueResultStackp, marpaESLIFValueResultTmpp);
    if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultStackp))) {
      MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFValueResultStackp push failure, %s", strerror(errno));
      goto err;
    }

    /* Push container content in work area */
    switch (type) {
    case MARPAESLIF_VALUE_TYPE_ROW:
      if ((sizel = marpaESLIFValueResultTmpp->u.r.sizel) > 0) {
        /* We push a copy of the inner elements */
        for (rowl = 0, marpaESLIFValueResultTmp2p = marpaESLIFValueResultTmpp->u.r.p;
             rowl < sizel;
             rowl++, marpaESLIFValueResultTmp2p++) {
          GENERICSTACK_PUSH_PTR(marpaESLIFValueResultWorkStackp, marpaESLIFValueResultTmp2p);
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultWorkStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFValueResultWorkStackp push failure, %s", strerror(errno));
            goto err;
          }
        }
      }
      break;
    case MARPAESLIF_VALUE_TYPE_TABLE:
      if ((sizel = marpaESLIFValueResultTmpp->u.t.sizel) > 0) {
        /* We push a copy of the inner elements */
        for (pairl = 0, marpaESLIFValueResultPairp = marpaESLIFValueResultTmpp->u.t.p;
             pairl < sizel;
             pairl++, marpaESLIFValueResultPairp++) {
          /* Key */
          GENERICSTACK_PUSH_PTR(marpaESLIFValueResultWorkStackp, &(marpaESLIFValueResultPairp->key));
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultWorkStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFValueResultWorkStackp push failure, %s", strerror(errno));
            goto err;
          }
          /* Value */
          GENERICSTACK_PUSH_PTR(marpaESLIFValueResultWorkStackp, &(marpaESLIFValueResultPairp->value));
          if (MARPAESLIF_UNLIKELY(GENERICSTACK_ERROR(marpaESLIFValueResultWorkStackp))) {
            MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "marpaESLIFValueResultWorkStackp push failure, %s", strerror(errno));
            goto err;
          }
        }
      }
      break;
    default:
      break;
    }
  }

  goto done;

 err:
  rci = -1;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", rci);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rci;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_pointers_cleanupb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultOrigp, marpaESLIFValueResult_t *marpaESLIFValueResultNewp)
/*****************************************************************************/
{
  static const char       *funcs                           = "_marpaESLIFRecognizer_pointers_cleanupb";
  genericStack_t          *marpaESLIFValueResultStackOrigp = marpaESLIFRecognizerp->marpaESLIFValueResultStackOrigp;
  genericStack_t          *marpaESLIFValueResultStackNewp;
  marpaESLIFValueResult_t *marpaESLIFValueResultOrigTmpp;
  marpaESLIFValueResult_t *marpaESLIFValueResultNewTmpp;
  void                    *origp;
  void                    *newp;
  int                      origUsedi;
  int                      newUsedi;
  int                      i;
  int                      j;
  short                    foundb;
  short                    rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* No need to track anything if marpaESLIFValueResultOrip does not contain a pointer */
  switch (marpaESLIFValueResultOrigp->type) {
  case MARPAESLIF_VALUE_TYPE_PTR:
  case MARPAESLIF_VALUE_TYPE_ARRAY:
  case MARPAESLIF_VALUE_TYPE_STRING:
  case MARPAESLIF_VALUE_TYPE_ROW:
  case MARPAESLIF_VALUE_TYPE_TABLE:
    break;
  default:
    rcb = 1;
    goto done;
  }

  /* Track non-shallowed old marpaESLIFValueResult */
#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Tracking original non-shallowed pointers", funcs);
#endif
  origUsedi = _marpaESLIFRecognizer_pointers_tracki(marpaESLIFRecognizerp, marpaESLIFValueResultOrigp, marpaESLIFValueResultStackOrigp);
  if (MARPAESLIF_UNLIKELY(origUsedi < 0)) {
    goto err;
  }

  /* Pointless to try to free if there is no non-shallowed pointer in the original marpaESLIFValueResult */
  if (! origUsedi) {
    rcb = 1;
    goto done;
  }

  /* Track non-shallowed new marpaESLIFValueResult */
#ifdef MARPAESLIF_NOTICE_ACTION
  MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Tracking new non-shallowed pointers", funcs);
#endif
  marpaESLIFValueResultStackNewp = marpaESLIFRecognizerp->marpaESLIFValueResultStackNewp;
  newUsedi = _marpaESLIFRecognizer_pointers_tracki(marpaESLIFRecognizerp, marpaESLIFValueResultNewp, marpaESLIFValueResultStackNewp);
  if (MARPAESLIF_UNLIKELY(newUsedi < 0)) {
    goto err;
  }

  /* If no non-shallowed pointer in the new marpaESLIFValueResult, no need to lookup with the array of origin non-shallowed pointers */
  if (! newUsedi) {
    /* Loop on all original non-shallowed pointers. It is VERY important to take the stack in reverse order */
    /* Note that doing a GET is a little more performant than a POP in this case. */
#ifdef MARPAESLIF_NOTICE_ACTION
    MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Freeing %d original pointers", funcs, origUsedi);
#endif
    for (i = --origUsedi; i >= 0; i--) {
      marpaESLIFValueResultOrigTmpp = (marpaESLIFValueResult_t *) GENERICSTACK_GET_PTR(marpaESLIFValueResultStackOrigp, i);
#ifdef MARPAESLIF_NOTICE_ACTION
      origp = MARPAESLIFVALUERESULT_TO_P(marpaESLIFValueResultOrigTmpp);
      MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Freeing original pointer %p hosted by a %s", funcs, origp, _marpaESLIF_value_types(marpaESLIFValueResultOrigTmpp->type));
#endif
      _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, marpaESLIFValueResultOrigTmpp);
    }
  } else {
    /* Same as before, but with a lookup on the new pointers. This is very consuming, the fastest way I found is */
    /* do a sort on the new pointers track first. */
#ifdef MARPAESLIF_NOTICE_ACTION
    MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Sorting %d items from the new value", funcs, newUsedi);
#endif
    MARPAESLIF_QSORT(genericStackItem_t, marpaESLIFValueResultStackNewp->items, marpaESLIFValueResultStackNewp->usedi, _marpaESLIF_cleanup_sort_inlinedi, _marpaESLIF_cleanup_sorti);

    /* j is the indice in the sorted tracked new pointers */
    j = 0;

#ifdef MARPAESLIF_NOTICE_ACTION
    MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Lookup %d original pointers within %d new pointers", funcs, origUsedi, newUsedi);
#endif
    for (i = --origUsedi; i >= 0; i--) {
      marpaESLIFValueResultOrigTmpp = (marpaESLIFValueResult_t *) GENERICSTACK_GET_PTR(marpaESLIFValueResultStackOrigp, i);
      /* By definition the pointer is ok */
      origp = MARPAESLIFVALUERESULT_TO_P(marpaESLIFValueResultOrigTmpp);
#ifdef MARPAESLIF_NOTICE_ACTION
      MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Lookup original pointer %p hosted by a %s within %d remaining new items", funcs, origp, _marpaESLIF_value_types(marpaESLIFValueResultOrigTmpp->type), newUsedi - j);
#endif

      foundb = 0;
      /* Continue traversal of sorted tracked new pointers */
      while (j < newUsedi) {
        marpaESLIFValueResultNewTmpp = (marpaESLIFValueResult_t *) GENERICSTACK_GET_PTR(marpaESLIFValueResultStackNewp, j++);
        newp = MARPAESLIFVALUERESULT_TO_P(marpaESLIFValueResultNewTmpp);
        if (origp == newp) {
#ifdef MARPAESLIF_NOTICE_ACTION
          MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Found original pointer %p hosted by a %s within a new item that is a %s", funcs, origp, _marpaESLIF_value_types(marpaESLIFValueResultOrigTmpp->type), _marpaESLIF_value_types(marpaESLIFValueResultNewTmpp->type));
#endif
          foundb = 1;
          break;
        }
      }

      if (! foundb) {
        /* Not found - this marpaESLIFValueResult can be freed */
#ifdef MARPAESLIF_NOTICE_ACTION
        MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "%s: Freeing original pointer %p hosted by a %s", funcs, origp, _marpaESLIF_value_types(marpaESLIFValueResultOrigTmpp->type));
#endif
        _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, marpaESLIFValueResultOrigTmpp);
      }
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
marpaESLIFGrammar_t *marpaESLIFJSON_decode_newp(marpaESLIF_t *marpaESLIFp, short strictb)
/*****************************************************************************/
{
  marpaESLIFGrammar_t *marpaESLIFGrammarp;

  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  marpaESLIFGrammarp = _marpaESLIFJSON_decode_newp(marpaESLIFp, strictb);
  goto done;

 err:
  marpaESLIFGrammarp = NULL;

 done:
  return marpaESLIFGrammarp;
}

/*****************************************************************************/
marpaESLIFGrammar_t *marpaESLIFJSON_encode_newp(marpaESLIF_t *marpaESLIFp, short strictb)
/*****************************************************************************/
{
  marpaESLIFGrammar_t *marpaESLIFGrammarp;

  if (MARPAESLIF_UNLIKELY(marpaESLIFp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  marpaESLIFGrammarp = _marpaESLIFJSON_encode_newp(marpaESLIFp, strictb);
  goto done;

 err:
  marpaESLIFGrammarp = NULL;

 done:
  return marpaESLIFGrammarp;
}

/*****************************************************************************/
short marpaESLIFValueResult_isinfb(marpaESLIF_t *marpaESLIFp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  short rcb = 0;

  if (marpaESLIFValueResultp != NULL) {
    switch (marpaESLIFValueResultp->type) {
    case MARPAESLIF_VALUE_TYPE_FLOAT:
      rcb = MARPAESLIF_ISINF(marpaESLIFValueResultp->u.f) ? 1 : 0;
      break;
    case MARPAESLIF_VALUE_TYPE_DOUBLE:
      rcb = MARPAESLIF_ISINF(marpaESLIFValueResultp->u.d) ? 1 : 0;
      break;
    case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:
      rcb = MARPAESLIF_ISINF(marpaESLIFValueResultp->u.ld) ? 1 : 0;
      break;
    default:
      break;
    }
  }

  return rcb;
}

/*****************************************************************************/
short marpaESLIFValueResult_isnanb(marpaESLIF_t *marpaESLIFp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  short rcb = 0;

  if (marpaESLIFValueResultp != NULL) {
    switch (marpaESLIFValueResultp->type) {
    case MARPAESLIF_VALUE_TYPE_FLOAT:
      rcb = MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.f) ? 1 : 0;
      break;
    case MARPAESLIF_VALUE_TYPE_DOUBLE:
      rcb = MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.d) ? 1 : 0;
      break;
    case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:
      rcb = MARPAESLIF_ISNAN(marpaESLIFValueResultp->u.ld) ? 1 : 0;
      break;
    default:
      break;
    }
  }

  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFValueResult_is_signed_nanb(marpaESLIF_t *marpaESLIFp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short negativeb, short *confidencebp)
/*****************************************************************************/
{
#ifdef MARPAESLIF_NAN
  float nanf;
#endif

  if (! marpaESLIFValueResult_isnanb(marpaESLIFp, marpaESLIFValueResultp)) {
    return 0;
  }

#ifdef MARPAESLIF_NAN
  /* The only real way to compare is the bit pattern, and indeed we have in marpaESLIFp -; */
  switch (marpaESLIFValueResultp->type) {
  case MARPAESLIF_VALUE_TYPE_FLOAT:
    nanf = marpaESLIFValueResultp->u.f;
    break;
  case MARPAESLIF_VALUE_TYPE_DOUBLE:
    nanf = (float) marpaESLIFValueResultp->u.d;
    break;
  case MARPAESLIF_VALUE_TYPE_LONG_DOUBLE:
    nanf = (float) marpaESLIFValueResultp->u.ld;
    break;
  default:
    /* Should never happen */
    return 0;
  }

  if (confidencebp != NULL) {
    *confidencebp = marpaESLIFp->nanconfidenceb;
  }

  if (negativeb) {
    return (memcmp(&nanf, &(marpaESLIFp->negativenanf) , sizeof(float)) == 0) ? 1 : 0;
  } else {
    return (memcmp(&nanf, &(marpaESLIFp->positivenanf) , sizeof(float)) == 0) ? 1 : 0;
  }
#else
  return 0;
#endif
}

/*****************************************************************************/
short marpaESLIFValueResult_is_positive_nanb(marpaESLIF_t *marpaESLIFp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short *confidencebp)
/*****************************************************************************/
{
  return _marpaESLIFValueResult_is_signed_nanb(marpaESLIFp, marpaESLIFValueResultp, 0 /* negativeb */, confidencebp);
}

/*****************************************************************************/
short marpaESLIFValueResult_is_negative_nanb(marpaESLIF_t *marpaESLIFp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short *confidencebp)
/*****************************************************************************/
{
  return _marpaESLIFValueResult_is_signed_nanb(marpaESLIFp, marpaESLIFValueResultp, 1 /* negativeb */, confidencebp);
}

/*****************************************************************************/
static int _marpaESLIF_pcre2_callouti(pcre2_callout_block *blockp, void *userDatavp)
/*****************************************************************************/
/* Note that since release 10.30 callouts uses an internal ovector, independant */
/* of the one requested by the caller. */
{
  static const char                  *funcs                       = "_marpaESLIF_pcre2_callouti";
  marpaESLIF_pcre2_callout_context_t *contextp                    = (marpaESLIF_pcre2_callout_context_t *) userDatavp;
  marpaESLIFRecognizer_t             *marpaESLIFRecognizerp       = contextp->marpaESLIFRecognizerp;
  marpaESLIF_grammar_t               *grammarp                    = marpaESLIFRecognizerp->grammarp;
  marpaESLIFValueResultPair_t        *marpaESLIFValuePairsp       = marpaESLIFRecognizerp->_marpaESLIFCalloutBlockPairs;
  marpaESLIF_terminal_t              *terminalp                   = contextp->terminalp;
  marpaESLIFAction_t                 *regexActionp                = grammarp->defaultRegexActionp;
  marpaESLIFRecognizerRegexCallback_t regexCallbackp;
  int                                 rci;
  size_t                              offset_vectorl;
  size_t                              i;
  marpaESLIFValueResult_t            *marpaESLIFValueResultOvectorp;
  marpaESLIFValueResultInt_t          marpaESLIFValueResultInt;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  if (MARPAESLIF_UNLIKELY(regexActionp == NULL)) {
    MARPAESLIF_ERROR(marpaESLIFRecognizerp->marpaESLIFp, "No regex default action");
    goto err;
  }

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_recognizerRegexActionCallbackb(marpaESLIFRecognizerp, terminalp->descp->asciis, regexActionp, &regexCallbackp))) {
    goto err;
  }

  /* Create/extend if needed the offset_ovector value */
  /* We know that offset_ovector[2] to offset_ovector[<capture_top>*2-1] can be inspected */
  offset_vectorl = blockp->capture_top * 2;
  if (offset_vectorl > marpaESLIFRecognizerp->_offset_vector_allocl) {
    /* Note that by definition offset_vectorl is > 0 here */
    if (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.type == MARPAESLIF_VALUE_TYPE_UNDEF) {
      /* Creation */
      marpaESLIFValueResultOvectorp = (marpaESLIFValueResult_t *) malloc(offset_vectorl * sizeof(marpaESLIFValueResult_t));
      if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultOvectorp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
    } else {
      /* Extension */
      marpaESLIFValueResultOvectorp = (marpaESLIFValueResult_t *) realloc(marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.u.r.p, offset_vectorl * sizeof(marpaESLIFValueResult_t));
      if (MARPAESLIF_UNLIKELY(marpaESLIFValueResultOvectorp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFRecognizerp->marpaESLIFp, "realloc failure, %s", strerror(errno));
        goto err;
      }
    }
    /* Type will change when we call MARPAESLIFCALLOUTBLOCK_INIT_ROW() just below */
    marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.u.r.p     = marpaESLIFValueResultOvectorp;
    marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.u.r.sizel = offset_vectorl;

    marpaESLIFRecognizerp->_offset_vector_allocl = offset_vectorl;
  } else {
    /* Note that by definition, here, marpaESLIFValueResultOvectorp is never NULL, because PCRE2 always invoke the callout with */
    /* an ovector of at least 2 elements, representing the full match, that are never usable as per the doc btw. */
    marpaESLIFValueResultOvectorp = marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.u.r.p;
  }

  /* Fill every member of the marpaESLIFValueResult that describes the input to regex action */

  if (blockp->callout_string == NULL) {
    MARPAESLIFCALLOUTBLOCK_INIT_LONG  (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_CALLOUT_NUMBER].value, blockp->callout_number);
    MARPAESLIFCALLOUTBLOCK_INIT_UNDEF (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_CALLOUT_STRING].value);
  } else {
    MARPAESLIFCALLOUTBLOCK_INIT_UNDEF (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_CALLOUT_NUMBER].value);
    MARPAESLIFCALLOUTBLOCK_INIT_ARRAY (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_CALLOUT_STRING].value, blockp->callout_string, blockp->callout_string_length);
  }
  /* Note that in fact blockp->subject is stream's inputs, and blockp->subject_length is stream's inputl */
  MARPAESLIFCALLOUTBLOCK_INIT_ARRAY   (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_SUBJECT].value, blockp->subject, blockp->subject_length);
  MARPAESLIFCALLOUTBLOCK_INIT_ARRAY   (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_PATTERN].value, terminalp->patterns, terminalp->patternl);
  MARPAESLIFCALLOUTBLOCK_INIT_LONG    (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_CAPTURE_TOP].value, blockp->capture_top);
  MARPAESLIFCALLOUTBLOCK_INIT_LONG    (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_CAPTURE_LAST].value, blockp->capture_last);
  MARPAESLIFCALLOUTBLOCK_INIT_ROW     (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value, marpaESLIFValueResultOvectorp, offset_vectorl);
  for (i = 0; i < offset_vectorl; i++) {
    MARPAESLIFCALLOUTBLOCK_INIT_LONG  (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.u.r.p[i], blockp->offset_vector[i]);
  }
  if (blockp->mark == NULL) {
    MARPAESLIFCALLOUTBLOCK_INIT_UNDEF (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_MARK].value);
  } else {
    /* As per the doc, mark is a pointer to a zero-terminated string */
    MARPAESLIFCALLOUTBLOCK_INIT_STRING(marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_MARK].value, blockp->mark, strlen((char *) blockp->mark));
  }
  MARPAESLIFCALLOUTBLOCK_INIT_LONG    (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_START_MATCH].value, blockp->start_match);
  MARPAESLIFCALLOUTBLOCK_INIT_LONG (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_CURRENT_POSITION].value, blockp->current_position);
  if (blockp->next_item_length == 0) {
    MARPAESLIFCALLOUTBLOCK_INIT_UNDEF (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_NEXT_ITEM].value);
  } else {
    MARPAESLIFCALLOUTBLOCK_INIT_ARRAY (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_NEXT_ITEM].value, terminalp->patterns + blockp->pattern_position, blockp->next_item_length);
  }
  MARPAESLIFCALLOUTBLOCK_INIT_INT     (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_GRAMMAR_LEVEL].value, grammarp->leveli);
  MARPAESLIFCALLOUTBLOCK_INIT_INT     (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_SYMBOL_ID].value, terminalp->idi);

  /* MARPAESLIF_NOTICEF(marpaESLIFRecognizerp->marpaESLIFp, "... Calling regex callback on terminal: %s", terminalp->descp->asciis); */
  if (MARPAESLIF_UNLIKELY(! regexCallbackp(marpaESLIFRecognizerp->marpaESLIFRecognizerOption.userDatavp, marpaESLIFRecognizerp, marpaESLIFRecognizerp->marpaESLIFCalloutBlockp, &marpaESLIFValueResultInt))) {
    goto err;
  }

  rci = marpaESLIFValueResultInt;
  /* If rci is < 0, the only accepted values are those meaningful from PCRE2 point of view */
  if (rci < PCRE2_ERROR_INTERNAL_DUPMATCH) {
    MARPAESLIF_WARNF(marpaESLIFRecognizerp->marpaESLIFp, "Invalid regex callout return value %d: it cannot be lower than %d, using PCRE2_ERROR_CALLOUT (%d) instead", rci, PCRE2_ERROR_INTERNAL_DUPMATCH, PCRE2_ERROR_CALLOUT);
    rci = PCRE2_ERROR_CALLOUT;
  }
  
  goto done;

 err:
  rci = PCRE2_ERROR_CALLOUT;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", rci);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);

  return rci;
}

/*****************************************************************************/
static int _marpaESLIF_pcre2_callout_enumeratei(pcre2_callout_enumerate_block *blockp, void *userDatavp)
/*****************************************************************************/
{
  static const char                            *funcs    = "_marpaESLIF_pcre2_callout_enumeratei";
  marpaESLIF_pcre2_callout_enumerate_context_t *contextp = (marpaESLIF_pcre2_callout_enumerate_context_t *) userDatavp;
  char                                          tmps[1024];
  char                                         *asciis;

  /* When contextp->marpaESLIFp is NULL, we just set the calloutb flag */
  if (contextp->marpaESLIFp != NULL) {
    if (blockp->callout_string == NULL) {
      /* Numerical callout */
      MARPAESLIF_STRING_CREATESHOW(contextp->asciishowl, contextp->asciishows, "#  Num callout: ");
      sprintf(tmps, "%d", blockp->callout_number);
      MARPAESLIF_STRING_CREATESHOW(contextp->asciishowl, contextp->asciishows, tmps);
    } else {
      /* String callout */
      MARPAESLIF_STRING_CREATESHOW(contextp->asciishowl, contextp->asciishows, "#  Str callout: ");
      asciis = _marpaESLIF_utf82printableascii_newp(contextp->marpaESLIFp, (char *) blockp->callout_string, (size_t) blockp->callout_string_length);
      MARPAESLIF_STRING_CREATESHOW(contextp->asciishowl, contextp->asciishows, asciis);
      _marpaESLIF_utf82printableascii_freev(asciis);
    }
    MARPAESLIF_STRING_CREATESHOW(contextp->asciishowl, contextp->asciishows, "\n");
  }

  /* A way to know that there are callouts in the regexp */
  contextp->calloutb = 1;

  return 0;
}

/*****************************************************************************/
static inline void _marpaESLIFCalloutBlock_initb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  marpaESLIFValueResultPair_t *marpaESLIFValuePairsp = marpaESLIFRecognizerp->_marpaESLIFCalloutBlockPairs;
  int                          i;

  /* Remember current offset_vectorl size */
  marpaESLIFRecognizerp->_offset_vector_allocl = 0;

  for (i = 0; i < _MARPAESLIFCALLOUTBLOCK_SIZE; i++) {
    MARPAESLIFCALLOUTBLOCK_INIT_STRING(marpaESLIFValuePairsp[i].key, marpaESLIFCalloutKeysp[i], strlen(marpaESLIFCalloutKeysp[i]));
    MARPAESLIFCALLOUTBLOCK_INIT_UNDEF (marpaESLIFValuePairsp[i].value);
  }

  marpaESLIFRecognizerp->_marpaESLIFCalloutBlock.contextp           = NULL;
  marpaESLIFRecognizerp->_marpaESLIFCalloutBlock.representationp    = NULL;
  marpaESLIFRecognizerp->_marpaESLIFCalloutBlock.type               = MARPAESLIF_VALUE_TYPE_TABLE;
  marpaESLIFRecognizerp->_marpaESLIFCalloutBlock.u.t.p              = marpaESLIFRecognizerp->_marpaESLIFCalloutBlockPairs;
  marpaESLIFRecognizerp->_marpaESLIFCalloutBlock.u.t.shallowb       = 1;
  marpaESLIFRecognizerp->_marpaESLIFCalloutBlock.u.t.freeUserDatavp = NULL;
  marpaESLIFRecognizerp->_marpaESLIFCalloutBlock.u.t.freeCallbackp  = NULL;
  marpaESLIFRecognizerp->_marpaESLIFCalloutBlock.u.t.sizel          = _MARPAESLIFCALLOUTBLOCK_SIZE;

  marpaESLIFRecognizerp->marpaESLIFCalloutBlockp = &(marpaESLIFRecognizerp->_marpaESLIFCalloutBlock);
}

/*****************************************************************************/
static inline void  _marpaESLIFCalloutBlock_disposev(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  marpaESLIFValueResultPair_t *marpaESLIFValuePairsp;

  if (marpaESLIFRecognizerp->marpaESLIFCalloutBlockp != NULL) {
    /* marpaESLIFRecognizerp was correctly initialized */
    marpaESLIFValuePairsp = marpaESLIFRecognizerp->_marpaESLIFCalloutBlockPairs;

    if (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.type == MARPAESLIF_VALUE_TYPE_ROW) {
      if (marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.u.r.p != NULL) {
        /* This is an array of marpaESLIFValueResult's, all of type LONG */
        free(marpaESLIFValuePairsp[MARPAESLIFCALLOUTBLOCK_OFFSET_VECTOR].value.u.r.p);
      }
    }
  }
}

/*****************************************************************************/
static inline marpaESLIFSymbol_t *_marpaESLIFSymbol_terminal_newp(marpaESLIF_t *marpaESLIFp, marpaESLIF_terminal_type_t terminalType, marpaESLIFString_t *stringp, char *modifiers, marpaESLIFString_t *substitutionStringp, char *substitutionModifiers, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  marpaESLIF_string_t   *utf8p                 = NULL;
  marpaESLIFSymbol_t    *symbolp               = NULL;
  marpaESLIF_terminal_t *terminalp             = NULL;
  marpaESLIF_string_t   *utf8Substitutionp     = NULL;
  marpaESLIF_terminal_t *substitutionTerminalp = NULL;

  utf8p = _marpaESLIF_string2utf8p(marpaESLIFp, stringp, 0 /* tconvsilentb */);
  if (MARPAESLIF_UNLIKELY(utf8p == NULL)) {
    goto err;
  }
  if (substitutionStringp != NULL) {
    utf8Substitutionp = _marpaESLIF_string2utf8p(marpaESLIFp, substitutionStringp, 0 /* tconvsilentb */);
    if (MARPAESLIF_UNLIKELY(utf8Substitutionp == NULL)) {
      goto err;
    }
  }

  symbolp = _marpaESLIF_symbol_newp(marpaESLIFp, marpaESLIFSymbolOptionp);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    goto err;
  }

  terminalp = _marpaESLIF_terminal_newp(marpaESLIFp,
					NULL, /* marpaWrapperGrammarStartp */
					0, /* eventSeti */
					NULL, /* descEncodings */
					NULL, /* descs */
					0, /* descl */
					terminalType,
					modifiers,
					utf8p->bytep,
					utf8p->bytel,
					NULL, /* testFullMatchs */
					NULL, /* testPartialMatchs */
                                        0, /* pseudob */
                                        0, /* characterClassb */
                                        (substitutionStringp != NULL) ? MARPAESLIF_TERMINAL_TYPE_REGEX :  MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                        0 /* substitutionb */);
  if (MARPAESLIF_UNLIKELY(terminalp == NULL)) {
    goto err;
  }

  symbolp->type        = MARPAESLIF_SYMBOL_TYPE_TERMINAL;
  symbolp->u.terminalp = terminalp;
  symbolp->idi         = terminalp->idi;
  symbolp->descp       = terminalp->descp;
  terminalp = NULL; /* It is in symbolp */

  if (substitutionStringp != NULL) {
    /* Overwrite symbol description */
    substitutionTerminalp = _marpaESLIF_terminal_newp(marpaESLIFp,
                                                      NULL, /* marpaWrapperGrammarStartp */
                                                      0, /* eventSeti */
                                                      NULL, /* descEncodings */
                                                      NULL, /* descs */
                                                      0, /* descl */
                                                      MARPAESLIF_TERMINAL_TYPE_STRING,
                                                      substitutionModifiers,
                                                      utf8Substitutionp->bytep,
                                                      utf8Substitutionp->bytel,
                                                      NULL, /* testFullMatchs */
                                                      NULL, /* testPartialMatchs */
                                                      0, /* pseudob */
                                                      0, /* characterClassb */
                                                      MARPAESLIF_TERMINAL_TYPE_NA, /* wantType */
                                                      1 /* substitutionb */);
    if (MARPAESLIF_UNLIKELY(substitutionTerminalp == NULL)) {
      goto err;
    }

    symbolp->descp = _marpaESLIF_terminal_add_substitution_desc_to_terminal_descp(marpaESLIFp, symbolp->u.terminalp, substitutionTerminalp);
    if (symbolp->descp == NULL) {
      goto err;
    }

    /* Transfer substitution information from substitutionTerminalp to symbolp->u.terminalp */
    symbolp->u.terminalp->substitutionUtf8s     = substitutionTerminalp->utf8s;
    symbolp->u.terminalp->substitutionUtf8l     = substitutionTerminalp->utf8l;
    symbolp->u.terminalp->substitutionModifiers = substitutionTerminalp->modifiers;
    symbolp->u.terminalp->substitutionPatterns  = substitutionTerminalp->patterns;
    symbolp->u.terminalp->substitutionPatternl  = substitutionTerminalp->patternl;
    symbolp->u.terminalp->substitutionPatterni  = substitutionTerminalp->patterni;

    substitutionTerminalp->utf8s     = NULL; /* it is now in terminalp */
    substitutionTerminalp->modifiers = NULL; /* it is now in terminalp */
    substitutionTerminalp->patterns  = NULL; /* it is now in terminalp */
  }

  goto done;

 err:
  marpaESLIFSymbol_freev(symbolp);
  symbolp = NULL;

 done:
  if (utf8p != stringp) {
    _marpaESLIF_string_freev(utf8p, 0 /* onStackb */); /* NULL aware */
  }
  if (utf8Substitutionp != substitutionStringp) {
    _marpaESLIF_string_freev(utf8Substitutionp, 0 /* onStackb */); /* NULL aware */
  }
  _marpaESLIF_terminal_freev(terminalp);
  _marpaESLIF_terminal_freev(substitutionTerminalp);

  return symbolp;
}

/*****************************************************************************/
static inline marpaESLIFSymbol_t *__marpaESLIFSymbol_meta_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp, char *symbols, int leveli, marpaESLIFString_t *descp, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  marpaESLIFSymbol_t   *symbolp   = NULL;
  marpaESLIF_grammar_t *grammarp;
  marpaESLIF_symbol_t  *foundSymbolp;

  grammarp = _marpaESLIFGrammar_grammar_findp(marpaESLIFGrammarp, leveli, descp);
  if (MARPAESLIF_UNLIKELY(grammarp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  /* We look for this symbol, it must be a lexeme */
  foundSymbolp = _marpaESLIF_symbol_findp(marpaESLIFGrammarp->marpaESLIFp, grammarp, symbols, -1 /* symboli */, NULL /* symbolip */, 0 /* silentb */, 0 /* onlyLhsb */, 1 /* onlyRhsb */, MARPAESLIF_SYMBOL_TYPE_META);
  if (MARPAESLIF_UNLIKELY(foundSymbolp == NULL)) {
    errno = EINVAL;
    goto err;
  }

  /* A lexeme is always a meta */
  if (foundSymbolp->type != MARPAESLIF_SYMBOL_TYPE_META) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Symbol <%s> must be a lexeme but is not a meta symbol", symbols);
    goto err;
  }

  /* We just duplicate symbol and mark it as a duplicate of another - this is used in _marpaESLIF_symbol_freev() */
  symbolp = (marpaESLIF_symbol_t *) malloc(sizeof(marpaESLIF_symbol_t));
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    goto err;
  }

  *symbolp = *foundSymbolp;

  symbolp->contentIsShallowb = 1;
  symbolp->marpaESLIFSymbolOption = marpaESLIFSymbolOptionp != NULL ? *marpaESLIFSymbolOptionp : marpaESLIFSymbolOption_default_template;
  symbolp->marpaESLIFGrammarp = marpaESLIFGrammarp;

  goto done;

 err:
  marpaESLIFSymbol_freev(symbolp);
  symbolp = NULL;

 done:
  return symbolp;
}

/*****************************************************************************/
marpaESLIFSymbol_t *marpaESLIFSymbol_string_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFString_t *stringp, char *modifiers, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY((marpaESLIFp == NULL) || (stringp == NULL))) {
    errno = EINVAL;
    return NULL;
  }

  return _marpaESLIFSymbol_string_newp(marpaESLIFp, stringp, modifiers, marpaESLIFSymbolOptionp);
}

/*****************************************************************************/
static inline marpaESLIF_symbol_t *_marpaESLIFSymbol_string_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFString_t *stringp, char *modifiers, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  return _marpaESLIFSymbol_terminal_newp(marpaESLIFp, MARPAESLIF_TERMINAL_TYPE_STRING, stringp, modifiers, NULL /* substitutionStringp */, NULL /* substitutionModifiers */, marpaESLIFSymbolOptionp);
}

/*****************************************************************************/
marpaESLIFSymbol_t *marpaESLIFSymbol_regex_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFString_t *stringp, char *modifiers, marpaESLIFString_t *substitutionStringp, char *substitutionModifiers, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY((marpaESLIFp == NULL) || (stringp == NULL))) {
    errno = EINVAL;
    return NULL;
  }

  return _marpaESLIFSymbol_regex_newp(marpaESLIFp, stringp, modifiers, substitutionStringp, substitutionModifiers, marpaESLIFSymbolOptionp);
}

/*****************************************************************************/
static inline marpaESLIF_symbol_t *_marpaESLIFSymbol_regex_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFString_t *stringp, char *modifiers, marpaESLIFString_t *substitutionStringp, char *substitutionModifiers, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  return _marpaESLIFSymbol_terminal_newp(marpaESLIFp, MARPAESLIF_TERMINAL_TYPE_REGEX, stringp, modifiers, substitutionStringp, substitutionModifiers, marpaESLIFSymbolOptionp);
}

/*****************************************************************************/
marpaESLIFSymbol_t *marpaESLIFSymbol_meta_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp, char *symbols, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY((marpaESLIFp == NULL) || (marpaESLIFGrammarp == NULL) || (symbols == NULL))) {
    errno = EINVAL;
    return NULL;
  }

  return _marpaESLIFSymbol_meta_newp(marpaESLIFp, marpaESLIFGrammarp, symbols, marpaESLIFSymbolOptionp);
}

/*****************************************************************************/
static inline marpaESLIF_symbol_t *_marpaESLIFSymbol_meta_newp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp, char *symbols, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  return __marpaESLIFSymbol_meta_newp(marpaESLIFp, marpaESLIFGrammarp, symbols, 0 /* leveli */, NULL /* descp */, marpaESLIFSymbolOptionp);
}

/*****************************************************************************/
marpaESLIFSymbol_t *marpaESLIFSymbol_meta_new_by_levelp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp, char *symbols, int leveli, marpaESLIFString_t *descp, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY((marpaESLIFp == NULL) || (marpaESLIFGrammarp == NULL) || (symbols == NULL))) {
    errno = EINVAL;
    return NULL;
  }

  return _marpaESLIFSymbol_meta_new_by_levelp(marpaESLIFp, marpaESLIFGrammarp, symbols, leveli, descp, marpaESLIFSymbolOptionp);
}

/*****************************************************************************/
static inline marpaESLIF_symbol_t *_marpaESLIFSymbol_meta_new_by_levelp(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *marpaESLIFGrammarp, char *symbols, int leveli, marpaESLIFString_t *descp, marpaESLIFSymbolOption_t *marpaESLIFSymbolOptionp)
/*****************************************************************************/
{
  return __marpaESLIFSymbol_meta_newp(marpaESLIFp, marpaESLIFGrammarp, symbols, leveli, descp, marpaESLIFSymbolOptionp);
}

/*****************************************************************************/
marpaESLIF_t *marpaESLIFSymbol_eslifp(marpaESLIFSymbol_t *marpaESLIFSymbolp)
/*****************************************************************************/
{
  if (MARPAESLIF_UNLIKELY(marpaESLIFSymbolp == NULL)) {
    errno = EINVAL;
    return NULL;
  }

  return marpaESLIFSymbolp->marpaESLIFp;
}

/*****************************************************************************/
short marpaESLIFSymbol_tryb(marpaESLIFSymbol_t *marpaESLIFSymbolp, char *inputs, size_t inputl, short *matchbp)
/*****************************************************************************/
{
  short                         rcb;

  if (MARPAESLIF_UNLIKELY((marpaESLIFSymbolp == NULL) || (inputs == NULL) || (inputl <= 0))) {
    errno = EINVAL;
    goto err;
  }

  rcb = _marpaESLIFSymbol_tryb(marpaESLIFSymbolp, inputs, inputl, matchbp);
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFSymbol_tryb(marpaESLIFSymbol_t *marpaESLIFSymbolp, char *inputs, size_t inputl, short *matchbp)
/*****************************************************************************/
{
  /* This is almost like _marpaESLIFRecognizer_symbol_tryb: we fake a recognizer on a complete fake stream */
  /* We just have to take of the import: we inherit symbol's import parameters.                           */
  marpaESLIFRecognizer_t       *marpaESLIFRecognizerp      = NULL;
  marpaESLIFRecognizerOption_t  marpaESLIFRecognizerOption = marpaESLIFRecognizerOption_default_template;
  marpaESLIF_grammar_t         *grammarp;
  marpaESLIF_stream_t          *marpaESLIF_streamp;
  short                         rcb;

  if (marpaESLIFSymbolp->marpaESLIFGrammarp != NULL) {
    /* Case of meta symbol only */
    grammarp = marpaESLIFSymbolp->marpaESLIFGrammarp->grammarp;
  } else {
    grammarp = NULL;
  }

  /* Fake a recognizer. EOF flag will be set automatically in fake mode */
  marpaESLIFRecognizerp = __marpaESLIFRecognizer_newp(marpaESLIFSymbolp->marpaESLIFp,
                                                      grammarp,
                                                      &marpaESLIFRecognizerOption,
                                                      0, /* discardb - not used anyway because we are in fake mode */
                                                      1, /* noEventb - not used anyway because we are in fake mode */
                                                      1, /* silentb */
                                                      NULL, /* marpaESLIFRecognizerParentp */
                                                      1, /* fakeb */
                                                      0, /* maxStartCompletionsi */
                                                      0, /* Already validated UTF-8 string ? */
                                                      0 /* isLexemeb */);
  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    goto err;
  }

  marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  marpaESLIF_streamp->inputs = inputs;
  marpaESLIF_streamp->inputl = inputl;
  marpaESLIF_streamp->eofb   = 1;

  rcb = __marpaESLIFRecognizer_symbol_tryb(marpaESLIFRecognizerp, marpaESLIFSymbolp, matchbp);
  goto done;

 err:
  rcb = 0;

 done:
  if (marpaESLIFRecognizerp != NULL) {
    _marpaESLIFRecognizer_freev(marpaESLIFRecognizerp, 1 /* forceb */);
  }
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_symbol_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFSymbol_t *marpaESLIFSymbolp, short *matchbp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_symbol_tryb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY((marpaESLIFRecognizerp == NULL) || (marpaESLIFSymbolp == NULL))) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_symbol_tryb(marpaESLIFRecognizerp, marpaESLIFSymbolp, matchbp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_symbol_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFSymbol_t *marpaESLIFSymbolp, short *matchbp)
/*****************************************************************************/
{
  return __marpaESLIFRecognizer_symbol_tryb(marpaESLIFRecognizerp, marpaESLIFSymbolp, matchbp);
}

/*****************************************************************************/
void marpaESLIFSymbol_freev(marpaESLIFSymbol_t *marpaESLIFSymbolp)
/*****************************************************************************/
{
  _marpaESLIF_symbol_freev(marpaESLIFSymbolp);
}

#ifdef MARPAESLIF_NAN
/*****************************************************************************/
static inline void _marpaESLIF_guessNanv(marpaESLIF_t *marpaESLIFp)
/*****************************************************************************/
{
  float  nanf                   = MARPAESLIF_NAN;
  float  positivef              = 1.0;
  float  negativef              = -1.0;
  double nand                   = MARPAESLIF_NAN;
  double positived              = 1.0;
  double negatived              = -1.0;

#ifdef C_COPYSIGNF
  marpaESLIFp->positivenanf                               = C_COPYSIGNF(nanf, positivef);
  marpaESLIFp->negativenanf                               = C_COPYSIGNF(nanf, negativef);
  marpaESLIFp->nanconfidenceb                             = 1;
#else /* C_COPYSIGNF */
#  ifdef C_COPYSIGN
  marpaESLIFp->positivenanf                               = (float) C_COPYSIGN(nand, positived);
  marpaESLIFp->negativenanf                               = (float) C_COPYSIGN(nanf, negatived);
  marpaESLIFp->nanconfidenceb                             = 1;
#  else /* C_COPYSIGN */
  /* Bad luck. We can only cross fingers.                                                    */
  marpaESLIFp->positivenanf                               = MARPAESLIF_NAN;
  marpaESLIFp->negativenanf                               = -MARPAESLIF_NAN;
  marpaESLIFp->nanconfidenceb                             = 0;
#  endif /* C_COPYSIGN */
#endif /* C_COPYSIGNF */
}
#endif /* MARPAESLIF_NAN */

/*****************************************************************************/
short marpaESLIFRecognizer_progressb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, int starti, int endi, size_t *progresslp, marpaESLIFRecognizerProgress_t **progresspp)
/*****************************************************************************/
{
  static const char                *funcs = "marpaESLIFRecognizer_progressb";
  short                             rcb;
  marpaESLIF_t                     *marpaESLIFp;
  marpaWrapperRecognizer_t         *marpaWrapperRecognizerp;
  size_t                            marpaWrapperRecognizerProgressl;
  marpaWrapperRecognizerProgress_t *marpaWrapperRecognizerProgressp;
  size_t                            marpaESLIFRecognizerProgressl;
  marpaESLIFRecognizerProgress_t   *marpaESLIFRecognizerProgressp;
  size_t                            progressl;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  marpaESLIFp             = marpaESLIFRecognizerp->marpaESLIFp;
  marpaWrapperRecognizerp = marpaESLIFRecognizerp->marpaWrapperRecognizerp;

  if (MARPAESLIF_UNLIKELY(! marpaWrapperRecognizer_progressb(marpaWrapperRecognizerp, starti, endi, &marpaWrapperRecognizerProgressl, &marpaWrapperRecognizerProgressp))) {
    goto err;
  }

  marpaESLIFRecognizerProgressl = marpaWrapperRecognizerProgressl;

  if (marpaESLIFRecognizerProgressl > 0) {
    /* Make sure we have enough storage */
    if (marpaESLIFRecognizerp->progressallocl == 0) {
      marpaESLIFRecognizerProgressp = (marpaESLIFRecognizerProgress_t *) malloc(sizeof(marpaESLIFRecognizerProgress_t) * marpaESLIFRecognizerProgressl);
      if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerProgressp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      marpaESLIFRecognizerp->progressallocl = marpaESLIFRecognizerProgressl;
      marpaESLIFRecognizerp->progressp      = marpaESLIFRecognizerProgressp;
    } else if (marpaESLIFRecognizerProgressl > marpaESLIFRecognizerp->progressallocl) {
      marpaESLIFRecognizerProgressp = (marpaESLIFRecognizerProgress_t *) realloc(marpaESLIFRecognizerp->progressp, sizeof(marpaESLIFRecognizerProgress_t) * marpaESLIFRecognizerProgressl);
      if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerProgressp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "realloc failure, %s", strerror(errno));
        goto err;
      }
      marpaESLIFRecognizerp->progressallocl = marpaESLIFRecognizerProgressl;
      marpaESLIFRecognizerp->progressp      = marpaESLIFRecognizerProgressp;
    } else {
      marpaESLIFRecognizerProgressp = marpaESLIFRecognizerp->progressp;
    }

    for (progressl = 0; progressl < marpaESLIFRecognizerProgressl; progressl++) {
      marpaESLIFRecognizerProgressp[progressl].earleySetIdi     = marpaWrapperRecognizerProgressp[progressl].earleySetIdi;
      marpaESLIFRecognizerProgressp[progressl].earleySetOrigIdi = marpaWrapperRecognizerProgressp[progressl].earleySetOrigIdi;
      marpaESLIFRecognizerProgressp[progressl].rulei            = marpaWrapperRecognizerProgressp[progressl].rulei;
      marpaESLIFRecognizerProgressp[progressl].positioni        = marpaWrapperRecognizerProgressp[progressl].positioni;
    }
  }

  if (progresslp != NULL) {
    *progresslp = marpaESLIFRecognizerProgressl;
  }
  if (progresspp != NULL) {
    *progresspp = marpaESLIFRecognizerProgressp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIF_transfer_grammarb(marpaESLIF_t *marpaESLIFp, marpaESLIFGrammar_t *dstp, int dsti, marpaESLIFGrammar_t *srcp, int srci)
/*****************************************************************************/
/* This (dangerous...) method will transfer grammar srcp[srci] to dstp[dsti] */
/* Prior to the transfer:                                                    */
/* - grammar srcp[srci] must exist                                           */
/* - grammar dstp[dsti] must not exist                                       */
/*****************************************************************************/
{
  marpaESLIF_grammar_t *grammar_srcp;
  marpaESLIF_grammar_t *grammar_dstp;
  short                 rcb;

  grammar_srcp = _marpaESLIFGrammar_grammar_findp(srcp, srci, NULL);
  if (MARPAESLIF_UNLIKELY(grammar_srcp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Source grammar at level %d does not exist", srci);
    goto err;
  }

  grammar_dstp = _marpaESLIFGrammar_grammar_findp(dstp, dsti, NULL);
  if (MARPAESLIF_UNLIKELY(grammar_dstp != NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Destination grammar at level %d already exist", dsti);
    goto err;
  }

  /* The risk of having an error at this stage is minimal - if there is, we will have a memory leak at most */

  /* Remove the src grammar for the src grammar stack */
  GENERICSTACK_SET_NA(srcp->grammarStackp, srci);
  if (GENERICSTACK_ERROR(srcp->grammarStackp)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "GENERICSTACK_SET_NA failure, %s", strerror(errno));
    goto err;
  }

  /* Move src grammar to dst grammar stack */
  GENERICSTACK_SET_PTR(dstp->grammarStackp, grammar_srcp, dsti);
  if (GENERICSTACK_ERROR(dstp->grammarStackp)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "GENERICSTACK_SET_PTR failure, %s", strerror(errno));
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline void _marpaESLIFRecognizer_errorv(marpaESLIFRecognizer_t *marpaESLIFRecognizerp)
/*****************************************************************************/
{
  static const char    *funcs              = "_marpaESLIFRecognizer_errorv";
  marpaESLIF_t         *marpaESLIFp        = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIF_grammar_t *grammarp           = marpaESLIFRecognizerp->grammarp;
  marpaESLIF_stream_t  *marpaESLIF_streamp = marpaESLIFRecognizerp->marpaESLIF_streamp;
  size_t                nTerminall;
  int                  *symbolIdArrayp;
  marpaESLIF_symbol_t **symbolArraypp;
  size_t                symboll;
  marpaESLIF_symbol_t  *symbolp;
  char                 *dumps;
  size_t                dumpl;
  
  MARPAESLIF_ERROR(marpaESLIFp, "");
  MARPAESLIF_ERROR(marpaESLIFp, "--------------------------------------------");
  MARPAESLIF_ERRORF(marpaESLIFp, "Recognizer progress (grammar level %d (%s)):", grammarp->leveli, grammarp->descp->asciis);
  marpaESLIFRecognizer_progressLogb(marpaESLIFRecognizerp, -1, -1, GENERICLOGGER_LOGLEVEL_ERROR);
  /* Ask for expected grammar terminals */
  if (MARPAESLIF_LIKELY(_marpaESLIFRecognizer_expectedTerminalsb(marpaESLIFRecognizerp, &nTerminall, &symbolIdArrayp, &symbolArraypp))) {
    if (nTerminall > 0) {
      MARPAESLIF_ERROR(marpaESLIFp, "");
      for (symboll = 0; symboll < nTerminall; symboll++) {
        symbolp = symbolArraypp[symboll];
        MARPAESLIF_ERRORF(marpaESLIFp, "Expected symbol: %s (symbol No %d)", _marpaESLIFGrammar_symbolDescriptionCallbacks(grammarp, symbolp->idi), symbolp->idi);
      }
    }
  }

  /* If there is some information before, show it */
  if ((marpaESLIF_streamp->inputs != NULL) && (marpaESLIF_streamp->buffers != NULL) && (marpaESLIF_streamp->inputs > marpaESLIF_streamp->buffers)) {
    if ((marpaESLIF_streamp->inputs - marpaESLIF_streamp->buffers) > 128) {
      dumps = marpaESLIF_streamp->inputs - 128;
      dumpl = 128;
    } else {
      dumps = marpaESLIF_streamp->buffers;
      dumpl = marpaESLIF_streamp->inputs - marpaESLIF_streamp->buffers;
    }
    MARPAESLIF_ERROR(marpaESLIFp, "");
    MARPAESLIFRECOGNIZER_HEXDUMPV(funcs,
                                  marpaESLIFRecognizerp,
                                  "",
                                  marpaESLIF_streamp->utfb ? "UTF-8 converted data before the failure" : "Raw data before the failure",
                                  dumps,
                                  dumpl,
                                  0, /* traceb */
                                  0, /* noticeb */
                                  marpaESLIF_streamp->linel,
                                  marpaESLIF_streamp->columnl);
  }

  MARPAESLIF_ERROR(marpaESLIFp, "");
  if (marpaESLIF_streamp->utfb && marpaESLIFRecognizerp->marpaESLIFRecognizerOption.newlineb) {
    MARPAESLIF_ERRORF(marpaESLIFp, "<<<<<< FAILURE AT LINE No %ld COLUMN No %ld, HERE: >>>>>>", (unsigned long) marpaESLIF_streamp->linel, (unsigned long) marpaESLIF_streamp->columnl);
  } else {
    MARPAESLIF_ERROR(marpaESLIFp, "<<<<<< FAILURE HERE: >>>>>>");
  }

  /* If there is some information after, show it */
  if ((marpaESLIF_streamp->inputs != NULL) && (marpaESLIF_streamp->inputl > 0)) {
    dumps = marpaESLIF_streamp->inputs;
    dumpl = marpaESLIF_streamp->inputl > 128 ? 128 : marpaESLIF_streamp->inputl;
    MARPAESLIF_ERROR(marpaESLIFp, "");
    MARPAESLIFRECOGNIZER_HEXDUMPV(funcs,
                                  marpaESLIFRecognizerp,
                                  "",
                                  marpaESLIF_streamp->utfb ? "UTF-8 converted data after the failure" : "Raw data after the failure",
                                  dumps,
                                  dumpl,
                                  0, /* traceb */
                                  0, /* noticeb */
                                  marpaESLIF_streamp->linel,
                                  marpaESLIF_streamp->columnl);
  }

  MARPAESLIF_ERROR(marpaESLIFp, "--------------------------------------------");

#ifndef MARPAESLIF_NTRACE
  err: /* For MARPAESLIF_INTERNAL_GET_SYMBOL_FROM_STACK */
#endif
  return;
}

#ifndef MARPAESLIF_NTRACE
/*****************************************************************************/
static inline void _marpaESLIF_dump(marpaESLIF_t *marpaESLIFp)
/*****************************************************************************/
/* Self dump                                                                 */
/*****************************************************************************/
{
  int   ngrammari;
  char *grammarshows;
  int   leveli;
  char *grammarscripts;

  if (marpaESLIFGrammar_ngrammarib(marpaESLIF_grammarp(marpaESLIFp), &ngrammari)) {
    GENERICLOGGER_TRACEF(marpaESLIFp->marpaESLIFOption.genericLoggerp, "ESLIF's ngrammari is %d", ngrammari);
    for (leveli = 0; leveli < ngrammari; leveli++) {
      if (marpaESLIFGrammar_grammarshowform_by_levelb(marpaESLIF_grammarp(marpaESLIFp), &grammarshows, leveli, NULL)) {
        GENERICLOGGER_TRACE (marpaESLIFp->marpaESLIFOption.genericLoggerp, "-------------------------");
        GENERICLOGGER_TRACEF(marpaESLIFp->marpaESLIFOption.genericLoggerp, "ESLIF grammar at level %d:", leveli);
        GENERICLOGGER_TRACEF(marpaESLIFp->marpaESLIFOption.genericLoggerp, "-------------------------\n%s", grammarshows);
      } else {
        GENERICLOGGER_ERRORF(marpaESLIFp->marpaESLIFOption.genericLoggerp, "marpaESLIFGrammar_grammarshowform_by_levelb(marpaESLIF_grammarp(marpaESLIFp), &grammarshows, leveli, NULL) failure, %s", strerror(errno));
        goto err;
      }
    }
  } else {
    GENERICLOGGER_ERRORF(marpaESLIFp->marpaESLIFOption.genericLoggerp, "marpaESLIFGrammar_ngrammarib(marpaESLIF_grammarp(marpaESLIFp), &ngrammari) failure, %s", strerror(errno));
    goto err;
  }

  /* Grammar script */
  if (! marpaESLIFGrammar_grammarshowscriptb(marpaESLIF_grammarp(marpaESLIFp), &grammarscripts)) {
    GENERICLOGGER_ERRORF(marpaESLIFp->marpaESLIFOption.genericLoggerp, "marpaESLIFGrammar_grammarshowscriptb failure, %s", strerror(errno));
    goto err;
  }
  GENERICLOGGER_TRACE (marpaESLIFp->marpaESLIFOption.genericLoggerp, "-------------------------");
  GENERICLOGGER_TRACE (marpaESLIFp->marpaESLIFOption.genericLoggerp, "ESLIF grammar script:");
  GENERICLOGGER_TRACEF(marpaESLIFp->marpaESLIFOption.genericLoggerp, "-------------------------\n%s", grammarscripts);

 err:
  return;
}
#endif /* MARPAESLIF_NTRACE */

/*****************************************************************************/
static inline marpaESLIF_lua_functiondecl_t *_marpaESLIF_lua_functiondecl_newp(marpaESLIF_t *marpaESLIFp)
/*****************************************************************************/
{
  marpaESLIF_lua_functiondecl_t *declp;

  declp = (marpaESLIF_lua_functiondecl_t *) malloc(sizeof(marpaESLIF_lua_functiondecl_t));
  if (MARPAESLIF_UNLIKELY(declp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  declp->luaparlists  = NULL;
  declp->luaparlistcb = 0;
  declp->sizei        = 0;

  goto done;

 err:
  _marpaESLIF_lua_functiondecl_freev(declp);
  declp = NULL;

 done:
  return declp;
}

/*****************************************************************************/
static inline marpaESLIF_lua_functioncall_t *_marpaESLIF_lua_functioncall_newp(marpaESLIF_t *marpaESLIFp)
/*****************************************************************************/
{
  marpaESLIF_lua_functioncall_t *callp;

  callp = (marpaESLIF_lua_functioncall_t *) malloc(sizeof(marpaESLIF_lua_functioncall_t));
  if (MARPAESLIF_UNLIKELY(callp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  callp->luaexplists  = NULL;
  callp->luaexplistcb = 0;
  callp->sizei        = 0;

  goto done;

 err:
  _marpaESLIF_lua_functioncall_freev(callp);
  callp = NULL;

 done:
  return callp;
}

/*****************************************************************************/
static inline marpaESLIF_lua_functiondecl_t *_marpaESLIF_lua_functiondecl_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIF_lua_functiondecl_t *declp)
/*****************************************************************************/
{
  marpaESLIF_lua_functiondecl_t *clonep;

  clonep = (marpaESLIF_lua_functiondecl_t *) malloc(sizeof(marpaESLIF_lua_functiondecl_t));
  if (MARPAESLIF_UNLIKELY(clonep == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  clonep->luaparlists = strdup(declp->luaparlists);
  if (MARPAESLIF_UNLIKELY(clonep->luaparlists == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
    goto err;
  }
  clonep->sizei        = declp->sizei;
  clonep->luaparlistcb = declp->luaparlistcb;

  goto done;

 err:
  _marpaESLIF_lua_functiondecl_freev(clonep);
  clonep = NULL;

 done:
  return clonep;
}

/*****************************************************************************/
static inline marpaESLIF_lua_functioncall_t *_marpaESLIF_lua_functioncall_clonep(marpaESLIF_t *marpaESLIFp, marpaESLIF_lua_functioncall_t *callp)
/*****************************************************************************/
{
  marpaESLIF_lua_functioncall_t *clonep;

  clonep = (marpaESLIF_lua_functioncall_t *) malloc(sizeof(marpaESLIF_lua_functioncall_t));
  if (MARPAESLIF_UNLIKELY(clonep == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  clonep->luaexplists = strdup(callp->luaexplists);
  if (MARPAESLIF_UNLIKELY(clonep->luaexplists == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
    goto err;
  }
  clonep->sizei        = callp->sizei;
  clonep->luaexplistcb = callp->luaexplistcb;

  goto done;

 err:
  _marpaESLIF_lua_functioncall_freev(clonep);
  clonep = NULL;

 done:
  return clonep;
}

/*****************************************************************************/
static inline marpaESLIF_lua_functioncall_t *_marpaESLIF_lua_functiondecl2callp(marpaESLIF_t *marpaESLIFp, marpaESLIF_lua_functiondecl_t *declp)
/*****************************************************************************/
{
  marpaESLIF_lua_functioncall_t *callp;

  callp = (marpaESLIF_lua_functioncall_t *) malloc(sizeof(marpaESLIF_lua_functioncall_t));
  if (MARPAESLIF_UNLIKELY(callp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }

  callp->luaexplists  = NULL;
  callp->luaexplistcb = declp->luaparlistcb;
  callp->sizei        = declp->sizei;

  callp->luaexplists  = strdup(declp->luaparlists);
  if (MARPAESLIF_UNLIKELY(callp->luaexplists == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "strdup failure, %s", strerror(errno));
    goto err;
  }

  goto done;

 err:
  _marpaESLIF_lua_functioncall_freev(callp);
  callp = NULL;

 done:
  return callp;
}

/*****************************************************************************/
static inline void _marpaESLIF_lua_functiondecl_freev(marpaESLIF_lua_functiondecl_t *declp)
/*****************************************************************************/
{
  if (declp != NULL) {
    if (declp->luaparlists != NULL) {
      free(declp->luaparlists);
    }
    free(declp);
  }
}

/*****************************************************************************/
static inline void _marpaESLIF_lua_functioncall_freev(marpaESLIF_lua_functioncall_t *callp)
/*****************************************************************************/
{
  if (callp != NULL) {
    if (callp->luaexplists != NULL) {
      free(callp->luaexplists);
    }
    free(callp);
  }
}

/*****************************************************************************/
static inline marpaESLIFValueResult_t *_marpaESLIFRecognizer_context_getp(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *contextp)
/*****************************************************************************/
{
  marpaESLIFValueResult_t  context;
  marpaESLIFValueResult_t *rcp;

  if (MARPAESLIF_UNLIKELY(! _marpaESLIF_lua_recognizer_get_contextp(marpaESLIFRecognizerp, contextp != NULL ? contextp : &context))) {
    goto err;
  }

  if (contextp != NULL) {
    /* The return value is the one given in argument */
    rcp = contextp;
  } else {
    /* We want to maintain the lifetime of this marpaESLIFValueResult, we put it in lexeme stack at unused indice 0 */
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_lexemeStack_i_setb(marpaESLIFRecognizerp, 0, &context))) {
      goto err;
    }

    /* This is in lexemeStackp at indice 0 */
    rcp = _marpaESLIFRecognizer_lexemeStack_i_getp(marpaESLIFRecognizerp, 0);
  }

  goto done;

 err:
  rcp = NULL;

 done:
  return rcp;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_eventb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *eventArraylp, marpaESLIFEvent_t **eventArraypp)
/*****************************************************************************/
{
  static const char *funcs = "_marpaESLIFRecognizer_eventb";
  short              rcb;

  /* We want to always make sure that grammar events are fetched */
  /* although without duplicates */
  _marpaESLIFRecognizer_clear_grammar_eventsb(marpaESLIFRecognizerp);
  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_push_grammar_eventsb(marpaESLIFRecognizerp))) {
    goto err;
  }

  if (eventArraylp != NULL) {
    *eventArraylp = marpaESLIFRecognizerp->eventArrayl;
  }
  if (eventArraypp != NULL) {
    *eventArraypp = marpaESLIFRecognizerp->eventArrayp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_name_last_pauseb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char *names, char **pausesp, size_t *pauselp)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_last_symbolDatab(marpaESLIFRecognizerp, names, pausesp, pauselp, marpaESLIFRecognizerp->lastPausepp, 1 /* forPauseb */, MARPAESLIF_SYMBOL_TYPE_NA, 0 /* onlyLhsb */, 1 /* onlyRhsb */);
}

/*****************************************************************************/
static inline size_t _marpaESLIF_next_power_of_twob(marpaESLIF_t *marpaESLIFp, size_t wantedl)
/*****************************************************************************/
/* https://www.geeksforgeeks.org/smallest-power-of-2-greater-than-or-equal-to-n/ */
/* Get the multiple of 2 that is >= sizel with one exception when sizel <= 1:*/
/* then the output will be 1.                                                */
/*****************************************************************************/
{
  size_t rcl;
  size_t previousl;

  if ((wantedl > 0) && !(wantedl & (wantedl - 1))) {
    rcl = wantedl;
  } else {
    previousl = rcl = 1;
    while (rcl < wantedl) {
      /* We count on compiler to optimize (<<= 1, + twice etc.) */
      rcl *= 2;
      if (rcl < previousl) {
        /* Turnaround */
        MARPAESLIF_ERRORF(marpaESLIFp, "Failed to get power of 2 >= %d", (unsigned long) wantedl);
        rcl = 0;
        break;
      }
      previousl = rcl;
    }
  }

  return rcl;
}

/*****************************************************************************/
static inline short _marpaESLIFValue_importb(marpaESLIFValue_t *marpaESLIFValuep, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  return _marpaESLIFValue_eslif2hostb(marpaESLIFValuep, marpaESLIFValueResultp, NULL /* forcedUserDatavp */, NULL /* forcedImporterp */);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_importb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFValueResult_t *marpaESLIFValueResultp)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_eslif2hostb(marpaESLIFRecognizerp, marpaESLIFValueResultp, NULL /* forcedUserDatavp */, NULL /* forcedImporterp */);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_name_expectedb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, size_t *nNamelp, char ***namesArraypp)
/*****************************************************************************/
{
  static const char    *funcs = "marpaESLIFRecognizer_name_expectedb";
  size_t                nTerminall;
  int                  *symbolIdArrayp;
  marpaESLIF_symbol_t **symbolArraypp;
  short                 rcb;
  marpaESLIF_t         *marpaESLIFp;
  size_t                symboll;
  marpaESLIF_symbol_t  *symbolp;
  size_t                nNamel;
  char                **namesArrayp;
  size_t                tmpl;
  char                **tmpsp;
  size_t                namesArrayAllocl; /* Current allocated size -; */

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_expectedTerminalsb(marpaESLIFRecognizerp, &nTerminall, &symbolIdArrayp, &symbolArraypp))) {
    goto err;
  }

  marpaESLIFp      = marpaESLIFRecognizerp->marpaESLIFp;
  namesArrayp      = marpaESLIFRecognizerp->namesArrayp;
  namesArrayAllocl = marpaESLIFRecognizerp->namesArrayAllocl;

  nNamel = 0;
  for (symboll = 0; symboll < nTerminall; symboll++) {
    symbolp = symbolArraypp[symboll];
    nNamel++;

    /* Prepare/use internal buffer */
    if (namesArrayAllocl <= 0) {
      tmpsp = (char **) malloc(sizeof(char **) * nNamel);
      if (MARPAESLIF_UNLIKELY(tmpsp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
        goto err;
      }
      namesArrayAllocl = marpaESLIFRecognizerp->namesArrayAllocl = nNamel;
      namesArrayp      = marpaESLIFRecognizerp->namesArrayp      = tmpsp;
    } else if (nNamel > namesArrayAllocl) {
      tmpl  = namesArrayAllocl * 2;
      tmpsp = (char **) realloc(namesArrayp, sizeof(char **) * tmpl);
      if (MARPAESLIF_UNLIKELY(tmpsp == NULL)) {
        MARPAESLIF_ERRORF(marpaESLIFp, "realloc failure, %s", strerror(errno));
        goto err;
      }
      namesArrayAllocl = marpaESLIFRecognizerp->namesArrayAllocl = tmpl;
      namesArrayp      = marpaESLIFRecognizerp->namesArrayp       = tmpsp;
    }

    /* We use symbolp->descp->asciis that is persisent */
    namesArrayp[nNamel - 1] = symbolp->descp->asciis;
  }

  /* Makes sure we reset the others - not needed but more beautiful from debugger perspective -; */
  for (symboll = nNamel; symboll < namesArrayAllocl; symboll++) {
    namesArrayp[symboll] = NULL;
  }

  if (nNamelp != NULL) {
    *nNamelp = nNamel;
  }
  if (namesArraypp != NULL) {
    *namesArraypp = namesArrayp;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  return rcb;
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_discard_last_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, char **trysp, size_t *trylp)
/*****************************************************************************/
{
  return _marpaESLIFRecognizer_last_symbolDatab(marpaESLIFRecognizerp, ":discard", trysp, trylp, marpaESLIFRecognizerp->lastTrypp, 0 /* forPauseb */, MARPAESLIF_SYMBOL_TYPE_META, 1 /* onlyLhsb */, 0 /* onlyRhsb */);
}

/*****************************************************************************/
static inline short _marpaESLIFRecognizer_alternativeb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFAlternative_t *marpaESLIFAlternativep)
/*****************************************************************************/
{
  static const char       *funcs              = "marpaESLIFRecognizer_alternativeb";
  marpaESLIF_t            *marpaESLIFp        = marpaESLIFRecognizerp->marpaESLIFp;
  marpaESLIF_grammar_t    *grammarp           = marpaESLIFRecognizerp->grammarp;
  marpaESLIF_symbol_t     *symbolp;
  marpaESLIF_alternative_t alternative;
  short                    rcb;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* An alternative can only be an RHS */
  symbolp = _marpaESLIF_symbol_findp(marpaESLIFp, grammarp, marpaESLIFAlternativep->names, -1, NULL /* symbolip */, 1 /* silentb */, 0 /* onlyLhsb */, 1 /* onlyRhsb */, MARPAESLIF_SYMBOL_TYPE_NA);
  if (MARPAESLIF_UNLIKELY(symbolp == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "Failed to find symbol <%s> used only as an RHS", marpaESLIFAlternativep->names);
    goto err;
  }

  alternative.marpaESLIFValueResult = marpaESLIFValueResultUndef;
  alternative.symbolp               = symbolp;
  alternative.marpaESLIFValueResult = marpaESLIFAlternativep->value;
  alternative.grammarLengthi        = (int) marpaESLIFAlternativep->grammarLengthl;
  alternative.usedb                 = 1;

  if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_fast_alternativeb(marpaESLIFRecognizerp, &alternative))) {
    goto err;
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  return rcb;
}

/*****************************************************************************/
static inline short __marpaESLIFRecognizer_symbol_tryb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, marpaESLIFSymbol_t *marpaESLIFSymbolp, short *matchbp)
/*****************************************************************************/
{
  static const char          *funcs = "__marpaESLIFRecognizer_symbol_tryb";
  marpaESLIF_matcher_value_t  rci;
  short                       rcb;
  marpaESLIFValueResult_t     marpaESLIFValueResult = marpaESLIFValueResultUndef;
  short                       rcMatcherb;
  marpaESLIFRecognizer_t     *marpaESLIFRecognizerTmpp;

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  /* An external symbol is never parameterized */
  if (marpaESLIFSymbolp->marpaESLIFGrammarp != NULL) {
    /* Case of meta symbol only - we create a temporary recognizer */
    marpaESLIFRecognizerTmpp = marpaESLIFRecognizer_newFromp(marpaESLIFSymbolp->marpaESLIFGrammarp, marpaESLIFRecognizerp);
    if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerTmpp == NULL)) {
      goto err;
    }
    
    rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerTmpp,
                                                       marpaESLIFRecognizerTmpp->marpaESLIF_streamp,
                                                       marpaESLIFSymbolp,
                                                       &rci,
                                                       &marpaESLIFValueResult,
                                                       0, /* maxStartCompletionsi */
                                                       NULL, /* lastSizeBeforeCompletionlp */
                                                       NULL, /* numberOfStartCompletionsip */
                                                       NULL /* matchedLengthl */);
    if (MARPAESLIF_UNLIKELY(! _marpaESLIFRecognizer_shareb(marpaESLIFRecognizerTmpp, NULL))) {
      goto err;
    }
    marpaESLIFRecognizer_freev(marpaESLIFRecognizerTmpp); /* NULL protected */
  } else {
    rcMatcherb = _marpaESLIFRecognizer_symbol_matcherb(marpaESLIFRecognizerp,
                                                       marpaESLIFRecognizerp->marpaESLIF_streamp,
                                                       marpaESLIFSymbolp,
                                                       &rci,
                                                       &marpaESLIFValueResult,
                                                       0, /* maxStartCompletionsi */
                                                       NULL, /* lastSizeBeforeCompletionlp */
                                                       NULL, /* numberOfStartCompletionsip */
                                                       NULL /* matchedLengthlp */);
  }

  if (rcMatcherb < 0) {
    /* Fatal error */
    goto err;
  }

  if (! rcMatcherb) {
    if (matchbp != NULL) {
      *matchbp = 0;
    }
  } else {
    switch (rci) {
    case MARPAESLIF_MATCH_FAILURE:
      if (matchbp != NULL) {
        *matchbp = 0;
      }
      break;
    case MARPAESLIF_MATCH_OK:
      if (matchbp != NULL) {
        *matchbp = 1;
      }
      /* Import, eventually */
      if (! _marpaESLIFRecognizer_eslif2hostb(marpaESLIFRecognizerp, &marpaESLIFValueResult, marpaESLIFSymbolp /* forcedUserDatavp */, _marpaESLIFRecognizerSymbolProxyImportb /* forcedImporterp */)) {
        goto err;
      }
      break;
    default:
      /* This is handling MARPAESLIF_MATCH_AGAIN that is a fatal error because _marpaESLIFRecognizer_symbol_matcherb() tried to handle that */
      goto err;
    }
  }

  rcb = 1;
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
  _marpaESLIFRecognizer_valueResultFreev(marpaESLIFRecognizerp, &marpaESLIFValueResult);
  return rcb;
}

/*****************************************************************************/
short marpaESLIFRecognizer_isStartCompleteb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, short *completebp)
/*****************************************************************************/
{
  static const char *funcs = "marpaESLIFRecognizer_isStartCompleteb";
  short              rcb;

  if (MARPAESLIF_UNLIKELY(marpaESLIFRecognizerp == NULL)) {
    errno = EINVAL;
    rcb = 0;
    goto fast_done;
  }

  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_INC(marpaESLIFRecognizerp);
  MARPAESLIFRECOGNIZER_TRACE(marpaESLIFRecognizerp, funcs, "start");

  rcb = _marpaESLIFRecognizer_isStartCompleteb(marpaESLIFRecognizerp, completebp);
  goto done;

 err:
  rcb = 0;

 done:
  MARPAESLIFRECOGNIZER_TRACEF(marpaESLIFRecognizerp, funcs, "return %d", (int) rcb);
  MARPAESLIFRECOGNIZER_CALLSTACKCOUNTER_DEC(marpaESLIFRecognizerp);
 fast_done:
  return rcb;
}

/*****************************************************************************/
static short _marpaESLIFRecognizerSymbolProxyImportb(marpaESLIFRecognizer_t *marpaESLIFRecognizerp, void *userDatavp, marpaESLIFValueResult_t *marpaESLIFValueResultp, short haveUndefb)
/*****************************************************************************/
{
  static const char  *funcs             = "_marpaESLIFRecognizerSymbolProxyImportb";
  marpaESLIFSymbol_t *marpaESLIFSymbolp = (marpaESLIFSymbol_t *) userDatavp;

  return
    (marpaESLIFSymbolp->marpaESLIFSymbolOption.importerp != NULL)
    ?
    marpaESLIFSymbolp->marpaESLIFSymbolOption.importerp(marpaESLIFSymbolp, marpaESLIFSymbolp->marpaESLIFSymbolOption.userDatavp, marpaESLIFValueResultp, haveUndefb)
    :
    1;
}

/*****************************************************************************/
static marpaESLIF_string_t *_marpaESLIF_terminal_add_substitution_desc_to_terminal_descp(marpaESLIF_t *marpaESLIFp, marpaESLIF_terminal_t *terminalp, marpaESLIF_terminal_t *substitutionTerminalp)
/*****************************************************************************/
{
  static const char   *funcs             = "_marpaESLIF_terminal_add_substitution_desc_to_terminal_descp";
  char                *asciis            = NULL;
  marpaESLIF_string_t *rcp               = NULL;
  char                *p;
  size_t               asciil;

  /* We also want to overwrite the terminal description to include the substitution */
  /* We revisit the ASCII version of the description */
  asciil = strlen(terminalp->descp->asciis) + 4 /* " -> " */ + strlen(substitutionTerminalp->descp->asciis);
  asciis = (char *) malloc(asciil + 1); /* + 1 for NUL byte */
  if (MARPAESLIF_UNLIKELY(asciis == NULL)) {
    MARPAESLIF_ERRORF(marpaESLIFp, "malloc failure, %s", strerror(errno));
    goto err;
  }
  p = asciis;
  strcpy(p, terminalp->descp->asciis);
  p += strlen(terminalp->descp->asciis);
  /* This is UTF-8 by definition */
  *p++ = ' ';
  *p++ = '-';
  *p++ = '>';
  *p++ = ' ';
  strcpy(p, substitutionTerminalp->descp->asciis);
  p += strlen(substitutionTerminalp->descp->asciis);
  *p = '\0';

  rcp = _marpaESLIF_string_newp(marpaESLIFp, "ASCII", asciis, asciil);
  if (rcp == NULL) {
    goto err;
  }

  goto done;

 err:
  _marpaESLIF_string_freev(rcp, 0 /* onStackb */);
  rcp = NULL;

 done:
  if (asciis != NULL) {
    free(asciis);
  }
  return rcp;
}

#include "bootstrap.c"
#include "lua.c"
#include "json.c"
#include "floattos.c"

