/* Generated by re2c 1.2.1 on Mon May 18 17:14:55 2020 */
/*
 * STEP Part 21 Parser
 *
 * Copyright (c) 2020, Christopher HORLER (cshorler@googlemail.com)
 *
 * All rights reserved.
 *
 * This file is part of the STEPCODE project.
 *
 * 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 <ORGANIZATION> 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 HOLDER 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.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <assert.h>

#include <sqlite3.h>

#define YYCTYPE unsigned char
#define YYCURSOR in->cur
#define YYLIMIT in->lim
#define YYMARKER in->mrk
#define YYCTXMARKER in->ctxmrk
#define YYFILL(n) do { \
        if (fill(in, n) != 0) { \
            fprintf(stderr, "lexer fill(...) failed, exiting\n"); \
            exit(1); \
        } \
    } while (0)

#define YYMAXFILL 17

#define INIT_BUF_SZ 4096
#define INIT_STACK_SZ 64

/* reserved literals '(' ')' ';' '=' */
#define T_P21_START     'S'
#define T_P21_END       'X'
#define T_HEADER        'H'
#define T_DATA          'D'
#define T_ENDSEC        'E'
#define T_EID           'I'
#define T_KEYWORD       'K'
#define T_VARIANT       'V'
#define T_EOF           '\x00'
#define T_ERROR         '\x01'

#define V_REAL          'r'
#define V_INTEGER       'i'
#define V_STRING        's'
#define V_BINARY        'b'
#define V_ENUMERATION   'e'
#define V_EID           T_EID
#define V_DERIVED       '*'
#define V_EMPTY         '$'

#define P_FILE          'f'
#define P_HEADERSECTION 'h'
#define P_DATASECTION   'd'
#define P_HEADERENTITY  'x'
#define P_SIMPLEENTITY  's'
#define P_COMPLEXENTITY 'c'
#define P_SIMPLERECORD  'u'
#define P_LIST          'l'
#define P_PARAMETER     'p'

int debug = 1;
#define dprintf(fmt, ...) \
    do { if (debug) fprintf(stderr, "%s:%3d " fmt, __FILE__, __LINE__, ##__VA_ARGS__); } while (0)
        
/* ppfu https://stackoverflow.com/a/11763277/1162349 */
#define GET_MACRO(_1, _2, _3, _4, NAME, ...) NAME
#define _EXPAND(x) x

/* for lookahead */
#define PUSH_SYMBOL(...) _EXPAND(GET_MACRO(__VA_ARGS__, _4, _3, _PUSH_SYMBOL2, _PUSH_SYMBOL1)(__VA_ARGS__))
#define _PUSH_SYMBOL1(token) in->sym[in->nsym++] = (Symbol){(token), 0, n, in->lineno, in->sp - in->basemrk}
#define _PUSH_SYMBOL2(token, vtype) in->sym[in->nsym++] = (Symbol){(token), (vtype), n, in->lineno, in->sp - in->basemrk}

/* for parse stack */
#define PUSH_TERMINAL(stack, sym) do { \
        Symbol it = (sym); \
        push((stack), it); \
        if (it.token == T_ERROR) goto err; \
    } while (0)
    
#define PUSH_TERMINAL_EXT(cxt, stack, sym) do { \
        Symbol it = (sym); \
        push((stack), it); \
        if (it.token == T_ERROR) goto err; \
        else if (it.token == '(') (cxt) = (stack)->idx_top - 1; \
        else if (it.token == ')') (stack)->items[(cxt)].n = (stack)->idx_top - (cxt) - 1; \
    } while (0)

/* test for one in a set of 1 to 4 e.g. {t0, t1, t2, t3} */
#define LOOKAHEAD(x, ...) _EXPAND(GET_MACRO(__VA_ARGS__, _LOOKAHEAD4, _LOOKAHEAD3, _LOOKAHEAD2, _LOOKAHEAD1)(x, __VA_ARGS__))
#define _LOOKAHEAD1(x, t0)             ((t0) == (x).token)
#define _LOOKAHEAD2(x, t0, t1)         ((t0) == (x).token || (t1) == (x).token)
#define _LOOKAHEAD3(x, t0, t1, t2)     (_LOOKAHEAD2(x, t0, t1) || (t2) == (x).token)
#define _LOOKAHEAD4(x, t0, t1, t2, t3) (_LOOKAHEAD2(x, t0, t1) || _LOOKAHEAD2(x, t2, t3))





/* lexeme */
typedef struct {
    uint8_t token;
    union {
        uint8_t vtype;
        uint8_t errtoken;
    };
    uint16_t n;
    uint32_t lineno;
    union {
        ptrdiff_t offset; /* from basemrk */
        void *data; /* production allocation if applicable */
    };
} Symbol;

typedef struct SimpleRecord_ {
    Symbol *kw;  /* 'KEYWORD' */
    Symbol *args;/* '(' */
} SimpleRecord;

typedef struct SimpleRecord_ HeaderEntity;

typedef struct {
    Symbol *eid; /* '#<idN>' */
    Symbol *eq;   /* '=' */
    Symbol *kw;  /* 'KEYWORD' */
    Symbol *args;/* '(' */
} SimpleEntity;

typedef struct {
    Symbol *eid; /* '#<idN>' */
    Symbol *eq;   /* '=' */
    Symbol *subsupers;/* '(' */
} ComplexEntity;


typedef struct {
    FILE *file;
    size_t bufsz;
    unsigned char *cur, *mrk, *ctxmrk, *lim;
    unsigned char *sp, *basemrk;
    int eof;
    uint32_t lineno;    
    int nsym;
    Symbol sym[3];
    unsigned char *buf;
} Input;

typedef struct {
    int idx_top;
    int idx_lim;
    Symbol *items;
} Stack;

/* LL(3) parser */
typedef struct {
    bool error;
    bool hold;
    Input *in;
    Stack *stack;
} P21Parser;

typedef void (p21_action_cb_t) (P21Parser *, int, void *);
typedef void (p21_error_cb_t) (P21Parser *, int, uint8_t);
typedef void (p21_ud_cb_t) (void *);

typedef struct {
    void            *userdata;
    p21_error_cb_t  *error_cb;
    p21_ud_cb_t     *ud_init_cb;
    p21_ud_cb_t     *ud_exit_cb;
    p21_action_cb_t *exchange_file_cb;
    p21_action_cb_t *header_start_cb;
    p21_action_cb_t *header_entity_list_cb;
    p21_action_cb_t *data_section_list_cb;
    p21_action_cb_t *data_start_cb;
    p21_action_cb_t *header_entity_cb;
    p21_action_cb_t *simple_entity_instance_cb;
    p21_action_cb_t *complex_entity_instance_cb;
    p21_action_cb_t *parameter_list_cb;
    p21_action_cb_t *parameter_cb;
    p21_action_cb_t *entity_instance_list_cb;
    p21_action_cb_t *entity_instance_cb;
    p21_action_cb_t *simple_record_list_cb;
    p21_action_cb_t *simple_record_cb;
} P21ParserActions;


void report_error(P21Parser *, const char *);
void _recover(Input *, uint8_t, uint8_t, uint8_t);
Symbol lpop(Input *, uint8_t);

void p21_parse(P21Parser *, P21ParserActions *);
void p21_exchange_file(P21Parser *, P21ParserActions *);
void p21_header_section(P21Parser *, P21ParserActions *);
void p21_header_entity_list(P21Parser *, P21ParserActions *);
void p21_header_entity(P21Parser *, P21ParserActions *);
void p21_data_section_list(P21Parser *, P21ParserActions *);
void p21_data_section(P21Parser *, P21ParserActions *);
void p21_entity_instance(P21Parser *, P21ParserActions *);
void p21_simple_entity_instance(P21Parser *, P21ParserActions *);
void p21_complex_entity_instance(P21Parser *, P21ParserActions *);
void p21_entity_instance_list(P21Parser *, P21ParserActions *);
void p21_parameter(P21Parser *, P21ParserActions *);
void p21_parameter_list(P21Parser *, P21ParserActions *);
void p21_simple_record(P21Parser *, P21ParserActions *);
void p21_simple_record_list(P21Parser *, P21ParserActions *);


void push(Stack *stack, Symbol it) {
    if (stack->idx_top == stack->idx_lim) {
        Symbol *nitems = realloc(stack->items, 2 * stack->idx_lim * sizeof stack->items[0]);
        if (!nitems) {
            fprintf(stderr, "failed to grow parser stack, memory exhausted\n");
            exit(1);
        }
        stack->items = nitems;
        stack->idx_lim *= 2;
    }
    
    stack->items[stack->idx_top++] = it;
}

/* mock implementations */
void drop(Stack *stack, uint32_t n) {
    assert(stack->idx_top >= n);
    stack->idx_top -= n;
}

void unwind(Stack *stack, int bsp) {
    stack->idx_top = bsp;
}

Symbol *pop(Stack *stack) {
    assert(stack->idx_top >= 1);
    stack->idx_top--;
    return stack->items + stack->idx_top;
}

Symbol *peek(Stack *stack) {
    assert(stack->idx_top >= 1);
    return stack->items + stack->idx_top - 1;
}

Symbol lpop(Input *in, uint8_t token) {
    Symbol *stack = in->sym;
    Symbol sym = stack[0];
    
    /* missing input or unexpected lookahead token */
    if (in->nsym == 0)
        return (Symbol){T_ERROR, token, 0, in->lineno};
    else if (sym.token != token)
        return (Symbol){T_ERROR, token, 0, sym.lineno};
    
    if (!--in->nsym) {
        memset(&in->sym[0], 0, sizeof in->sym[0]);
    } else {
        memmove(&in->sym[0], &in->sym[1], in->nsym * sizeof in->sym[0]);
        memset(&in->sym[in->nsym], 0, sizeof in->sym[0]);
    }
    
    return sym;
}

static int fill(Input *in, size_t need)
{
    size_t free;
    unsigned char *newbuf;
    
    if (in->eof) {
        return 1;
    }
    free = in->basemrk - in->buf;
    if (free < need) {
        newbuf = realloc(in->buf, 2 * in->bufsz + YYMAXFILL);
        if (!newbuf) {
            fprintf(stderr, "fatal - buffer memory exhausted, exiting\n");
            return 2;
        }
        in->bufsz *= 2;
        in->lim = newbuf + (in->lim - in->buf);
        in->cur = newbuf + (in->cur - in->buf);
        in->mrk = newbuf + (in->mrk - in->buf);
        in->ctxmrk = newbuf + (in->ctxmrk - in->buf);
        in->basemrk = newbuf + (in->basemrk - in->buf);
        in->sp = newbuf + (in->sp - in->buf);
        in->buf = newbuf;
        
        /* don't memmove() here! */
        free = (in->buf + in->bufsz) - in->lim;
    } else {
        memmove(in->buf, in->basemrk, in->lim - in->basemrk);
        in->lim -= free;
        in->cur -= free;
        in->mrk -= free;
        in->ctxmrk -= free;
        in->basemrk -= free;
        in->sp -= free;
    }
    
    in->lim += fread(in->lim, 1, free, in->file);
    if (in->lim < in->buf + in->bufsz) {
        in->eof = 1;
        memset(in->lim, 0, YYMAXFILL);
        in->lim += YYMAXFILL;
    }
    return 0;
}

static void p21_init(P21Parser *p, FILE *file)
{
    Stack *stack;
    Input *in; 

    in = malloc(sizeof *in);
    if (!in)
        goto err;
    memset(in, 0, sizeof *in);
    in->bufsz = INIT_BUF_SZ;
    in->buf = malloc(INIT_BUF_SZ + YYMAXFILL);
    if (!in->buf)
        goto err;
    in->file = file;
    in->cur = in->basemrk = in->sp = in->lim = in->buf + INIT_BUF_SZ;
    in->lineno = 1;
    fill(in, 1);

    stack = malloc(sizeof *stack);
    if (!stack)
        goto err;
    memset(stack, 0, sizeof *stack);
    stack->idx_lim = 16;
    stack->idx_top = 0;
    stack->items = malloc(stack->idx_lim * sizeof stack->items[0]);
    if (!stack->items)
        goto err;

    p->in = in;
    p->stack = stack;
    p->error = false;
    
    return;
    
err:
    fprintf(stderr, "failed to initialise parser\n");
    exit(1);
}

/* noop error handler */
void default_error_handler(P21Parser *p, int bsp, uint8_t t) {
    Symbol *sym = peek(p->stack);
    if (sym->token == T_ERROR)
        pop(p->stack);
    push(p->stack, (Symbol){t});
}

/* TODO: this needs to be reworked */
void report_error(P21Parser *p, const char *cxt) {
    Input *in = p->in;
    Symbol *it = peek(p->stack);
    int lineno;
    unsigned char *cur;
    
    fprintf(stderr, cxt);
    
    if (it->token == T_ERROR) {
        fprintf(stderr, "  syntax error - line: %d\n", it->lineno);
        fprintf(stderr, "  expected '%c' (token type) ", it->errtoken);
    } else {
        cur = in->cur;
        lineno = in->lineno;
        while (1) {
            if (*(cur - 2) == '\r' && *(cur - 1) == '\n') { cur -= 2; --lineno; }
            else if (*(cur - 1) == '\n') { --cur; --lineno; }
            else { break; }
        }
        fprintf(stderr, "  syntax error - line: %d\n", lineno);
    }
    
    if (!in->nsym) {
        cur = in->cur;
        lineno = in->lineno;
        while (1) {
            if (*cur == '\r' && *(cur + 1) == '\n') { cur -= 2; --lineno; }
            else if (*cur == '\n') { --cur; --lineno; }
            else { break; }
        }
        fprintf(stderr, "  unexpected character '%c' (line: %d)\n", *cur, lineno);        
    } else {
        fprintf(stderr, "  got '%c' (token type)\n", in->sym[0].token);
    }
}


void lex_comment(Input *in) {
    size_t n;
    int comment_lvl = 1;
    
    while (1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= '*') {
		if (yych <= '\r') {
			if (yych == '\n') goto yy4;
			if (yych >= '\r') goto yy6;
		} else {
			if (yych <= 0x001F) goto yy2;
			if (yych <= ' ') goto yy7;
			if (yych <= ')') goto yy10;
			goto yy13;
		}
	} else {
		if (yych <= '[') {
			if (yych == '/') goto yy16;
			if (yych <= 'Z') goto yy10;
		} else {
			if (yych == ']') goto yy2;
			if (yych <= '~') goto yy10;
		}
	}
yy2:
	++YYCURSOR;
yy3:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy4:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy6:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy4;
	goto yy3;
yy7:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') {
		if (yych <= ')') {
			if (yych <= 0x001F) goto yy9;
			if (yych <= ' ') goto yy7;
			goto yy10;
		} else {
			if (yych <= '*') goto yy9;
			if (yych <= '.') goto yy10;
		}
	} else {
		if (yych <= '\\') {
			if (yych != '[') goto yy10;
		} else {
			if (yych <= ']') goto yy9;
			if (yych <= '~') goto yy10;
		}
	}
yy9:
	{ n = in->cur - in->sp; }
	{ continue; }
yy10:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') {
		if (yych <= ')') {
			if (yych >= ' ') goto yy10;
		} else {
			if (yych <= '*') goto yy12;
			if (yych <= '.') goto yy10;
		}
	} else {
		if (yych <= '\\') {
			if (yych != '[') goto yy10;
		} else {
			if (yych <= ']') goto yy12;
			if (yych <= '~') goto yy10;
		}
	}
yy12:
	{ n = in->cur - in->sp; }
	{ continue; }
yy13:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '*') goto yy13;
	if (yych == '/') goto yy18;
	{ n = in->cur - in->sp; }
	{ continue; }
yy16:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy20;
	{ n = in->cur - in->sp; }
	{ continue; }
yy18:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{
            if (!--comment_lvl) { break; }
            else { continue; }
        }
yy20:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

    }
    
    return;
    
err:
    fprintf(stderr, "invalid character in comment, exiting\n");
    exit(1);
}

#define recover(in, ...) GET_MACRO(__VA_ARGS__, _4, _RECOVER3, _RECOVER2, _RECOVER1)(in, __VA_ARGS__)
#define _RECOVER1(in, u0) _recover((in), (u0), 0U, 0U)
#define _RECOVER2(in, u0, u1) _recover((in), (u0), (u1), 0U)
#define _RECOVER3(in, u0, u1, u2) _recover((in), (u0), (u1), (u2))

void _recover(Input *in, uint8_t u0, uint8_t u1, uint8_t u2) {
    size_t n;
    Symbol sym;
    
    while (in->nsym) {
        if (LOOKAHEAD(in->sym[0], u0, u1, u2, T_EOF))
            break;
        --in->nsym;
        memmove(&in->sym[0], &in->sym[1], in->nsym * sizeof in->sym[0]);
        memset(&in->sym[in->nsym], 0, sizeof in->sym[0]);
    }
    
    if (in->nsym)
        return;
    
    while (1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	unsigned int yyaccept = 0;
	if ((YYLIMIT - YYCURSOR) < 17) YYFILL(17);
	yych = *YYCURSOR;
	if (yych <= '-') {
		if (yych <= '"') {
			if (yych <= '\r') {
				if (yych == '\n') goto yy26;
				if (yych >= '\r') goto yy28;
			} else {
				if (yych <= 0x001F) goto yy24;
				if (yych <= ' ') goto yy29;
				if (yych <= '!') goto yy32;
				goto yy33;
			}
		} else {
			if (yych <= '\'') {
				if (yych <= '#') goto yy34;
				if (yych <= '$') goto yy35;
				if (yych >= '\'') goto yy37;
			} else {
				if (yych <= '*') {
					if (yych <= ')') goto yy38;
					goto yy40;
				} else {
					if (yych != ',') goto yy42;
				}
			}
		}
	} else {
		if (yych <= 'E') {
			if (yych <= ':') {
				if (yych <= '.') goto yy43;
				if (yych <= '/') goto yy44;
				if (yych <= '9') goto yy45;
			} else {
				if (yych <= '@') {
					if (yych <= ';') goto yy38;
				} else {
					if (yych <= 'C') goto yy48;
					if (yych <= 'D') goto yy51;
					goto yy52;
				}
			}
		} else {
			if (yych <= 'Z') {
				if (yych <= 'G') goto yy48;
				if (yych <= 'H') goto yy53;
				if (yych <= 'I') goto yy54;
				goto yy48;
			} else {
				if (yych <= '_') {
					if (yych >= '_') goto yy48;
				} else {
					if (yych <= '`') goto yy24;
					if (yych <= 'z') goto yy48;
				}
			}
		}
	}
yy24:
	++YYCURSOR;
yy25:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy26:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy28:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy26;
	goto yy25;
yy29:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy29;
	{ n = in->cur - in->sp; }
	{ continue; }
yy32:
	yych = *++YYCURSOR;
	if (yych <= '^') {
		if (yych <= '@') goto yy25;
		if (yych <= 'Z') goto yy48;
		goto yy25;
	} else {
		if (yych == '`') goto yy25;
		if (yych <= 'z') goto yy48;
		goto yy25;
	}
yy33:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '/') goto yy25;
	if (yych <= '3') goto yy55;
	goto yy25;
yy34:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy25;
	if (yych <= '9') goto yy58;
	goto yy25;
yy35:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_VARIANT, V_EMPTY}; goto check; }
yy37:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '[') {
		if (yych <= 0x001F) goto yy25;
		if (yych <= 'Z') goto yy62;
		goto yy25;
	} else {
		if (yych == ']') goto yy25;
		if (yych <= '~') goto yy62;
		goto yy25;
	}
yy38:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){*in->sp}; goto check; }
yy40:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_VARIANT, V_DERIVED}; goto check; }
yy42:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= ',') {
		if (yych == '+') goto yy66;
		goto yy25;
	} else {
		if (yych <= '-') goto yy66;
		if (yych <= '/') goto yy25;
		if (yych <= '9') goto yy45;
		goto yy25;
	}
yy43:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '@') goto yy25;
	if (yych <= 'Z') goto yy68;
	if (yych == '_') goto yy68;
	goto yy25;
yy44:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy70;
	goto yy25;
yy45:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '.') goto yy72;
	if (yych <= '/') goto yy47;
	if (yych <= '9') goto yy45;
yy47:
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_VARIANT, V_INTEGER}; goto check; }
yy48:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
yy49:
	if (yych <= 'Z') {
		if (yych <= '/') goto yy50;
		if (yych <= '9') goto yy48;
		if (yych >= 'A') goto yy48;
	} else {
		if (yych <= '_') {
			if (yych >= '_') goto yy48;
		} else {
			if (yych <= '`') goto yy50;
			if (yych <= 'z') goto yy48;
		}
	}
yy50:
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_KEYWORD}; goto check; }
yy51:
	yych = *++YYCURSOR;
	if (yych == 'A') goto yy75;
	goto yy49;
yy52:
	yych = *++YYCURSOR;
	if (yych == 'N') goto yy76;
	goto yy49;
yy53:
	yych = *++YYCURSOR;
	if (yych == 'E') goto yy77;
	goto yy49;
yy54:
	yych = *++YYCURSOR;
	if (yych == 'S') goto yy78;
	goto yy49;
yy55:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') {
		if (yych == '"') goto yy79;
	} else {
		if (yych <= '9') goto yy55;
		if (yych <= '@') goto yy57;
		if (yych <= 'F') goto yy55;
	}
yy57:
	YYCURSOR = YYMARKER;
	if (yyaccept <= 1) {
		if (yyaccept == 0) {
			goto yy25;
		} else {
			goto yy64;
		}
	} else {
		if (yyaccept == 2) {
			goto yy74;
		} else {
			goto yy50;
		}
	}
yy58:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy60;
	if (yych <= '9') goto yy58;
yy60:
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_EID}; goto check; }
yy61:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
yy62:
	if (yych <= 'Z') {
		if (yych <= 0x001F) goto yy57;
		if (yych != '\'') goto yy61;
	} else {
		if (yych <= '\\') {
			if (yych <= '[') goto yy57;
			goto yy65;
		} else {
			if (yych <= ']') goto yy57;
			if (yych <= '~') goto yy61;
			goto yy57;
		}
	}
	yyaccept = 1;
	YYMARKER = ++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\'') goto yy61;
yy64:
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_VARIANT, V_STRING}; goto check; }
yy65:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= 'S') {
		if (yych <= '@') goto yy57;
		if (yych <= 'I') goto yy81;
		if (yych <= 'R') goto yy57;
		goto yy82;
	} else {
		if (yych <= 'X') {
			if (yych <= 'W') goto yy57;
			goto yy83;
		} else {
			if (yych == '\\') goto yy61;
			goto yy57;
		}
	}
yy66:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= ',') {
		if (yych == '+') goto yy66;
		goto yy57;
	} else {
		if (yych <= '-') goto yy66;
		if (yych <= '/') goto yy57;
		if (yych <= '9') goto yy45;
		goto yy57;
	}
yy68:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '9') {
		if (yych == '.') goto yy84;
		if (yych <= '/') goto yy57;
		goto yy68;
	} else {
		if (yych <= 'Z') {
			if (yych <= '@') goto yy57;
			goto yy68;
		} else {
			if (yych == '_') goto yy68;
			goto yy57;
		}
	}
yy70:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yy72:
	yyaccept = 2;
	YYMARKER = ++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy74;
	if (yych <= '9') goto yy72;
	if (yych == 'E') goto yy86;
yy74:
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_VARIANT, V_REAL}; goto check; }
yy75:
	yych = *++YYCURSOR;
	if (yych == 'T') goto yy88;
	goto yy49;
yy76:
	yych = *++YYCURSOR;
	if (yych == 'D') goto yy89;
	goto yy49;
yy77:
	yych = *++YYCURSOR;
	if (yych == 'A') goto yy90;
	goto yy49;
yy78:
	yych = *++YYCURSOR;
	if (yych == 'O') goto yy91;
	goto yy49;
yy79:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_VARIANT, V_BINARY}; goto check; }
yy81:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yy61;
	goto yy57;
yy82:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yy92;
	goto yy57;
yy83:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '3') {
		if (yych == '2') goto yy93;
		goto yy57;
	} else {
		if (yych <= '4') goto yy94;
		if (yych == '\\') goto yy95;
		goto yy57;
	}
yy84:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_VARIANT, V_ENUMERATION}; goto check; }
yy86:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= ',') {
		if (yych == '+') goto yy86;
		goto yy57;
	} else {
		if (yych <= '-') goto yy86;
		if (yych <= '/') goto yy57;
		if (yych <= '9') goto yy96;
		goto yy57;
	}
yy88:
	yych = *++YYCURSOR;
	if (yych == 'A') goto yy98;
	goto yy49;
yy89:
	yyaccept = 3;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == '-') goto yy99;
	if (yych == 'S') goto yy100;
	goto yy49;
yy90:
	yych = *++YYCURSOR;
	if (yych == 'D') goto yy101;
	goto yy49;
yy91:
	yyaccept = 3;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == '-') goto yy102;
	goto yy49;
yy92:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '[') {
		if (yych <= 0x001F) goto yy57;
		if (yych <= 'Z') goto yy61;
		goto yy57;
	} else {
		if (yych == ']') goto yy57;
		if (yych <= '~') goto yy61;
		goto yy57;
	}
yy93:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yy103;
	goto yy57;
yy94:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yy104;
	goto yy57;
yy95:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy105;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy105;
	goto yy57;
yy96:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy74;
	if (yych <= '9') goto yy96;
	goto yy74;
yy98:
	yych = *++YYCURSOR;
	if (yych <= ')') {
		if (yych == ' ') goto yy106;
		if (yych <= '\'') goto yy49;
		goto yy106;
	} else {
		if (yych <= '/') {
			if (yych <= '.') goto yy49;
			goto yy106;
		} else {
			if (yych == ';') goto yy106;
			goto yy49;
		}
	}
yy99:
	yych = *++YYCURSOR;
	if (yych == 'I') goto yy108;
	goto yy57;
yy100:
	yych = *++YYCURSOR;
	if (yych == 'E') goto yy109;
	goto yy49;
yy101:
	yych = *++YYCURSOR;
	if (yych == 'E') goto yy110;
	goto yy49;
yy102:
	yych = *++YYCURSOR;
	if (yych == '1') goto yy111;
	goto yy57;
yy103:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy112;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy112;
	goto yy57;
yy104:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy113;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy113;
	goto yy57;
yy105:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy61;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy61;
	goto yy57;
yy106:
	++YYCURSOR;
	YYCURSOR -= 1;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_DATA}; goto check; }
yy108:
	yych = *++YYCURSOR;
	if (yych == 'S') goto yy114;
	goto yy57;
yy109:
	yych = *++YYCURSOR;
	if (yych == 'C') goto yy115;
	goto yy49;
yy110:
	yych = *++YYCURSOR;
	if (yych == 'R') goto yy116;
	goto yy49;
yy111:
	yych = *++YYCURSOR;
	if (yych == '0') goto yy117;
	goto yy57;
yy112:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy118;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy118;
	goto yy57;
yy113:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy119;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy119;
	goto yy57;
yy114:
	yych = *++YYCURSOR;
	if (yych == 'O') goto yy120;
	goto yy57;
yy115:
	yych = *++YYCURSOR;
	if (yych == ';') goto yy121;
	goto yy49;
yy116:
	yych = *++YYCURSOR;
	if (yych == ';') goto yy123;
	goto yy49;
yy117:
	yych = *++YYCURSOR;
	if (yych == '3') goto yy125;
	goto yy57;
yy118:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy126;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy126;
	goto yy57;
yy119:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy127;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy127;
	goto yy57;
yy120:
	yych = *++YYCURSOR;
	if (yych == '-') goto yy128;
	goto yy57;
yy121:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_ENDSEC}; goto check; }
yy123:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_HEADER}; goto check; }
yy125:
	yych = *++YYCURSOR;
	if (yych == '0') goto yy129;
	goto yy57;
yy126:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy130;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy130;
	goto yy57;
yy127:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy131;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy131;
	goto yy57;
yy128:
	yych = *++YYCURSOR;
	if (yych == '1') goto yy132;
	goto yy57;
yy129:
	yych = *++YYCURSOR;
	if (yych == '3') goto yy133;
	goto yy57;
yy130:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '@') {
		if (yych <= '/') goto yy57;
		if (yych <= '9') goto yy112;
		goto yy57;
	} else {
		if (yych <= 'F') goto yy112;
		if (yych == '\\') goto yy134;
		goto yy57;
	}
yy131:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy135;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy135;
	goto yy57;
yy132:
	yych = *++YYCURSOR;
	if (yych == '0') goto yy136;
	goto yy57;
yy133:
	yych = *++YYCURSOR;
	if (yych == '-') goto yy137;
	goto yy57;
yy134:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == 'X') goto yy138;
	goto yy57;
yy135:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy139;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy139;
	goto yy57;
yy136:
	yych = *++YYCURSOR;
	if (yych == '3') goto yy140;
	goto yy57;
yy137:
	yych = *++YYCURSOR;
	if (yych == '2') goto yy141;
	goto yy57;
yy138:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '0') goto yy81;
	goto yy57;
yy139:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy142;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy142;
	goto yy57;
yy140:
	yych = *++YYCURSOR;
	if (yych == '0') goto yy143;
	goto yy57;
yy141:
	yych = *++YYCURSOR;
	if (yych == '1') goto yy144;
	goto yy57;
yy142:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy57;
	if (yych <= '9') goto yy145;
	if (yych <= '@') goto yy57;
	if (yych <= 'F') goto yy145;
	goto yy57;
yy143:
	yych = *++YYCURSOR;
	if (yych == '3') goto yy146;
	goto yy57;
yy144:
	yych = *++YYCURSOR;
	if (yych == ';') goto yy147;
	goto yy57;
yy145:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '@') {
		if (yych <= '/') goto yy57;
		if (yych <= '9') goto yy113;
		goto yy57;
	} else {
		if (yych <= 'F') goto yy113;
		if (yych == '\\') goto yy134;
		goto yy57;
	}
yy146:
	yych = *++YYCURSOR;
	if (yych == '-') goto yy149;
	goto yy57;
yy147:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_P21_START}; goto check; }
yy149:
	yych = *++YYCURSOR;
	if (yych != '2') goto yy57;
	yych = *++YYCURSOR;
	if (yych != '1') goto yy57;
	yych = *++YYCURSOR;
	if (yych != ';') goto yy57;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ sym = (Symbol){T_P21_END}; goto check; }
}

check:
        if (LOOKAHEAD(sym, u0, u1, u2, T_EOF)) {
            PUSH_SYMBOL(sym.token, sym.vtype);
            break;
        }
    }
    
    return;
    
err:
    fprintf(stderr, "fatal, failed to resolve follow set (%c, %c, %c)\n", u0, u1, u2);
    exit(1);
}


/*
 * P21Parser
 */
void p21_parse(P21Parser *p, P21ParserActions *act) {
    if (act->ud_init_cb)
        act->ud_init_cb(act->userdata);
    
    p21_exchange_file(p, act);
    
    if (act->ud_exit_cb)
        act->ud_exit_cb(act->userdata);

    assert(p->stack->idx_top == 1);    
    return;

err:    
    report_error(p, "exchange_file' << 0 >>\n");
}

void p21_exchange_file(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;
    
    while (in->nsym < 1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 13) YYFILL(13);
	yych = *YYCURSOR;
	if (yych <= 0x001F) {
		if (yych <= '\n') {
			if (yych >= '\n') goto yy158;
		} else {
			if (yych == '\r') goto yy160;
		}
	} else {
		if (yych <= '/') {
			if (yych <= ' ') goto yy161;
			if (yych >= '/') goto yy164;
		} else {
			if (yych == 'I') goto yy165;
		}
	}
	++YYCURSOR;
yy157:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy158:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy160:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy158;
	goto yy157;
yy161:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy161;
	{ n = in->cur - in->sp; }
	{ continue; }
yy164:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy166;
	goto yy157;
yy165:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == 'S') goto yy168;
	goto yy157;
yy166:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yy168:
	yych = *++YYCURSOR;
	if (yych == 'O') goto yy170;
yy169:
	YYCURSOR = YYMARKER;
	goto yy157;
yy170:
	yych = *++YYCURSOR;
	if (yych != '-') goto yy169;
	yych = *++YYCURSOR;
	if (yych != '1') goto yy169;
	yych = *++YYCURSOR;
	if (yych != '0') goto yy169;
	yych = *++YYCURSOR;
	if (yych != '3') goto yy169;
	yych = *++YYCURSOR;
	if (yych != '0') goto yy169;
	yych = *++YYCURSOR;
	if (yych != '3') goto yy169;
	yych = *++YYCURSOR;
	if (yych != '-') goto yy169;
	yych = *++YYCURSOR;
	if (yych != '2') goto yy169;
	yych = *++YYCURSOR;
	if (yych != '1') goto yy169;
	yych = *++YYCURSOR;
	if (yych != ';') goto yy169;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_P21_START); continue;}
}

    }
    PUSH_TERMINAL(p->stack, lpop(in, T_P21_START));

    p21_header_section(p, act);
    p21_data_section_list(p, act);

    PUSH_TERMINAL(p->stack, lpop(in, T_P21_END));
    
    if (p->error)
        goto err;
    
    /* user action */
    if (act->exchange_file_cb)
        act->exchange_file_cb(p, bsp, act->userdata);
    
    /* default reduction */
    p->stack->items[bsp] = (Symbol){P_FILE};
    drop(p->stack, p->stack->idx_top - bsp - 1);
    
    return;

err:
    report_error(p, "exchange_file << 1 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_FILE);
    else default_error_handler(p, bsp, P_FILE);
    recover(in, T_EOF);
}

void p21_header_section(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;
    
    while (in->nsym < 1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
	yych = *YYCURSOR;
	if (yych <= 0x001F) {
		if (yych <= '\n') {
			if (yych >= '\n') goto yya186;
		} else {
			if (yych == '\r') goto yya188;
		}
	} else {
		if (yych <= '/') {
			if (yych <= ' ') goto yya189;
			if (yych >= '/') goto yya192;
		} else {
			if (yych == 'H') goto yya193;
		}
	}
	++YYCURSOR;
yya185:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yya186:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yya188:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yya186;
	goto yya185;
yya189:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yya189;
	{ n = in->cur - in->sp; }
	{ continue; }
yya192:
	yych = *++YYCURSOR;
	if (yych == '*') goto yya194;
	goto yya185;
yya193:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == 'E') goto yya196;
	goto yya185;
yya194:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yya196:
	yych = *++YYCURSOR;
	if (yych == 'A') goto yya198;
yya197:
	YYCURSOR = YYMARKER;
	goto yya185;
yya198:
	yych = *++YYCURSOR;
	if (yych != 'D') goto yya197;
	yych = *++YYCURSOR;
	if (yych != 'E') goto yya197;
	yych = *++YYCURSOR;
	if (yych != 'R') goto yya197;
	yych = *++YYCURSOR;
	if (yych != ';') goto yya197;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_HEADER); continue; }
}

    }
    PUSH_TERMINAL(p->stack, lpop(in, T_HEADER));

    /* section callback */
    if (act->header_start_cb)
        act->header_start_cb(p, bsp, act->userdata);
    
    /* mandatory headers */
    p21_header_entity(p, act);
    p21_header_entity(p, act);
    p21_header_entity(p, act);
   
    while (in->nsym < 1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
	yych = *YYCURSOR;
	if (yych <= '/') {
		if (yych <= '\r') {
			if (yych == '\n') goto yyb208;
			if (yych >= '\r') goto yyb210;
		} else {
			if (yych <= ' ') {
				if (yych >= ' ') goto yyb211;
			} else {
				if (yych <= '!') goto yyb214;
				if (yych >= '/') goto yyb215;
			}
		}
	} else {
		if (yych <= 'Z') {
			if (yych <= '@') goto yyb206;
			if (yych == 'E') goto yyb219;
			goto yyb216;
		} else {
			if (yych <= '_') {
				if (yych >= '_') goto yyb216;
			} else {
				if (yych <= '`') goto yyb206;
				if (yych <= 'z') goto yyb216;
			}
		}
	}
yyb206:
	++YYCURSOR;
yyb207:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yyb208:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yyb210:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yyb208;
	goto yyb207;
yyb211:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yyb211;
	{ n = in->cur - in->sp; }
	{ continue; }
yyb214:
	yych = *++YYCURSOR;
	if (yych <= '^') {
		if (yych <= '@') goto yyb207;
		if (yych <= 'Z') goto yyb216;
		goto yyb207;
	} else {
		if (yych == '`') goto yyb207;
		if (yych <= 'z') goto yyb216;
		goto yyb207;
	}
yyb215:
	yych = *++YYCURSOR;
	if (yych == '*') goto yyb220;
	goto yyb207;
yyb216:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
yyb217:
	if (yych <= 'Z') {
		if (yych <= '/') goto yyb218;
		if (yych <= '9') goto yyb216;
		if (yych >= 'A') goto yyb216;
	} else {
		if (yych <= '_') {
			if (yych >= '_') goto yyb216;
		} else {
			if (yych <= '`') goto yyb218;
			if (yych <= 'z') goto yyb216;
		}
	}
yyb218:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_KEYWORD); continue; }
yyb219:
	yych = *++YYCURSOR;
	if (yych == 'N') goto yyb222;
	goto yyb217;
yyb220:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yyb222:
	yych = *++YYCURSOR;
	if (yych != 'D') goto yyb217;
	yych = *++YYCURSOR;
	if (yych != 'S') goto yyb217;
	yych = *++YYCURSOR;
	if (yych != 'E') goto yyb217;
	yych = *++YYCURSOR;
	if (yych != 'C') goto yyb217;
	yych = *++YYCURSOR;
	if (yych != ';') goto yyb217;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_ENDSEC); continue; }
}

    }
    
    /* optional headers */
    if (LOOKAHEAD(in->sym[0], T_KEYWORD))
        p21_header_entity_list(p, act);

    PUSH_TERMINAL(p->stack, lpop(in, T_ENDSEC));

    if (p->error)
        goto err;
    
    /* default reduction */
    p->stack->items[bsp] = (Symbol){P_HEADERSECTION};
    drop(p->stack, p->stack->idx_top - bsp - 1);
    
    return;
    
err:
    report_error(p, "header_section << 2 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_HEADERSECTION);
    else default_error_handler(p, bsp, P_HEADERSECTION);
    recover(in, T_DATA);
}

void p21_data_section_list(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    uint32_t len = 0;
    Input *in = p->in;

    do {
        while (in->nsym < 1) {
            in->sp = in->cur;
            
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 17) YYFILL(17);
	yych = *YYCURSOR;
	if (yych <= ' ') {
		if (yych <= '\f') {
			if (yych == '\n') goto yy233;
		} else {
			if (yych <= '\r') goto yy235;
			if (yych >= ' ') goto yy236;
		}
	} else {
		if (yych <= 'C') {
			if (yych == '/') goto yy239;
		} else {
			if (yych <= 'D') goto yy240;
			if (yych <= 'E') goto yy241;
		}
	}
	++YYCURSOR;
yy232:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy233:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy235:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy233;
	goto yy232;
yy236:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy236;
	{ n = in->cur - in->sp; }
	{ continue; }
yy239:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy242;
	goto yy232;
yy240:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == 'A') goto yy244;
	goto yy232;
yy241:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == 'N') goto yy246;
	goto yy232;
yy242:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yy244:
	yych = *++YYCURSOR;
	if (yych == 'T') goto yy247;
yy245:
	YYCURSOR = YYMARKER;
	goto yy232;
yy246:
	yych = *++YYCURSOR;
	if (yych == 'D') goto yy248;
	goto yy245;
yy247:
	yych = *++YYCURSOR;
	if (yych == 'A') goto yy249;
	goto yy245;
yy248:
	yych = *++YYCURSOR;
	if (yych == '-') goto yy250;
	goto yy245;
yy249:
	yych = *++YYCURSOR;
	if (yych <= ')') {
		if (yych == ' ') goto yy251;
		if (yych <= '\'') goto yy245;
		goto yy251;
	} else {
		if (yych <= '/') {
			if (yych <= '.') goto yy245;
			goto yy251;
		} else {
			if (yych == ';') goto yy251;
			goto yy245;
		}
	}
yy250:
	yych = *++YYCURSOR;
	if (yych == 'I') goto yy253;
	goto yy245;
yy251:
	++YYCURSOR;
	YYCURSOR -= 1;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_DATA); continue; }
yy253:
	yych = *++YYCURSOR;
	if (yych != 'S') goto yy245;
	yych = *++YYCURSOR;
	if (yych != 'O') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '-') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '1') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '0') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '3') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '0') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '3') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '-') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '2') goto yy245;
	yych = *++YYCURSOR;
	if (yych != '1') goto yy245;
	yych = *++YYCURSOR;
	if (yych != ';') goto yy245;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_P21_END); continue; }
}

        }
        if (!LOOKAHEAD(in->sym[0], T_DATA))
            break;
        p21_data_section(p, act);
    } while (++len);

    /* one or more */
    if (!len) {
        push(p->stack, (Symbol){T_ERROR, T_DATA, 0, in->sym[0].lineno});
        p->error = true;
    }
    
    if(p->error)
        goto err;
    
    /* user action */
    if (act->data_section_list_cb)
        act->data_section_list_cb(p, bsp, act->userdata);

    /* default reduction */
    p->stack->items[bsp] = (Symbol){P_LIST};
    drop(p->stack, p->stack->idx_top - bsp - 1);
    
    return;
    
err:
    report_error(p, "data_section_list << 3 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_LIST);
    else default_error_handler(p, bsp, P_LIST);
    recover(in, T_P21_END);
}

void p21_data_section(P21Parser *p, P21ParserActions *act) {
    size_t n, cxt;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    while (in->nsym < 2) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= ' ') {
		if (yych <= '\f') {
			if (yych == '\n') goto yya271;
		} else {
			if (yych <= '\r') goto yya273;
			if (yych >= ' ') goto yya274;
		}
	} else {
		if (yych <= '.') {
			if (yych == '(') goto yya277;
		} else {
			if (yych <= '/') goto yya279;
			if (yych == ';') goto yya277;
		}
	}
	++YYCURSOR;
yya270:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yya271:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yya273:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yya271;
	goto yya270;
yya274:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yya274;
	{ n = in->cur - in->sp; }
	{ continue; }
yya277:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(*in->sp); continue; }
yya279:
	yych = *++YYCURSOR;
	if (yych != '*') goto yya270;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

    }
    PUSH_TERMINAL(p->stack, lpop(in, T_DATA));
    
    if (LOOKAHEAD(in->sym[0], '(')) {
        PUSH_TERMINAL(p->stack, lpop(in, '('));
        
        p21_parameter_list(p, act);
        while (in->nsym < 2) {
            in->sp = in->cur;
            
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= 0x001F) {
		if (yych <= '\n') {
			if (yych >= '\n') goto yyb286;
		} else {
			if (yych == '\r') goto yyb288;
		}
	} else {
		if (yych <= '/') {
			if (yych <= ' ') goto yyb289;
			if (yych >= '/') goto yyb292;
		} else {
			if (yych == ';') goto yyb293;
		}
	}
	++YYCURSOR;
yyb285:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yyb286:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yyb288:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yyb286;
	goto yyb285;
yyb289:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yyb289;
	{ n = in->cur - in->sp; }
	{ continue; }
yyb292:
	yych = *++YYCURSOR;
	if (yych == '*') goto yyb295;
	goto yyb285;
yyb293:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(';'); continue; }
yyb295:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

        }
        
        PUSH_TERMINAL(p->stack, lpop(in, ')'));
    }
    PUSH_TERMINAL(p->stack, lpop(in, ';'));
    
    if (act->data_start_cb)
        act->data_start_cb(p, bsp, act->userdata);

    while (in->nsym < 1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
	yych = *YYCURSOR;
	if (yych <= ' ') {
		if (yych <= '\f') {
			if (yych == '\n') goto yyc301;
		} else {
			if (yych <= '\r') goto yyc303;
			if (yych >= ' ') goto yyc304;
		}
	} else {
		if (yych <= '.') {
			if (yych == '#') goto yyc307;
		} else {
			if (yych <= '/') goto yyc308;
			if (yych == 'E') goto yyc309;
		}
	}
	++YYCURSOR;
yyc300:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yyc301:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yyc303:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yyc301;
	goto yyc300;
yyc304:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yyc304;
	{ n = in->cur - in->sp; }
	{ continue; }
yyc307:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yyc300;
	if (yych <= '9') goto yyc310;
	goto yyc300;
yyc308:
	yych = *++YYCURSOR;
	if (yych == '*') goto yyc313;
	goto yyc300;
yyc309:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == 'N') goto yyc315;
	goto yyc300;
yyc310:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yyc312;
	if (yych <= '9') goto yyc310;
yyc312:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_EID); continue; }
yyc313:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yyc315:
	yych = *++YYCURSOR;
	if (yych == 'D') goto yyc317;
yyc316:
	YYCURSOR = YYMARKER;
	goto yyc300;
yyc317:
	yych = *++YYCURSOR;
	if (yych != 'S') goto yyc316;
	yych = *++YYCURSOR;
	if (yych != 'E') goto yyc316;
	yych = *++YYCURSOR;
	if (yych != 'C') goto yyc316;
	yych = *++YYCURSOR;
	if (yych != ';') goto yyc316;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_ENDSEC); continue; }
}

    }
    if (LOOKAHEAD(in->sym[0], T_EID))
        p21_entity_instance_list(p, act);
    
    PUSH_TERMINAL(p->stack, lpop(in, T_ENDSEC));
    
    if (p->error)
        goto err;
    
    /* default reduction */
    p->stack->items[bsp] = (Symbol){P_DATASECTION};
    drop(p->stack, p->stack->idx_top - bsp - 1);
    
    return;

err:
    report_error(p, "data_section << 4 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_DATASECTION);
    else default_error_handler(p, bsp, P_DATASECTION);
    recover(in, T_P21_END, T_DATA);
}

void p21_header_entity(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;
    
    /* set KEYWORD as basemrk to prevent fill() recycling the buffer before user action */
    while (in->nsym < 1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= '.') {
		if (yych <= '\r') {
			if (yych == '\n') goto yy327;
			if (yych >= '\r') goto yy329;
		} else {
			if (yych <= 0x001F) goto yy325;
			if (yych <= ' ') goto yy330;
			if (yych <= '!') goto yy333;
		}
	} else {
		if (yych <= '^') {
			if (yych <= '/') goto yy334;
			if (yych <= '@') goto yy325;
			if (yych <= 'Z') goto yy335;
		} else {
			if (yych == '`') goto yy325;
			if (yych <= 'z') goto yy335;
		}
	}
yy325:
	++YYCURSOR;
yy326:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy327:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy329:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy327;
	goto yy326;
yy330:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy330;
	{ n = in->cur - in->sp; }
	{ continue; }
yy333:
	yych = *++YYCURSOR;
	if (yych <= '^') {
		if (yych <= '@') goto yy326;
		if (yych <= 'Z') goto yy335;
		goto yy326;
	} else {
		if (yych == '`') goto yy326;
		if (yych <= 'z') goto yy335;
		goto yy326;
	}
yy334:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy338;
	goto yy326;
yy335:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= 'Z') {
		if (yych <= '/') goto yy337;
		if (yych <= '9') goto yy335;
		if (yych >= 'A') goto yy335;
	} else {
		if (yych <= '_') {
			if (yych >= '_') goto yy335;
		} else {
			if (yych <= '`') goto yy337;
			if (yych <= 'z') goto yy335;
		}
	}
yy337:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_KEYWORD); continue; }
yy338:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

    }
    
    /* set KEYWORD as basemrk to prevent fill() recycling the buffer before user action */
    assert(in->nsym == 1);
    in->basemrk += in->sym[0].offset;
    in->sym[0].offset = 0;

    p21_simple_record(p, act);
    
    while (in->nsym < 1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= 0x001F) {
		if (yych <= '\n') {
			if (yych >= '\n') goto yy344;
		} else {
			if (yych == '\r') goto yy346;
		}
	} else {
		if (yych <= '/') {
			if (yych <= ' ') goto yy347;
			if (yych >= '/') goto yy350;
		} else {
			if (yych == ';') goto yy351;
		}
	}
	++YYCURSOR;
yy343:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy344:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy346:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy344;
	goto yy343;
yy347:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy347;
	{ n = in->cur - in->sp; }
	{ continue; }
yy350:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy353;
	goto yy343;
yy351:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(';'); continue; }
yy353:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

    }
    PUSH_TERMINAL(p->stack, lpop(in, ';'));

    if (p->error)
        goto err;
    
    /* user action */
    if (act->header_entity_cb)
        act->header_entity_cb(p, bsp, act->userdata);

    /* reduction */
    assert(!p->hold);
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_HEADERENTITY};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }
    
    return;
    
err:
    report_error(p, "header_entity << 5 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_HEADERENTITY);
    else default_error_handler(p, bsp, P_HEADERENTITY);
    recover(in, T_ENDSEC, T_KEYWORD);
}

void p21_header_entity_list(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    p21_header_entity(p, act);
    
    do {
        while (in->nsym < 1) {
            in->sp = in->cur;
            
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
	yych = *YYCURSOR;
	if (yych <= '/') {
		if (yych <= '\r') {
			if (yych == '\n') goto yy359;
			if (yych >= '\r') goto yy361;
		} else {
			if (yych <= ' ') {
				if (yych >= ' ') goto yy362;
			} else {
				if (yych <= '!') goto yy365;
				if (yych >= '/') goto yy366;
			}
		}
	} else {
		if (yych <= 'Z') {
			if (yych <= '@') goto yy357;
			if (yych == 'E') goto yy370;
			goto yy367;
		} else {
			if (yych <= '_') {
				if (yych >= '_') goto yy367;
			} else {
				if (yych <= '`') goto yy357;
				if (yych <= 'z') goto yy367;
			}
		}
	}
yy357:
	++YYCURSOR;
yy358:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy359:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy361:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy359;
	goto yy358;
yy362:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy362;
	{ n = in->cur - in->sp; }
	{ continue; }
yy365:
	yych = *++YYCURSOR;
	if (yych <= '^') {
		if (yych <= '@') goto yy358;
		if (yych <= 'Z') goto yy367;
		goto yy358;
	} else {
		if (yych == '`') goto yy358;
		if (yych <= 'z') goto yy367;
		goto yy358;
	}
yy366:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy371;
	goto yy358;
yy367:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
yy368:
	if (yych <= 'Z') {
		if (yych <= '/') goto yy369;
		if (yych <= '9') goto yy367;
		if (yych >= 'A') goto yy367;
	} else {
		if (yych <= '_') {
			if (yych >= '_') goto yy367;
		} else {
			if (yych <= '`') goto yy369;
			if (yych <= 'z') goto yy367;
		}
	}
yy369:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_KEYWORD); continue; }
yy370:
	yych = *++YYCURSOR;
	if (yych == 'N') goto yy373;
	goto yy368;
yy371:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yy373:
	yych = *++YYCURSOR;
	if (yych != 'D') goto yy368;
	yych = *++YYCURSOR;
	if (yych != 'S') goto yy368;
	yych = *++YYCURSOR;
	if (yych != 'E') goto yy368;
	yych = *++YYCURSOR;
	if (yych != 'C') goto yy368;
	yych = *++YYCURSOR;
	if (yych != ';') goto yy368;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_ENDSEC); continue; }
}

        }
        if (!LOOKAHEAD(in->sym[0], T_KEYWORD))
            break;
        p21_header_entity(p, act);
    } while (1);
        
    if (p->error)
        goto err;
    
    
    /* user action */
    if (act->header_entity_list_cb)
        act->header_entity_list_cb(p, bsp, act->userdata);

    /* reduction */
    assert(!p->hold);
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_LIST};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }
    
    return;
    
err:
    report_error(p, "header_entity_list << 6 >>");
    if (act->error_cb) act->error_cb(p, bsp, P_LIST);
    else default_error_handler(p, bsp, P_LIST);
    recover(in, T_ENDSEC);
}

void p21_entity_instance_list(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    p21_entity_instance(p, act);
    
    do {
        while (in->nsym < 1) {
            in->sp = in->cur;
            
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 7) YYFILL(7);
	yych = *YYCURSOR;
	if (yych <= ' ') {
		if (yych <= '\f') {
			if (yych == '\n') goto yy384;
		} else {
			if (yych <= '\r') goto yy386;
			if (yych >= ' ') goto yy387;
		}
	} else {
		if (yych <= '.') {
			if (yych == '#') goto yy390;
		} else {
			if (yych <= '/') goto yy391;
			if (yych == 'E') goto yy392;
		}
	}
	++YYCURSOR;
yy383:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy384:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy386:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy384;
	goto yy383;
yy387:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy387;
	{ n = in->cur - in->sp; }
	{ continue; }
yy390:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy383;
	if (yych <= '9') goto yy393;
	goto yy383;
yy391:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy396;
	goto yy383;
yy392:
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych == 'N') goto yy398;
	goto yy383;
yy393:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy395;
	if (yych <= '9') goto yy393;
yy395:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_EID); continue; }
yy396:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yy398:
	yych = *++YYCURSOR;
	if (yych == 'D') goto yy400;
yy399:
	YYCURSOR = YYMARKER;
	goto yy383;
yy400:
	yych = *++YYCURSOR;
	if (yych != 'S') goto yy399;
	yych = *++YYCURSOR;
	if (yych != 'E') goto yy399;
	yych = *++YYCURSOR;
	if (yych != 'C') goto yy399;
	yych = *++YYCURSOR;
	if (yych != ';') goto yy399;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_ENDSEC); continue; }
}

        }
        if (!LOOKAHEAD(in->sym[0], T_EID))
            break;
        p21_entity_instance(p, act);
    } while (1);
    
    if (p->error)
        goto err;
    
    /* user action */
    if (act->entity_instance_list_cb)
        act->entity_instance_list_cb(p, bsp, act->userdata);

    /* reduction */
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_LIST};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }
    
    return;
    
err:
    report_error(p, "entity_instance_list << 7 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_LIST);
    else default_error_handler(p, bsp, P_LIST);
    recover(in, T_ENDSEC);
}

void p21_parameter_list(P21Parser *p, P21ParserActions *act) {    
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    p21_parameter(p, act);

    do {
        while (in->nsym < 1) {
            in->sp = in->cur;
            
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= ' ') {
		if (yych <= '\f') {
			if (yych == '\n') goto yy410;
		} else {
			if (yych <= '\r') goto yy412;
			if (yych >= ' ') goto yy413;
		}
	} else {
		if (yych <= '+') {
			if (yych == ')') goto yy416;
		} else {
			if (yych <= ',') goto yy416;
			if (yych == '/') goto yy418;
		}
	}
	++YYCURSOR;
yy409:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy410:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy412:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy410;
	goto yy409;
yy413:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy413;
	{ n = in->cur - in->sp; }
	{ continue; }
yy416:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(*in->sp); continue; }
yy418:
	yych = *++YYCURSOR;
	if (yych != '*') goto yy409;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

        }
        if (LOOKAHEAD(in->sym[0], ')'))
            break;

        PUSH_TERMINAL(p->stack, lpop(in, ','));
        p21_parameter(p, act);
    } while (1);

    if (p->error)
        goto err;
    
    /* user action */
    if (act->parameter_list_cb)
        act->parameter_list_cb(p, bsp, act->userdata);
    
    /* reduction */
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_LIST};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }

    return;
    
err:
    report_error(p, "parameter_list << 8 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_LIST);
    else default_error_handler(p, bsp, P_LIST);
    recover(in, ')', ';');
}

void p21_entity_instance(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    /* set EID as basemrk to prevent fill() recycling the buffer before user action */
    assert(in->nsym == 1);
    in->basemrk += in->sym[0].offset;
    in->sym[0].offset = 0;

    while (in->nsym < 3) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= '.') {
		if (yych <= 0x001F) {
			if (yych <= '\n') {
				if (yych >= '\n') goto yy425;
			} else {
				if (yych == '\r') goto yy427;
			}
		} else {
			if (yych <= '!') {
				if (yych <= ' ') goto yy428;
				goto yy431;
			} else {
				if (yych == '(') goto yy432;
			}
		}
	} else {
		if (yych <= 'Z') {
			if (yych <= '<') {
				if (yych <= '/') goto yy434;
			} else {
				if (yych <= '=') goto yy432;
				if (yych >= 'A') goto yy435;
			}
		} else {
			if (yych <= '_') {
				if (yych >= '_') goto yy435;
			} else {
				if (yych <= '`') goto yy423;
				if (yych <= 'z') goto yy435;
			}
		}
	}
yy423:
	++YYCURSOR;
yy424:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy425:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy427:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy425;
	goto yy424;
yy428:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy428;
	{ n = in->cur - in->sp; }
	{ continue; }
yy431:
	yych = *++YYCURSOR;
	if (yych <= '^') {
		if (yych <= '@') goto yy424;
		if (yych <= 'Z') goto yy435;
		goto yy424;
	} else {
		if (yych == '`') goto yy424;
		if (yych <= 'z') goto yy435;
		goto yy424;
	}
yy432:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(*in->sp); continue; }
yy434:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy438;
	goto yy424;
yy435:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= 'Z') {
		if (yych <= '/') goto yy437;
		if (yych <= '9') goto yy435;
		if (yych >= 'A') goto yy435;
	} else {
		if (yych <= '_') {
			if (yych >= '_') goto yy435;
		} else {
			if (yych <= '`') goto yy437;
			if (yych <= 'z') goto yy435;
		}
	}
yy437:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_KEYWORD); continue; }
yy438:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

    }
    if (!LOOKAHEAD(in->sym[0], T_EID) || !LOOKAHEAD(in->sym[1], '='))
        goto err;
        
    if (LOOKAHEAD(in->sym[2], T_KEYWORD)) {
        p21_simple_entity_instance(p, act);
    } else if (LOOKAHEAD(in->sym[2], '(')) {
        p21_complex_entity_instance(p, act);
    }

    if (p->error)
        goto err;
    
    /* user action */
    if (act->entity_instance_cb)
        act->entity_instance_cb(p, bsp, act->userdata);
    
    /* no default reduction */
    
    return;
    
err:
    report_error(p, "entity_instance << 9 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_LIST);
    else default_error_handler(p, bsp, P_LIST);
    recover(in, T_ENDSEC, T_EID);
}

void p21_simple_entity_instance(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    PUSH_TERMINAL(p->stack, lpop(in, T_EID));
    PUSH_TERMINAL(p->stack, lpop(in, '='));
    
    p21_simple_record(p, act);

    while (in->nsym < 1) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= 0x001F) {
		if (yych <= '\n') {
			if (yych >= '\n') goto yy444;
		} else {
			if (yych == '\r') goto yy446;
		}
	} else {
		if (yych <= '/') {
			if (yych <= ' ') goto yy447;
			if (yych >= '/') goto yy450;
		} else {
			if (yych == ';') goto yy451;
		}
	}
	++YYCURSOR;
yy443:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy444:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy446:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy444;
	goto yy443;
yy447:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy447;
	{ n = in->cur - in->sp; }
	{ continue; }
yy450:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy453;
	goto yy443;
yy451:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(';'); continue; }
yy453:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

    }
    PUSH_TERMINAL(p->stack, lpop(in, ';'));

    if (p->error)
        goto err;
    
    /* user action */
    if (act->simple_entity_instance_cb)
        act->simple_entity_instance_cb(p, bsp, act->userdata);

    /* reduction */
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_SIMPLEENTITY};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }

    return;
    
err:
    report_error(p, "simple_entity_instance << 10 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_SIMPLEENTITY);
    else default_error_handler(p, bsp, P_SIMPLEENTITY);
    recover(in, T_ENDSEC, T_EID);
}


void p21_complex_entity_instance(P21Parser *p, P21ParserActions *act) {
    size_t n, c;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    PUSH_TERMINAL(p->stack, lpop(in, T_EID));
    PUSH_TERMINAL(p->stack, lpop(in, '='));
    PUSH_TERMINAL_EXT(c, p->stack, lpop(in, '('));
    
    p21_simple_record_list(p, act);

    while (in->nsym < 2) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= 0x001F) {
		if (yych <= '\n') {
			if (yych >= '\n') goto yy459;
		} else {
			if (yych == '\r') goto yy461;
		}
	} else {
		if (yych <= '/') {
			if (yych <= ' ') goto yy462;
			if (yych >= '/') goto yy465;
		} else {
			if (yych == ';') goto yy466;
		}
	}
	++YYCURSOR;
yy458:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy459:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy461:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy459;
	goto yy458;
yy462:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy462;
	{ n = in->cur - in->sp; }
	{ continue; }
yy465:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy468;
	goto yy458;
yy466:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(';'); continue; }
yy468:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

    }
    
    PUSH_TERMINAL_EXT(c, p->stack, lpop(in, ')'));
    PUSH_TERMINAL(p->stack, lpop(in, ';'));

    if (p->error) 
        goto err;
    
    /* user action */
    if (act->complex_entity_instance_cb)
        act->complex_entity_instance_cb(p, bsp, act->userdata);

    /* reduction */
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_COMPLEXENTITY};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }
    
    return;
    
err:
    report_error(p, "complex_entity_instance << 11 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_COMPLEXENTITY);
    else default_error_handler(p, bsp, P_COMPLEXENTITY);
    recover(in, T_ENDSEC, T_EID);
}

void p21_simple_record(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    while (in->nsym < 3) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	unsigned int yyaccept = 0;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= ')') {
		if (yych <= ' ') {
			if (yych <= '\f') {
				if (yych == '\n') goto yy474;
			} else {
				if (yych <= '\r') goto yy476;
				if (yych >= ' ') goto yy477;
			}
		} else {
			if (yych <= '#') {
				if (yych <= '!') goto yy480;
				if (yych <= '"') goto yy481;
				goto yy482;
			} else {
				if (yych <= '$') goto yy483;
				if (yych <= '&') goto yy472;
				if (yych <= '\'') goto yy485;
				goto yy486;
			}
		}
	} else {
		if (yych <= '9') {
			if (yych <= ',') {
				if (yych <= '*') goto yy488;
				if (yych <= '+') goto yy490;
			} else {
				if (yych <= '-') goto yy490;
				if (yych <= '.') goto yy491;
				if (yych <= '/') goto yy492;
				goto yy493;
			}
		} else {
			if (yych <= '^') {
				if (yych <= '@') goto yy472;
				if (yych <= 'Z') goto yy496;
			} else {
				if (yych == '`') goto yy472;
				if (yych <= 'z') goto yy496;
			}
		}
	}
yy472:
	++YYCURSOR;
yy473:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy474:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy476:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy474;
	goto yy473;
yy477:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy477;
	{ n = in->cur - in->sp; }
	{ continue; }
yy480:
	yych = *++YYCURSOR;
	if (yych <= '^') {
		if (yych <= '@') goto yy473;
		if (yych <= 'Z') goto yy496;
		goto yy473;
	} else {
		if (yych == '`') goto yy473;
		if (yych <= 'z') goto yy496;
		goto yy473;
	}
yy481:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '/') goto yy473;
	if (yych <= '3') goto yy499;
	goto yy473;
yy482:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yy473;
	if (yych <= '9') goto yy502;
	goto yy473;
yy483:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_EMPTY); continue; }
yy485:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '[') {
		if (yych <= 0x001F) goto yy473;
		if (yych <= 'Z') goto yy506;
		goto yy473;
	} else {
		if (yych == ']') goto yy473;
		if (yych <= '~') goto yy506;
		goto yy473;
	}
yy486:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(*in->sp); continue; }
yy488:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_DERIVED); continue; }
yy490:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= ',') {
		if (yych == '+') goto yy510;
		goto yy473;
	} else {
		if (yych <= '-') goto yy510;
		if (yych <= '/') goto yy473;
		if (yych <= '9') goto yy493;
		goto yy473;
	}
yy491:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '@') goto yy473;
	if (yych <= 'Z') goto yy512;
	if (yych == '_') goto yy512;
	goto yy473;
yy492:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy514;
	goto yy473;
yy493:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '.') goto yy516;
	if (yych <= '/') goto yy495;
	if (yych <= '9') goto yy493;
yy495:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_INTEGER); continue; }
yy496:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= 'Z') {
		if (yych <= '/') goto yy498;
		if (yych <= '9') goto yy496;
		if (yych >= 'A') goto yy496;
	} else {
		if (yych <= '_') {
			if (yych >= '_') goto yy496;
		} else {
			if (yych <= '`') goto yy498;
			if (yych <= 'z') goto yy496;
		}
	}
yy498:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_KEYWORD); continue; }
yy499:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') {
		if (yych == '"') goto yy519;
	} else {
		if (yych <= '9') goto yy499;
		if (yych <= '@') goto yy501;
		if (yych <= 'F') goto yy499;
	}
yy501:
	YYCURSOR = YYMARKER;
	if (yyaccept <= 1) {
		if (yyaccept == 0) {
			goto yy473;
		} else {
			goto yy508;
		}
	} else {
		goto yy518;
	}
yy502:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy504;
	if (yych <= '9') goto yy502;
yy504:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_EID); continue; }
yy505:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
yy506:
	if (yych <= 'Z') {
		if (yych <= 0x001F) goto yy501;
		if (yych != '\'') goto yy505;
	} else {
		if (yych <= '\\') {
			if (yych <= '[') goto yy501;
			goto yy509;
		} else {
			if (yych <= ']') goto yy501;
			if (yych <= '~') goto yy505;
			goto yy501;
		}
	}
	yyaccept = 1;
	YYMARKER = ++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\'') goto yy505;
yy508:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_STRING); continue; }
yy509:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= 'S') {
		if (yych <= '@') goto yy501;
		if (yych <= 'I') goto yy521;
		if (yych <= 'R') goto yy501;
		goto yy522;
	} else {
		if (yych <= 'X') {
			if (yych <= 'W') goto yy501;
			goto yy523;
		} else {
			if (yych == '\\') goto yy505;
			goto yy501;
		}
	}
yy510:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= ',') {
		if (yych == '+') goto yy510;
		goto yy501;
	} else {
		if (yych <= '-') goto yy510;
		if (yych <= '/') goto yy501;
		if (yych <= '9') goto yy493;
		goto yy501;
	}
yy512:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '9') {
		if (yych == '.') goto yy524;
		if (yych <= '/') goto yy501;
		goto yy512;
	} else {
		if (yych <= 'Z') {
			if (yych <= '@') goto yy501;
			goto yy512;
		} else {
			if (yych == '_') goto yy512;
			goto yy501;
		}
	}
yy514:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yy516:
	yyaccept = 2;
	YYMARKER = ++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy518;
	if (yych <= '9') goto yy516;
	if (yych == 'E') goto yy526;
yy518:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_REAL); continue; }
yy519:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_BINARY); continue; }
yy521:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yy505;
	goto yy501;
yy522:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yy528;
	goto yy501;
yy523:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '3') {
		if (yych == '2') goto yy529;
		goto yy501;
	} else {
		if (yych <= '4') goto yy530;
		if (yych == '\\') goto yy531;
		goto yy501;
	}
yy524:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_ENUMERATION); continue; }
yy526:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= ',') {
		if (yych == '+') goto yy526;
		goto yy501;
	} else {
		if (yych <= '-') goto yy526;
		if (yych <= '/') goto yy501;
		if (yych <= '9') goto yy532;
		goto yy501;
	}
yy528:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '[') {
		if (yych <= 0x001F) goto yy501;
		if (yych <= 'Z') goto yy505;
		goto yy501;
	} else {
		if (yych == ']') goto yy501;
		if (yych <= '~') goto yy505;
		goto yy501;
	}
yy529:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yy534;
	goto yy501;
yy530:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yy535;
	goto yy501;
yy531:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy536;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy536;
	goto yy501;
yy532:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy518;
	if (yych <= '9') goto yy532;
	goto yy518;
yy534:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy537;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy537;
	goto yy501;
yy535:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy538;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy538;
	goto yy501;
yy536:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy505;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy505;
	goto yy501;
yy537:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy539;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy539;
	goto yy501;
yy538:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy540;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy540;
	goto yy501;
yy539:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy541;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy541;
	goto yy501;
yy540:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy542;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy542;
	goto yy501;
yy541:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy543;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy543;
	goto yy501;
yy542:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy544;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy544;
	goto yy501;
yy543:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '@') {
		if (yych <= '/') goto yy501;
		if (yych <= '9') goto yy537;
		goto yy501;
	} else {
		if (yych <= 'F') goto yy537;
		if (yych == '\\') goto yy545;
		goto yy501;
	}
yy544:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy546;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy546;
	goto yy501;
yy545:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == 'X') goto yy547;
	goto yy501;
yy546:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy548;
	if (yych <= '@') goto yy501;
	if (yych <= 'F') goto yy548;
	goto yy501;
yy547:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '0') goto yy521;
	goto yy501;
yy548:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy549;
	if (yych <= '@') goto yy501;
	if (yych >= 'G') goto yy501;
yy549:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yy501;
	if (yych <= '9') goto yy550;
	if (yych <= '@') goto yy501;
	if (yych >= 'G') goto yy501;
yy550:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '@') {
		if (yych <= '/') goto yy501;
		if (yych <= '9') goto yy538;
		goto yy501;
	} else {
		if (yych <= 'F') goto yy538;
		if (yych == '\\') goto yy545;
		goto yy501;
	}
}

    }

    PUSH_TERMINAL(p->stack, lpop(in, T_KEYWORD));
    PUSH_TERMINAL_EXT(n, p->stack, lpop(in, '('));
    
    if (LOOKAHEAD(in->sym[0], '(', T_KEYWORD, T_VARIANT))
        p21_parameter_list(p, act);

    PUSH_TERMINAL_EXT(n, p->stack, lpop(in, ')'));

    if (p->error)
        goto err;
    
    /* user action */
    if (act->simple_record_cb)
        act->simple_record_cb(p, bsp, act->userdata);
    
    /* reduction */
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_SIMPLERECORD};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }
    
    return;
    
err:
    report_error(p, "simple_record << 12 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_SIMPLERECORD);
    else default_error_handler(p, bsp, P_SIMPLERECORD);
    recover(in, ';', ')', T_KEYWORD);
}

void p21_simple_record_list(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    p21_simple_record(p, act);
    
    do {
        while (in->nsym < 1) {
            in->sp = in->cur;
            
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= ')') {
		if (yych <= '\r') {
			if (yych == '\n') goto yy555;
			if (yych >= '\r') goto yy557;
		} else {
			if (yych <= ' ') {
				if (yych >= ' ') goto yy558;
			} else {
				if (yych <= '!') goto yy561;
				if (yych >= ')') goto yy562;
			}
		}
	} else {
		if (yych <= 'Z') {
			if (yych == '/') goto yy564;
			if (yych >= 'A') goto yy565;
		} else {
			if (yych <= '_') {
				if (yych >= '_') goto yy565;
			} else {
				if (yych <= '`') goto yy553;
				if (yych <= 'z') goto yy565;
			}
		}
	}
yy553:
	++YYCURSOR;
yy554:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yy555:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yy557:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yy555;
	goto yy554;
yy558:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yy558;
	{ n = in->cur - in->sp; }
	{ continue; }
yy561:
	yych = *++YYCURSOR;
	if (yych <= '^') {
		if (yych <= '@') goto yy554;
		if (yych <= 'Z') goto yy565;
		goto yy554;
	} else {
		if (yych == '`') goto yy554;
		if (yych <= 'z') goto yy565;
		goto yy554;
	}
yy562:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(')'); continue; }
yy564:
	yych = *++YYCURSOR;
	if (yych == '*') goto yy568;
	goto yy554;
yy565:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= 'Z') {
		if (yych <= '/') goto yy567;
		if (yych <= '9') goto yy565;
		if (yych >= 'A') goto yy565;
	} else {
		if (yych <= '_') {
			if (yych >= '_') goto yy565;
		} else {
			if (yych <= '`') goto yy567;
			if (yych <= 'z') goto yy565;
		}
	}
yy567:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_KEYWORD); continue; }
yy568:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

        }
        if (!LOOKAHEAD(in->sym[0], T_KEYWORD))
            break;
        p21_simple_record(p, act);
    } while (1);

    if (p->error)
        goto err;
    
    /* user action */
    if (act->simple_record_list_cb)
        act->simple_record_list_cb(p, bsp, act->userdata);

    /* reduction */
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_LIST};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }
    
    return;
    
err:
    report_error(p, "simple_record_list << 13 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_LIST);
    else default_error_handler(p, bsp, P_LIST);
    recover(in, ')', ';');
}

void p21_parameter(P21Parser *p, P21ParserActions *act) {
    size_t n;
    uint32_t bsp = p->stack->idx_top;
    Input *in = p->in;

    while (in->nsym < 2) {
        in->sp = in->cur;
        
{
	YYCTYPE yych;
	unsigned int yyaccept = 0;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= ')') {
		if (yych <= ' ') {
			if (yych <= '\f') {
				if (yych == '\n') goto yya574;
			} else {
				if (yych <= '\r') goto yya576;
				if (yych >= ' ') goto yya577;
			}
		} else {
			if (yych <= '#') {
				if (yych <= '!') goto yya580;
				if (yych <= '"') goto yya581;
				goto yya582;
			} else {
				if (yych <= '$') goto yya583;
				if (yych <= '&') goto yya572;
				if (yych <= '\'') goto yya585;
				goto yya586;
			}
		}
	} else {
		if (yych <= '9') {
			if (yych <= ',') {
				if (yych <= '*') goto yya588;
				if (yych <= '+') goto yya590;
				goto yya586;
			} else {
				if (yych <= '-') goto yya590;
				if (yych <= '.') goto yya591;
				if (yych <= '/') goto yya592;
				goto yya593;
			}
		} else {
			if (yych <= '^') {
				if (yych <= '@') goto yya572;
				if (yych <= 'Z') goto yya596;
			} else {
				if (yych == '`') goto yya572;
				if (yych <= 'z') goto yya596;
			}
		}
	}
yya572:
	++YYCURSOR;
yya573:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yya574:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yya576:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yya574;
	goto yya573;
yya577:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yya577;
	{ n = in->cur - in->sp; }
	{ continue; }
yya580:
	yych = *++YYCURSOR;
	if (yych <= '^') {
		if (yych <= '@') goto yya573;
		if (yych <= 'Z') goto yya596;
		goto yya573;
	} else {
		if (yych == '`') goto yya573;
		if (yych <= 'z') goto yya596;
		goto yya573;
	}
yya581:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '/') goto yya573;
	if (yych <= '3') goto yya599;
	goto yya573;
yya582:
	yych = *++YYCURSOR;
	if (yych <= '/') goto yya573;
	if (yych <= '9') goto yya602;
	goto yya573;
yya583:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_EMPTY); continue; }
yya585:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '[') {
		if (yych <= 0x001F) goto yya573;
		if (yych <= 'Z') goto yya606;
		goto yya573;
	} else {
		if (yych == ']') goto yya573;
		if (yych <= '~') goto yya606;
		goto yya573;
	}
yya586:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(*in->sp); continue; }
yya588:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_DERIVED); continue; }
yya590:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= ',') {
		if (yych == '+') goto yya610;
		goto yya573;
	} else {
		if (yych <= '-') goto yya610;
		if (yych <= '/') goto yya573;
		if (yych <= '9') goto yya593;
		goto yya573;
	}
yya591:
	yyaccept = 0;
	yych = *(YYMARKER = ++YYCURSOR);
	if (yych <= '@') goto yya573;
	if (yych <= 'Z') goto yya612;
	if (yych == '_') goto yya612;
	goto yya573;
yya592:
	yych = *++YYCURSOR;
	if (yych == '*') goto yya614;
	goto yya573;
yya593:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '.') goto yya616;
	if (yych <= '/') goto yya595;
	if (yych <= '9') goto yya593;
yya595:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_INTEGER); continue; }
yya596:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= 'Z') {
		if (yych <= '/') goto yya598;
		if (yych <= '9') goto yya596;
		if (yych >= 'A') goto yya596;
	} else {
		if (yych <= '_') {
			if (yych >= '_') goto yya596;
		} else {
			if (yych <= '`') goto yya598;
			if (yych <= 'z') goto yya596;
		}
	}
yya598:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_KEYWORD); continue; }
yya599:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') {
		if (yych == '"') goto yya619;
	} else {
		if (yych <= '9') goto yya599;
		if (yych <= '@') goto yya601;
		if (yych <= 'F') goto yya599;
	}
yya601:
	YYCURSOR = YYMARKER;
	if (yyaccept <= 1) {
		if (yyaccept == 0) {
			goto yya573;
		} else {
			goto yya608;
		}
	} else {
		goto yya618;
	}
yya602:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya604;
	if (yych <= '9') goto yya602;
yya604:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_EID); continue; }
yya605:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
yya606:
	if (yych <= 'Z') {
		if (yych <= 0x001F) goto yya601;
		if (yych != '\'') goto yya605;
	} else {
		if (yych <= '\\') {
			if (yych <= '[') goto yya601;
			goto yya609;
		} else {
			if (yych <= ']') goto yya601;
			if (yych <= '~') goto yya605;
			goto yya601;
		}
	}
	yyaccept = 1;
	YYMARKER = ++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\'') goto yya605;
yya608:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_STRING); continue; }
yya609:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= 'S') {
		if (yych <= '@') goto yya601;
		if (yych <= 'I') goto yya621;
		if (yych <= 'R') goto yya601;
		goto yya622;
	} else {
		if (yych <= 'X') {
			if (yych <= 'W') goto yya601;
			goto yya623;
		} else {
			if (yych == '\\') goto yya605;
			goto yya601;
		}
	}
yya610:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= ',') {
		if (yych == '+') goto yya610;
		goto yya601;
	} else {
		if (yych <= '-') goto yya610;
		if (yych <= '/') goto yya601;
		if (yych <= '9') goto yya593;
		goto yya601;
	}
yya612:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '9') {
		if (yych == '.') goto yya624;
		if (yych <= '/') goto yya601;
		goto yya612;
	} else {
		if (yych <= 'Z') {
			if (yych <= '@') goto yya601;
			goto yya612;
		} else {
			if (yych == '_') goto yya612;
			goto yya601;
		}
	}
yya614:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
yya616:
	yyaccept = 2;
	YYMARKER = ++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya618;
	if (yych <= '9') goto yya616;
	if (yych == 'E') goto yya626;
yya618:
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_REAL); continue; }
yya619:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_BINARY); continue; }
yya621:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yya605;
	goto yya601;
yya622:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yya628;
	goto yya601;
yya623:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '3') {
		if (yych == '2') goto yya629;
		goto yya601;
	} else {
		if (yych <= '4') goto yya630;
		if (yych == '\\') goto yya631;
		goto yya601;
	}
yya624:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(T_VARIANT, V_ENUMERATION); continue; }
yya626:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= ',') {
		if (yych == '+') goto yya626;
		goto yya601;
	} else {
		if (yych <= '-') goto yya626;
		if (yych <= '/') goto yya601;
		if (yych <= '9') goto yya632;
		goto yya601;
	}
yya628:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '[') {
		if (yych <= 0x001F) goto yya601;
		if (yych <= 'Z') goto yya605;
		goto yya601;
	} else {
		if (yych == ']') goto yya601;
		if (yych <= '~') goto yya605;
		goto yya601;
	}
yya629:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yya634;
	goto yya601;
yya630:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '\\') goto yya635;
	goto yya601;
yya631:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya636;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya636;
	goto yya601;
yya632:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya618;
	if (yych <= '9') goto yya632;
	goto yya618;
yya634:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya637;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya637;
	goto yya601;
yya635:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya638;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya638;
	goto yya601;
yya636:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya605;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya605;
	goto yya601;
yya637:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya639;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya639;
	goto yya601;
yya638:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya640;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya640;
	goto yya601;
yya639:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya641;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya641;
	goto yya601;
yya640:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya642;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya642;
	goto yya601;
yya641:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya643;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya643;
	goto yya601;
yya642:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya644;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya644;
	goto yya601;
yya643:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '@') {
		if (yych <= '/') goto yya601;
		if (yych <= '9') goto yya637;
		goto yya601;
	} else {
		if (yych <= 'F') goto yya637;
		if (yych == '\\') goto yya645;
		goto yya601;
	}
yya644:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya646;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya646;
	goto yya601;
yya645:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == 'X') goto yya647;
	goto yya601;
yya646:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya648;
	if (yych <= '@') goto yya601;
	if (yych <= 'F') goto yya648;
	goto yya601;
yya647:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == '0') goto yya621;
	goto yya601;
yya648:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya649;
	if (yych <= '@') goto yya601;
	if (yych >= 'G') goto yya601;
yya649:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '/') goto yya601;
	if (yych <= '9') goto yya650;
	if (yych <= '@') goto yya601;
	if (yych >= 'G') goto yya601;
yya650:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych <= '@') {
		if (yych <= '/') goto yya601;
		if (yych <= '9') goto yya638;
		goto yya601;
	} else {
		if (yych <= 'F') goto yya638;
		if (yych == '\\') goto yya645;
		goto yya601;
	}
}

    }
    
    if (LOOKAHEAD(in->sym[0], T_VARIANT)) {
        PUSH_TERMINAL(p->stack, lpop(in, T_VARIANT));
    } else {
        if (LOOKAHEAD(in->sym[0], T_KEYWORD)) {
            PUSH_TERMINAL(p->stack, lpop(in, T_KEYWORD));
            PUSH_TERMINAL(p->stack, lpop(in, '('));
            p21_parameter(p, act);
        } else {
            PUSH_TERMINAL(p->stack, lpop(in, '('));
            if (LOOKAHEAD(in->sym[0], '(', T_KEYWORD, T_VARIANT)) {
                p21_parameter_list(p, act);
            }
        }
        while (in->nsym < 1) {
            in->sp = in->cur;
            
{
	YYCTYPE yych;
	if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
	yych = *YYCURSOR;
	if (yych <= 0x001F) {
		if (yych <= '\n') {
			if (yych >= '\n') goto yyb655;
		} else {
			if (yych == '\r') goto yyb657;
		}
	} else {
		if (yych <= ')') {
			if (yych <= ' ') goto yyb658;
			if (yych >= ')') goto yyb661;
		} else {
			if (yych == '/') goto yyb663;
		}
	}
	++YYCURSOR;
yyb654:
	{ n = in->cur - in->sp; }
	{ YYCURSOR--; break; }
yyb655:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ in->lineno++; continue; }
yyb657:
	yych = *++YYCURSOR;
	if (yych == '\n') goto yyb655;
	goto yyb654;
yyb658:
	++YYCURSOR;
	if (YYLIMIT <= YYCURSOR) YYFILL(1);
	yych = *YYCURSOR;
	if (yych == ' ') goto yyb658;
	{ n = in->cur - in->sp; }
	{ continue; }
yyb661:
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ PUSH_SYMBOL(')'); continue; }
yyb663:
	yych = *++YYCURSOR;
	if (yych != '*') goto yyb654;
	++YYCURSOR;
	{ n = in->cur - in->sp; }
	{ lex_comment(in); continue; }
}

        }
        PUSH_TERMINAL(p->stack, lpop(in, ')'));
    }
    
    if (p->error)
        goto err;
    
    /* user action */
    if (act->parameter_cb)
        act->parameter_cb(p, bsp, act->userdata);

    /* reduction */
    if (!p->hold) {
        p->stack->items[bsp] = (Symbol){P_PARAMETER};
        drop(p->stack, p->stack->idx_top - bsp - 1);
    }
    
    return;

err:
    report_error(p, "parameter << 14 >>\n");
    if (act->error_cb) act->error_cb(p, bsp, P_PARAMETER);
    else default_error_handler(p, bsp, P_PARAMETER);
    recover(in, ')', ',', ';');
}

void mock_error(P21Parser *, int, uint8_t);
void mock_ud_init(void *);
void mock_ud_exit(void *);
void mock_exchange_file(P21Parser *, int, void *);
void mock_header_start(P21Parser *, int, void *);
void mock_header_entity_list(P21Parser *, int, void *);
void mock_data_section_list(P21Parser *, int, void *);
void mock_data_start(P21Parser *, int, void *);
void mock_header_entity(P21Parser *, int, void *);
void mock_simple_entity_instance(P21Parser *, int, void *);
void mock_complex_entity_instance(P21Parser *, int, void *);
void mock_parameter_list(P21Parser *, int, void *);
void mock_parameter(P21Parser *, int, void *);
void mock_entity_instance_list(P21Parser *, int, void *);
void mock_entity_instance(P21Parser *, int, void *);
void mock_simple_record_list(P21Parser *, int, void *);
void mock_simple_record(P21Parser *, int, void *);
void mock_noop(P21Parser *, int, void *);

typedef struct {
    sqlite3 *db;
    sqlite3_stmt *sec_stmt;
    sqlite3_stmt *sei_stmt;
    sqlite3_stmt *cei_stmt;
    sqlite3_stmt *hei_stmt;
    int section_idx;
} P21UserData;

P21UserData mockdata = {0};

P21ParserActions mockact = {
    .userdata = &mockdata,
    .error_cb = mock_error,
    .ud_init_cb = mock_ud_init,
    .ud_exit_cb = mock_ud_exit,
    .header_start_cb = mock_header_start,
    .data_start_cb = mock_data_start,
    .exchange_file_cb = NULL,
    .header_entity_list_cb = NULL,
    .data_section_list_cb = NULL,
    .header_entity_cb = mock_header_entity,
    .simple_entity_instance_cb = mock_simple_entity_instance,
    .complex_entity_instance_cb = mock_complex_entity_instance,
    .parameter_list_cb = mock_noop,
    .parameter_cb = mock_noop,
    .entity_instance_list_cb = NULL,
    .entity_instance_cb = NULL,
    .simple_record_list_cb = mock_noop,
    .simple_record_cb = mock_noop
};

void mock_error(P21Parser *p, int bsp, uint8_t cxt) { 
    switch (cxt) {
        case P_SIMPLEENTITY:
        case P_COMPLEXENTITY:
        case P_HEADERENTITY:
            dprintf("caught error: '%c'\n", cxt);
            p->error = false;
            drop(p->stack, p->stack->idx_top - bsp - 1);
            break;
        default:
            p->error = true;
            break;
    }
}


void mock_ud_init(void *d) {
    P21UserData *ud = d;
    char ddl_sql[] = 
        "PRAGMA foreign_keys = ON;\n"
        "CREATE TABLE entity_enum (type TEXT(1) PRIMARY KEY);\n"
        "INSERT INTO entity_enum (type) VALUES ('S'), ('C');\n"
        "CREATE TABLE section_enum (type TEXT(1) PRIMARY KEY);\n"
        "INSERT INTO section_enum (type) VALUES ('D'), ('H');\n"

        "CREATE TABLE section_table (\n"
        "    id INTEGER PRIMARY KEY,\n"
        "    lineno INTEGER NOT NULL,\n"
        "    section_type TEXT(1) NOT NULL REFERENCES section_enum(type)\n"
        ");\n"

        "CREATE TABLE section_headers (\n"
        "    id INTEGER PRIMARY KEY,\n"
        "    type_name TEXT COLLATE NOCASE,\n"
        "    raw_data TEXT NOT NULL,\n"
        "    lineno INTEGER NOT NULL,\n"
        "    fk_section INTEGER NOT NULL REFERENCES section_table(id)\n"
        ");\n"

        "CREATE TABLE data_table (\n"
        "    id TEXT PRIMARY KEY,\n"
        "    type_name TEXT COLLATE NOCASE,\n"
        "    raw_data TEXT NOT NULL,\n"
        "    lineno INTEGER NOT NULL,\n"
        "    entity_type TEXT(1) NOT NULL REFERENCES entity_enum(type),\n"
        "    fk_section INTEGER NOT NULL REFERENCES section_table(id)\n"
        ") WITHOUT ROWID;\n"
        
        "BEGIN DEFERRED TRANSACTION;";

    char sei_sql[] = "INSERT INTO data_table VALUES (?,?,?,?,'S',?)";
    char cei_sql[] = "INSERT INTO data_table VALUES (?,NULL,?,?,'C',?)";
    char hei_sql[] = "INSERT INTO section_headers(type_name, raw_data, lineno, fk_section) VALUES (?, ?, ?, ?)";
    int rc;
    
    rc = sqlite3_open_v2(":memory:", &ud->db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
    
    /* TODO: read ddl sql from external file */
    rc = sqlite3_exec(ud->db, ddl_sql, NULL, NULL, NULL);
    
    rc |= sqlite3_prepare_v3(ud->db, sei_sql, sizeof sei_sql, SQLITE_PREPARE_PERSISTENT, &ud->sei_stmt, NULL);
    rc |= sqlite3_prepare_v3(ud->db, cei_sql, sizeof cei_sql, SQLITE_PREPARE_PERSISTENT, &ud->cei_stmt, NULL);
    rc |= sqlite3_prepare_v3(ud->db, hei_sql, sizeof hei_sql, SQLITE_PREPARE_PERSISTENT, &ud->hei_stmt, NULL);
    
    if (rc != SQLITE_OK)
        exit(1);
    
    ud->section_idx = 0;
}

void mock_ud_exit(void *d) {
    P21UserData *ud = d;
    int rc;
    char ddl_sql[] = 
        "CREATE INDEX ix_type_name ON data_table(type_name);\n"
        "CREATE INDEX ix_entity_type ON data_table(entity_type);\n"
        "CREATE INDEX ix_fk_section ON data_table(fk_section);";

    rc = sqlite3_finalize(ud->sei_stmt);
    rc |= sqlite3_finalize(ud->cei_stmt);
    rc |= sqlite3_finalize(ud->hei_stmt);
    if (rc != SQLITE_OK) goto err;

    rc = sqlite3_exec(ud->db, "COMMIT TRANSACTION", NULL, NULL, NULL);
    if (rc != SQLITE_OK) goto err;
    
    /* TODO: benchmark index creation here vs on db init */
    rc = sqlite3_exec(ud->db, ddl_sql, NULL, NULL, NULL);
    if (rc != SQLITE_OK) goto err;
    
    rc = sqlite3_close(ud->db);
    if (rc != SQLITE_OK) goto err;
    
    return;
err:
    dprintf("db error\n");
    exit(1);
}

void mock_exchange_file(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; }
void mock_header_start(P21Parser *p, int bsp, void *d) {
    char sec_sql[] = "INSERT INTO section_table VALUES(?,?,'H')";
    Stack *s = p->stack;
    P21UserData *ud = d;
    Symbol *t = s->items + bsp;
    sqlite3_stmt *stmt;
    int rc;

    rc = sqlite3_prepare_v2(ud->db, sec_sql, sizeof sec_sql, &stmt, NULL);
    if (rc != SQLITE_OK) goto err;
    
    rc |= sqlite3_bind_int(stmt, 1, ++ud->section_idx);
    rc |= sqlite3_bind_int(stmt, 2, t->lineno);
    if (rc != SQLITE_OK) goto err;
    
    rc |= sqlite3_step(stmt);
    if (rc != SQLITE_DONE) goto err;
    
    sqlite3_finalize(stmt);

    /*
    s->items[bsp] = (Symbol){P_HEADERSECTION};
    drop(s, s->idx_top - bsp - 1);
    */
    
    return;
    
err:
    dprintf("db error\n");
    exit(1);
}
void mock_header_entity_list(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; }
void mock_data_section_list(P21Parser *p, int bsp, void *d) { Stack *s = p->stack; }
void mock_data_start(P21Parser *p, int bsp, void *d) {
    char sec_sql[] = "INSERT INTO section_table VALUES(?,?,'D')";
    Stack *s = p->stack;
    P21UserData *ud = d;
    Symbol *t = s->items + bsp;
    sqlite3_stmt *stmt;
    int rc;

    rc = sqlite3_prepare_v2(ud->db, sec_sql, sizeof sec_sql, &stmt, NULL);
    if (rc != SQLITE_OK) goto err;
    
    rc |= sqlite3_bind_int(stmt, 1, ++ud->section_idx);
    rc |= sqlite3_bind_int(stmt, 2, t->lineno);
    if (rc != SQLITE_OK) goto err;
    
    rc |= sqlite3_step(stmt);
    if (rc!= SQLITE_DONE) goto err;
    
    sqlite3_finalize(stmt);
        
    return;
    
err:
    dprintf("db error\n");
    exit(1);
}

void mock_header_entity(P21Parser *p, int bsp, void *d) {
    Stack *s = p->stack;
    P21UserData *ud = d;
    HeaderEntity e = {s->items + bsp, s->items + bsp + 1};
    size_t i, nargs = e.args->n;
    unsigned char *basemrk = p->in->basemrk;
    ptrdiff_t ep;
    int rc;
    
    /* rewrite (normalise) args member before bind */
    e.args->offset = (e.args + 1)->offset;
    e.args->n = (e.args + 1)->n;
    for (i = 2, ep = e.args->offset + 1; i < nargs; i++) {
        Symbol *t = e.args + i;
        if (t->token == '(') t->n = 1;
        if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n);
        ep += t->n;
    }
    e.args->n = ep - e.args->offset;
    
    rc = sqlite3_reset(ud->hei_stmt);
    if (rc != SQLITE_OK) goto err;
    
    rc =  sqlite3_bind_text(ud->hei_stmt, 1, basemrk + e.kw->offset, e.kw->n, SQLITE_TRANSIENT);
    rc |= sqlite3_bind_text(ud->hei_stmt, 2, basemrk + e.args->offset, e.args->n, SQLITE_TRANSIENT);
    rc |= sqlite3_bind_int(ud->hei_stmt, 3, e.kw->lineno);
    rc |= sqlite3_bind_int(ud->hei_stmt, 4, ud->section_idx);
    if (rc != SQLITE_OK) goto err;
    
    rc = sqlite3_step(ud->hei_stmt);
    if (rc != SQLITE_DONE) goto err;
    
    p->hold = false;
    return;
    
err:
    mock_error(p, bsp, P_HEADERENTITY);
    dprintf("db error\n");
}

void mock_simple_entity_instance(P21Parser *p, int bsp, void *d) {
    Stack *s = p->stack;
    P21UserData *ud = d;
    SimpleEntity e = {s->items + bsp, s->items + bsp + 1, s->items + bsp + 2, s->items + bsp + 3};
    size_t i, nargs = e.args->n;
    unsigned char *basemrk = p->in->basemrk;
    ptrdiff_t ep;
    int rc;
    
    /* rewrite (normalise) args before bind */
    e.args->offset = (e.args + 1)->offset;
    e.args->n = (e.args + 1)->n;
    for (i = 2, ep = e.args->offset + e.args->n; i < nargs; i++) {
        Symbol *t = e.args + i;
        if (t->token == '(') t->n = 1;
        if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n);
        ep += t->n;
    }
    e.args->n = ep - e.args->offset;

    /* */
    rc = sqlite3_reset(ud->sei_stmt);
    if (rc != SQLITE_OK) goto err;

    rc =  sqlite3_bind_text(ud->sei_stmt, 1, basemrk + e.eid->offset, e.eid->n, SQLITE_TRANSIENT);
    rc |= sqlite3_bind_text(ud->sei_stmt, 2, basemrk + e.kw->offset, e.kw->n, SQLITE_TRANSIENT);
    rc |= sqlite3_bind_text(ud->sei_stmt, 3, basemrk + e.args->offset, e.args->n, SQLITE_TRANSIENT);
    rc |= sqlite3_bind_int(ud->sei_stmt, 4, e.eid->lineno);
    rc |= sqlite3_bind_int(ud->sei_stmt, 5, ud->section_idx);
    if (rc != SQLITE_OK) goto err;
    
    rc = sqlite3_step(ud->sei_stmt);
    if (rc != SQLITE_DONE) goto err;
    
    p->hold = false;    
    
    return;
    
err:
    mock_error(p, bsp, P_SIMPLEENTITY);
    dprintf("db error\n");
}


void mock_complex_entity_instance(P21Parser *p, int bsp, void *d) {
    Stack *s = p->stack;
    P21UserData *ud = d;
    ComplexEntity e = {s->items + bsp, s->items + bsp + 1, s->items + bsp + 2};
    size_t i, nsubsupers = e.subsupers->n;
    unsigned char *basemrk = p->in->basemrk;
    ptrdiff_t ep;
    int rc;
    
    /* rewrite (normalise) list before bind */
    for (i = 1, ep = e.subsupers->offset + 1; i < nsubsupers; i++) {
        Symbol *t = e.subsupers + i;
        if (t->token == '(') t->n = 1;
        if (ep != t->offset) memmove(basemrk + ep, basemrk + t->offset, t->n);
        ep += t->n;
    }
    e.subsupers->n = ep - e.subsupers->offset;
    
    rc = sqlite3_reset(ud->cei_stmt);
    if (rc != SQLITE_OK) goto err;
    
    rc = sqlite3_bind_text(ud->cei_stmt, 1, basemrk + e.eid->offset, e.eid->n, SQLITE_TRANSIENT);
    rc |= sqlite3_bind_text(ud->cei_stmt, 2, basemrk + e.subsupers->offset, e.subsupers->n, SQLITE_TRANSIENT);
    rc |= sqlite3_bind_int(ud->cei_stmt, 3, e.eid->lineno);
    rc |= sqlite3_bind_int(ud->cei_stmt, 4, ud->section_idx);
    if (rc != SQLITE_OK) goto err;
    
    rc = sqlite3_step(ud->cei_stmt);
    if (rc != SQLITE_DONE) goto err;

    p->hold = false;
    return;
    
err:
    mock_error(p, bsp, P_COMPLEXENTITY);
    dprintf("db error \n");
}

void mock_parameter_list(P21Parser *p, int bsp, void *d) { }
void mock_parameter(P21Parser *p, int bsp, void *d) { }
void mock_entity_instance_list(P21Parser *p, int bsp, void *d) { }
void mock_entity_instance(P21Parser *p, int bsp, void *d) { }
void mock_simple_record_list(P21Parser *p, int bsp, void *d) { }
void mock_simple_record(P21Parser *p, int bsp, void *d) {}

void mock_noop(P21Parser *p, int bsp, void *d) {
    p->hold = true;
}

int main(char *argv[], int argc) {
    const char *paths[] = {
        "/home/chorler/projects/src/stepcode/test/p21/test_array_bounds_FAIL1.p21",
        "/home/chorler/projects/src/stepcode/test/p21/comments.p21",
        "/home/chorler/projects/src/stepcode/test/p21/test_inverse_attr.p21",
        "/home/chorler/projects/src/stepcode/test/p21/missing_and_required.p21",
        "/home/chorler/projects/src/stepcode/test/p21/test_array_bounds.p21",
        "/home/chorler/projects/src/stepcode/test/p21/test_inherit_inverse.p21",
        "/home/chorler/projects/src/stepcode/data/ap214e3/as1-oc-214.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/dm1-id-214.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD_BACK.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD_FRONT.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY_FRONT.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT_BACK_000.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT_FRONT_000.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/s1-c5-214.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/MAINBODY_BACK.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/HEAD.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL_TURBINE.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/TAIL_MIDDLE_PART.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/s1-c5-214/FOOT.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/sg1-c5-214.stp",
        "/home/chorler/projects/src/stepcode/data/ap214e3/io1-cm-214.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS7-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS1Mod0-outresult.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS2-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS1Mod0-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS3-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS10Mod0-outresult.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS2Mod0-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS8-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS3Mod0-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS4Mod0-outresult.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS7Mod0-outresult.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS4Mod0-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS10Mod0-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS3Mod0-outresult.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS8Mod0-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS4-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS7Mod0-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS2Mod0-outresult.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS8Mod0-outresult.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS10-out.stp",
        "/home/chorler/projects/src/stepcode/data/ap209/ATS1-out.stp"
    };
    
    P21Parser myp;
    P21UserData mydata;
    FILE *fp;
    memset(&mydata, 0, sizeof mydata);
    
    for (unsigned int i = 0; i < (sizeof paths / sizeof paths[0]); i++) {
        fp = fopen(paths[i], "rb");
        if (!fp) { fprintf(stderr, "failed to read input: %s\n", paths[i]); continue; }
        else { fprintf(stderr, "processing: %s\n", paths[i]); }
        p21_init(&myp, fp);
        p21_parse(&myp, &mockact);
    }
}
