view tests/agcl/examples/good/mas.cpp @ 21:1c9dac05d040

Add lint-style FALLTHROUGH annotations to fallthrough cases. (in the parse engine and thus the output code) Document this, because the old output causes warnings with gcc10.
author David A. Holland
date Mon, 13 Jun 2022 00:04:38 -0400
parents 13d2b8934445
children
line wrap: on
line source

/*
 * AnaGram, a System for Syntax Directed Programming
 * C Macro preprocessor
 * Macro argument substitution module
 *
 * Copyright 1993-2000 Parsifal Software. All Rights Reserved.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */

#include "mpp.h"


/*
 * AnaGram, A System for Syntax Directed Programming
 * File generated by: ...
 *
 * AnaGram Parsing Engine
 * Copyright 1993-2002 Parsifal Software. All Rights Reserved.
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 *    claim that you wrote the original software. If you use this software
 *    in a product, an acknowledgment in the product documentation would be
 *    appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 *    misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 */

#ifndef MAS_H
#include "mas.h"
#endif

#ifndef MAS_H
#error Mismatched header file
#endif

#include <ctype.h>
#include <stdio.h>

#define RULE_CONTEXT (&((PCB).cs[(PCB).ssx]))
#define ERROR_CONTEXT ((PCB).cs[(PCB).error_frame_ssx])
#define CONTEXT ((PCB).cs[(PCB).ssx])


#define CHANGE_REDUCTION(x) mas_change_reduction(mas_##x##_token)
int mas_change_reduction(mas_token_type);

#define INPUT_VALUE(type) *(type *) &(PCB).input_value

#line - "mas.syn"
                                      // Embedded C
#include "array.h"                     // AnaGram\CLASSLIB\INCLUDE\array.h
#include "stack.h"                     // AnaGram\CLASSLIB\INCLUDE\stack.h


// Macro Definitions

#define INPUT_CODE(T) (T).id
#define PCB (*mas_pcb)
#define SYNTAX_ERROR syntax_error(PCB.error_message);


// Static variables

typedef stack<unsigned>   unsigned_stack;      // accomodate broken compilers

static unsigned_stack     active_macros(200,20);
static token            **args;
static int                args_only = 0;
static mas_pcb_type      *mas_pcb;
static int                n_concats = 0;
static int                n_args;
static unsigned          *params;
static token_accumulator  space_stack(100);


/*

expand_text() is a shell procedure which calls the mas parser a
number of times. It is used to expand arguments before substituting
them into a macro, and to expand the body of a macro. Notice that
expand_text() is recursive, since macros encountered during the an
expansion process may themselves need to be expanded.

expand_text() takes three explicit arguments:
  token *text:
    points to a string of tokens, terminated by an eof token.

  int n:
    specifies the number of arguments. Defaults to 0. The arguments
    themselves are token strings on the token accumulator stack.
    expand_text() makes copies of them and stores pointers to them in
    the args array.

  unsigned *p:
    An array of n dictionary indices which gives the names of the
    parameters for which the arguments are to be substituted. p
    defaults to NULL.

global switches
  Two global switches affect the expansion of text: if_clause and
  args_only.  Setting if_clause affects the treatment of the token
  "defined". Setting args_only causes only macro parameters to be
  expanded.

*/

void expand_text(token *text, int n, unsigned *p) {
  mas_pcb_type pcb;

// Save old status
  mas_pcb_type *save_pcb = mas_pcb;
  int save_n_args = n_args;
  token **save_args = args;
  unsigned *save_params = params;
  int save_switch = args_only;

// pop args from accumlator stack and expand them
  args_only = 0;
  token **new_args;
  int k = n;
  if (n) {
    new_args = new token*[n];
    args_only = 1;
    while (k--) {
    token t;
    token top = *(token *) ta;
    while (top.id == SPACE) ta >> t;             //trim space on right
    array<token> arg_tokens(ta, size(ta) + 1);
    token *tp = arg_tokens;
    while (tp->id == SPACE) tp++;                //trim space on left
    --ta;
    mas_pcb = &pcb;
    pcb.pointer = tp;
    ++ta;
    mas();
      new_args[k] = copy(ta);
      --ta;
    }
    args_only = 0;
  }
  else new_args = NULL;

// Expand text
  args = new_args;
  n_args = n;
  params = p;
  pcb.pointer = text;
  mas_pcb = &pcb;
  ++ta;
  ++active_macros;
  n_concats = 0;
  mas();

// If any new tokens were created by concatenation, rescan
  while (n_concats) {
    array<token> expansion(ta,size(ta) + 1);
    --ta;
    pcb.pointer = expansion;
    ++ta;
    n_concats = 0;
    n = size(active_macros);

#ifdef _MSC_VER                  //Cope with peculiarity of MSVC++
    while (n--) macro[*((unsigned *)active_macros + n)].busy_flag = 1;
#else
    while (n--) macro[active_macros[n]].busy_flag = 1;
#endif
    mas();
  }
  n = size(active_macros);
#ifdef _MSC_VER                  //Cope with peculiarity of MSVC++
    while (n--) macro[*((unsigned *)active_macros + n)].busy_flag = 0;
#else
  while (n--) macro[active_macros[n]].busy_flag = 0;
#endif
  --active_macros;

// Discard argument strings

  n = n_args;
  while (n--) delete [] args[n];
  if (n_args) delete [] args;

// Restore old status

  args_only = save_switch;
  args = save_args;
  n_args = save_n_args;
  params = save_params;
  mas_pcb = save_pcb;
}

/*

expand_macro() is a shell procedure which sets up a call to
expand_text for a specific macro.

*/

void expand_macro(token t, unsigned n_args) {
  unsigned id = macro_id[t.handle];
  token *body = macro[id].body;
  assert(n_args == macro[id].n_args);
  if (body == NULL) {
    while (n_args--) --ta;
    ++ta;
    return;
  }
  expand_text(body,n_args,macro[id].arg_names);
}

/*

expand_arg() is another shell procedure for expand_text() which does
a complete expansion of a single macro argument.

*/

static void expand_arg(unsigned n) {
  expand_text(args[n]);
  concat(ta);
}

/*

id_macro() is very nearly the same as id_macro() in TS.SYN. The
primary difference is that this one deals in tokens, the other in
character strings.

*/

static token id_macro(token t) {
  unsigned n = n_args;
  unsigned id;

  while (n--) if (t.handle == params[n]) {
    CHANGE_REDUCTION(parameter_name);
    t.handle = n;
    return t;
  }
  if (args_only) return t;
  if (if_clause && t.handle == defined_value) {
    CHANGE_REDUCTION(defined);
    return t;
  }
  id = macro_id[t.handle];
  if (id == 0) return t;
  if (macro[id].busy_flag) return t;
  active_macros << id;
  if (macro[id].parens) CHANGE_REDUCTION(macro);
  else CHANGE_REDUCTION(simple_macro);
  return t;
}

/*

defined() is very nearly the same as defined() in TS.SYN. The primary
difference is that this one deals in tokens, the other in character
strings.

*/

static token defined(unsigned handle) {
  token t;
  t.id = DECconstant;
  t.handle = macro_id[handle] ? one_value : zero_value;
  return t;
}

/*

concatenate() implements the splicing together of two tokens by the
"##" operator in a macro definition. Because of the way the grammar
has been written, spaces have already been trimmed on both sides of the
## by the parser.

If there are actually two tokens to concatenate, the last token on
the left is popped off, its string value is obtained from the token
dictionary and pushed onto the string accumulator, ditto for the
first token on the right. The string is then identified and the token
is classified. If the new token is the name of a macro, a new scan
will be required to expand it.

*/

static void concatenate(void) {
  array<token> right_arg(ta, size(ta) + 1);
  token t;
  token *tp = right_arg;

  --ta;                // discard right argument from stack

  if (size(ta) && tp->id != END_OF_FILE) {
    ta >> t;                               // pop left token
    ++sa << td[t.handle] << td[tp->handle];      // left string + right string
    t.handle = td << sa.top();             // identify string
    t.id  = classify_token(sa.top());      // classify token
    --sa;                                  // discard string
    ++tp;                                  // discard old token on right
    if (macro_id[t.handle]) n_concats++;      // if macro, signal rescan
    ta << t;                               // output new token
  }
  ta << tp;                                // remainder of right side
}

/*

make_string() implements the '#' operator in macro expansions, that
is, it turns its operand into a string constant. To do this it must
provide "" marks and must quote any embedded " or \ characters with
the \ character.

*/

static token make_string(unsigned n) {
  token *tp;
  token t;

  tp = args[n];
  ++sa << '"';
  while (tp->id != END_OF_FILE) {
    char *p = td[tp->handle];
    char c;
    while ((c = *p++) != 0) {
      if (c == '"' || c == '\\') sa << '\\';
      sa << c;
    }
    tp++;
  }
  sa << '"';
  t.id = STRINGliteral;
  t.handle = td << sa.top();
  --sa;
  return t;
}

#line - "mas.cpp"

#ifndef CONVERT_CASE
#define CONVERT_CASE(c) (c)
#endif
#ifndef TAB_SPACING
#define TAB_SPACING 8
#endif

static void ag_rp_1(void) {
#line - "mas.syn"
  reset(space_stack);
#line - "mas.cpp"
}

static void ag_rp_2(token s) {
#line - "mas.syn"
if (args_only) space_stack << s;
#line - "mas.cpp"
}

static void ag_rp_3(void) {
#line - "mas.syn"
  ta << space_stack;
#line - "mas.cpp"
}

static void ag_rp_4(void) {
#line - "mas.syn"
  ta << space_stack;
#line - "mas.cpp"
}

static void ag_rp_5(token t) {
#line - "mas.syn"
  ta << t << space_stack;
#line - "mas.cpp"
}

static void ag_rp_6(token t) {
#line - "mas.syn"
  ta << t;
#line - "mas.cpp"
}

static void ag_rp_7(token n) {
#line - "mas.syn"
  ta << make_string(n.handle);
#line - "mas.cpp"
}

static void ag_rp_8(token t) {
#line - "mas.syn"
  ta << t;
#line - "mas.cpp"
}

static void ag_rp_9(token t) {
#line - "mas.syn"
  expand_macro(t,0), concat(ta);
#line - "mas.cpp"
}

static void ag_rp_10(token t, unsigned n) {
#line - "mas.syn"
  expand_macro(t,n), concat(ta);
#line - "mas.cpp"
}

static void ag_rp_11(token n) {
#line - "mas.syn"
  ta << defined(n.handle);
#line - "mas.cpp"
}

static token ag_rp_12(token n) {
#line - "mas.syn"
  return n;
#line - "mas.cpp"
}

static token ag_rp_13(token n) {
#line - "mas.syn"
  return n;
#line - "mas.cpp"
}

static token ag_rp_14(token n) {
#line - "mas.syn"
  return id_macro(n);
#line - "mas.cpp"
}

static void ag_rp_15(token name) {
#line - "mas.syn"
  expand_arg(name.handle), ta << space_stack;
#line - "mas.cpp"
}

static void ag_rp_16(token name) {
#line - "mas.syn"
  ta << args[name.handle], concatenate();
#line - "mas.cpp"
}

static void ag_rp_17(void) {
#line - "mas.syn"
  concatenate();
#line - "mas.cpp"
}

static void ag_rp_18(token n) {
#line - "mas.syn"
  ta << args[n.handle], ++ta;
#line - "mas.cpp"
}

static void ag_rp_19(void) {
#line - "mas.syn"
  ++ta;
#line - "mas.cpp"
}

static void ag_rp_20(token t) {
#line - "mas.syn"
  ta << t, ++ta;
#line - "mas.cpp"
}

static void ag_rp_21(void) {
#line - "mas.syn"
  ++ta;
#line - "mas.cpp"
}

static void ag_rp_22(token t) {
#line - "mas.syn"
  ta << t;
#line - "mas.cpp"
}

static void ag_rp_23(token n) {
#line - "mas.syn"
  ta << make_string(n.handle);
#line - "mas.cpp"
}

static void ag_rp_24(token t) {
#line - "mas.syn"
  ta << t;
#line - "mas.cpp"
}

static unsigned ag_rp_25(void) {
#line - "mas.syn"
  return 0;
#line - "mas.cpp"
}

static unsigned ag_rp_26(void) {
#line - "mas.syn"
  return 1;
#line - "mas.cpp"
}

static unsigned ag_rp_27(unsigned n) {
#line - "mas.syn"
  return n+1;
#line - "mas.cpp"
}

static void ag_rp_28(token t) {
#line - "mas.syn"
  ++ta << t;
#line - "mas.cpp"
}

static void ag_rp_29(token t) {
#line - "mas.syn"
  ta << t;
#line - "mas.cpp"
}

static void ag_rp_30(token t) {
#line - "mas.syn"
  ta << t;
#line - "mas.cpp"
}

static void ag_rp_31(token t) {
#line - "mas.syn"
  concat(ta) << t;
#line - "mas.cpp"
}

static void ag_rp_32(token t) {
#line - "mas.syn"
  ++ta << t;
#line - "mas.cpp"
}

static void ag_rp_33(token t) {
#line - "mas.syn"
  ta << t;
#line - "mas.cpp"
}


#ifndef AG_TRACE_FILE_NAME
#define AG_TRACE_FILE_NAME "mas.etr"
#endif

static void ag_trace_error(void) {
  FILE *ag_file = fopen(AG_TRACE_FILE_NAME, "w");
  int i;
  if (ag_file == NULL) return;
  fprintf(ag_file, "%d\n", (PCB).ssx);
  for (i = 0; i < (PCB).ssx; i++) fprintf(ag_file, "%d\n", (PCB).ss[i]);
  fprintf(ag_file, "%d\n", (PCB).sn);
  fprintf(ag_file, "%d\n", (PCB).token_number);
  fclose(ag_file);
}


#define READ_COUNTS 
#define WRITE_COUNTS 
#undef V
#define V(i,t) (*t (&(PCB).vs[(PCB).ssx + i]))
#undef VS
#define VS(i) (PCB).vs[(PCB).ssx + i]

#ifndef GET_CONTEXT
#define GET_CONTEXT CONTEXT = (PCB).input_context
#endif

typedef enum {
  ag_action_1,
  ag_action_2,
  ag_action_3,
  ag_action_4,
  ag_action_5,
  ag_action_6,
  ag_action_7,
  ag_action_8,
  ag_action_9,
  ag_action_10,
  ag_action_11,
  ag_action_12
} ag_parser_action;


#ifndef NULL_VALUE_INITIALIZER
#define NULL_VALUE_INITIALIZER = { 0 }
#endif

static mas_vs_type const ag_null_value NULL_VALUE_INITIALIZER;

static const unsigned char ag_rpx[] = {
    0,  0,  0,  0,  0,  0,  1,  2,  0,  3,  4,  5,  6,  7,  8,  9, 10, 11,
   12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,  0,  0,  0,  0, 25,
   26, 27, 28, 29, 30, 31,  0,  0, 32,  0, 33
};

#define AG_TCV(x) ag_tcv[(x)]

static const unsigned char ag_tcv[] = {
    6, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,  7, 34, 34, 13,
   34, 34, 34, 34, 17, 19, 34, 34, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 25, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 22, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
   34, 34, 34, 34
};

#ifndef SYNTAX_ERROR
#define SYNTAX_ERROR fprintf(stderr,"%s\n", (PCB).error_message)
#endif

#ifndef PARSER_STACK_OVERFLOW
#define PARSER_STACK_OVERFLOW {fprintf(stderr, \
  "\nParser stack overflow\n");}
#endif

#ifndef REDUCTION_TOKEN_ERROR
#define REDUCTION_TOKEN_ERROR {fprintf(stderr, \
  "\nReduction token error\n");}
#endif


#ifndef INPUT_CODE
#define INPUT_CODE(T) (T)
#endif



static const int ag_rtt[] = {
   15, 14, 16, 11, 20,  0
};

static const unsigned char ag_tstt[] = {
34,28,22,19,17,13,7,6,0,1,2,
34,28,22,19,17,13,7,6,0,3,4,5,8,9,10,11,14,15,16,20,23,
34,28,22,19,17,13,7,0,1,
22,17,7,0,1,21,
22,0,14,
34,28,25,22,19,17,13,7,6,0,1,
34,28,25,22,19,17,13,7,6,0,1,
34,28,25,22,19,17,13,7,6,0,1,
34,28,25,22,19,17,13,7,6,0,1,
34,28,22,19,17,13,0,3,8,9,10,11,14,15,16,20,23,
6,0,
34,28,22,19,17,13,7,0,11,14,15,16,20,24,26,
22,17,7,0,
25,7,0,
25,17,7,0,
25,7,0,
25,7,0,
22,0,14,
22,7,0,1,
34,28,25,22,19,17,13,7,0,1,18,
22,7,0,
34,25,22,17,13,7,0,27,29,31,
28,19,0,
19,7,0,1,
34,28,25,22,19,17,13,7,0,31,32,
34,25,22,17,13,7,0,31,32,
34,25,22,17,13,7,0,1,
19,7,0,
34,28,25,22,19,17,13,7,0,31,32,
34,25,22,17,13,7,0,27,29,31,
34,25,22,17,13,7,0,31,32,

};


static unsigned const char ag_astt[244] = {
  4,4,4,4,4,4,4,4,7,1,0,2,2,2,2,2,1,10,8,7,1,1,1,1,1,1,1,1,2,2,1,1,4,4,4,4,4,
  4,4,7,1,4,4,4,7,1,2,2,7,2,4,4,4,4,4,4,4,4,4,7,1,4,4,4,4,4,4,4,4,4,7,1,4,4,
  4,4,4,4,4,4,4,7,1,4,4,4,4,4,4,4,4,4,7,1,2,2,2,2,2,1,5,3,3,1,1,1,1,2,2,1,1,
  3,7,2,2,2,2,2,1,10,7,2,2,2,2,2,2,2,2,1,10,7,2,10,4,2,1,10,4,2,10,4,2,10,4,
  2,7,2,4,4,7,1,4,4,4,4,4,4,4,4,7,1,1,1,10,7,2,2,2,2,2,10,4,1,1,1,1,2,7,4,4,
  7,1,2,10,2,2,2,2,2,2,7,1,3,2,2,2,2,2,2,4,1,3,4,4,4,4,4,4,7,1,2,10,7,2,10,2,
  2,2,2,2,2,7,1,3,2,2,2,2,2,10,7,1,1,1,2,2,2,2,2,2,4,1,3
};


static const unsigned char ag_pstt[] = {
6,6,6,6,6,6,6,6,0,1,0,
12,12,20,12,12,4,7,10,1,9,9,10,9,8,7,6,5,14,15,3,2,
6,6,6,6,6,6,6,2,11,
6,6,6,3,12,17,
20,4,13,
6,6,6,6,6,6,6,6,6,5,13,
6,6,6,6,6,6,6,6,6,6,14,
6,6,6,6,6,6,6,6,6,7,15,
6,6,6,6,6,6,6,6,6,8,16,
12,12,20,12,12,4,4,2,2,8,7,6,5,14,15,3,2,
5,10,
28,28,20,28,28,17,7,11,30,22,30,30,30,23,30,
18,18,7,12,
24,7,21,
26,19,7,11,
27,7,10,
25,7,9,
20,17,29,
6,6,18,20,
6,6,6,6,6,6,6,6,19,21,22,
23,7,20,
38,38,38,44,38,7,35,25,25,24,
26,16,22,
6,6,23,27,
40,46,40,40,39,44,40,40,24,28,45,
40,40,40,44,40,40,36,28,43,
6,6,6,6,6,6,26,29,
19,7,27,
40,46,40,40,41,44,40,40,28,28,45,
38,38,38,44,38,7,29,30,30,24,
40,40,40,44,40,40,37,28,43,

};


static const unsigned char ag_sbt[] = {
     0,  11,  32,  41,  47,  50,  61,  72,  83,  94, 111, 113, 128, 132,
   135, 139, 142, 145, 148, 152, 163, 166, 176, 179, 183, 194, 203, 211,
   214, 225, 235, 244
};


static const unsigned char ag_sbe[] = {
     8,  19,  39,  44,  48,  59,  70,  81,  92, 100, 112, 120, 131, 134,
   138, 141, 144, 146, 150, 160, 165, 172, 178, 181, 191, 200, 209, 213,
   222, 231, 241, 244
};


static const unsigned char ag_fl[] = {
  1,1,2,0,1,3,0,2,1,2,2,2,1,2,1,1,5,2,2,6,1,2,3,3,3,3,3,3,1,2,1,1,1,1,1,
  1,2,4,1,2,1,2,1,2,1,2,2
};

static const unsigned char ag_ptt[] = {
    0,  4,  4,  5,  5,  2,  1,  1,  3,  3,  3,  3,  9,  9,  9,  9,  9,  9,
   21, 21, 15,  8, 10, 10, 23, 23, 23, 23, 24, 24, 24, 26, 26, 26, 26, 18,
   18, 18, 29, 29, 32, 32, 27, 27, 31, 31, 31
};

static const unsigned char  *ag_valid(int ag_k) {
  const unsigned char  *ag_tp = &ag_tstt[ag_sbt[(PCB).sn+1]];
  while (*--ag_tp != (unsigned char) ag_k) if (*ag_tp == 0) return NULL;
  return ag_tp;
}

int mas_change_reduction(mas_token_type ag_k) {
  if (!ag_valid(ag_k)) return 0;
  (PCB).reduction_token = ag_k;
  return 1;
}

static void ag_default(const  int *ag_tp) {
  (PCB).ag_dsn = (PCB).sn;
  (PCB).ag_dtl = ag_tp;
  while (!ag_valid((mas_token_type) *ag_tp)) ag_tp++;
  (PCB).reduction_token = (mas_token_type) *ag_tp;
}



static void ag_ra(void)
{
  switch(ag_rpx[(PCB).ag_ap]) {
    case 1: ag_rp_1(); break;
    case 2: ag_rp_2(V(1,(token *))); break;
    case 3: ag_rp_3(); break;
    case 4: ag_rp_4(); break;
    case 5: ag_rp_5(V(0,(token *))); break;
    case 6: ag_rp_6(V(0,(token *))); break;
    case 7: ag_rp_7(V(1,(token *))); break;
    case 8: ag_rp_8(V(0,(token *))); break;
    case 9: ag_rp_9(V(0,(token *))); break;
    case 10: ag_rp_10(V(0,(token *)), V(3,(unsigned *))); break;
    case 11: ag_rp_11(V(1,(token *))); break;
    case 12: V(0,(token *)) = ag_rp_12(V(1,(token *))); break;
    case 13: V(0,(token *)) = ag_rp_13(V(3,(token *))); break;
    case 14: ag_default(&ag_rtt[0]); V(0,(token *)) = ag_rp_14(V(0,(token *))); break;
    case 15: ag_rp_15(V(0,(token *))); break;
    case 16: ag_rp_16(V(2,(token *))); break;
    case 17: ag_rp_17(); break;
    case 18: ag_rp_18(V(0,(token *))); break;
    case 19: ag_rp_19(); break;
    case 20: ag_rp_20(V(0,(token *))); break;
    case 21: ag_rp_21(); break;
    case 22: ag_rp_22(V(0,(token *))); break;
    case 23: ag_rp_23(V(1,(token *))); break;
    case 24: ag_rp_24(V(0,(token *))); break;
    case 25: V(0,(unsigned *)) = ag_rp_25(); break;
    case 26: V(0,(unsigned *)) = ag_rp_26(); break;
    case 27: V(0,(unsigned *)) = ag_rp_27(V(0,(unsigned *))); break;
    case 28: ag_rp_28(V(0,(token *))); break;
    case 29: ag_rp_29(V(1,(token *))); break;
    case 30: ag_rp_30(V(0,(token *))); break;
    case 31: ag_rp_31(V(1,(token *))); break;
    case 32: ag_rp_32(V(0,(token *))); break;
    case 33: ag_rp_33(V(1,(token *))); break;
  }
  (PCB).la_ptr = (PCB).pointer;
}

#define TOKEN_NAMES mas_token_names
const char *const mas_token_names[35] = {
  "grammar",
  "space",
  "grammar",
  "parse unit",
  "",
  "",
  "eof",
  "' '",
  "parameter expansion",
  "simple parse unit",
  "concatenation",
  "macro",
  "",
  "'#'",
  "parameter name",
  "variable",
  "simple macro",
  "'('",
  "macro arg list",
  "')'",
  "defined",
  "macro name",
  "NAME",
  "left side",
  "right side",
  "CONCAT",
  "not parameter",
  "arg elements",
  "','",
  "initial arg element",
  "",
  "nested elements",
  "arg element",
  "",
  "",

};

#ifndef MISSING_FORMAT
#define MISSING_FORMAT "Missing %s"
#endif
#ifndef UNEXPECTED_FORMAT
#define UNEXPECTED_FORMAT "Unexpected %s"
#endif
#ifndef UNNAMED_TOKEN
#define UNNAMED_TOKEN "input"
#endif


static void ag_diagnose(void) {
  int ag_snd = (PCB).sn;
  int ag_k = ag_sbt[ag_snd];

  if (*TOKEN_NAMES[ag_tstt[ag_k]] && ag_astt[ag_k + 1] == ag_action_8) {
    sprintf((PCB).ag_msg, MISSING_FORMAT, TOKEN_NAMES[ag_tstt[ag_k]]);
  }
  else if (ag_astt[ag_sbe[(PCB).sn]] == ag_action_8
          && (ag_k = (int) ag_sbe[(PCB).sn] + 1) == (int) ag_sbt[(PCB).sn+1] - 1
          && *TOKEN_NAMES[ag_tstt[ag_k]]) {
    sprintf((PCB).ag_msg, MISSING_FORMAT, TOKEN_NAMES[ag_tstt[ag_k]]);
  }
  else if ((PCB).token_number && *TOKEN_NAMES[(PCB).token_number]) {
    sprintf((PCB).ag_msg, UNEXPECTED_FORMAT, TOKEN_NAMES[(PCB).token_number]);
  }
  else if (isprint(INPUT_CODE((*(PCB).pointer))) && INPUT_CODE((*(PCB).pointer)) != '\\') {
    char buf[20];
    sprintf(buf, "\'%c\'", (char) INPUT_CODE((*(PCB).pointer)));
    sprintf((PCB).ag_msg, UNEXPECTED_FORMAT, buf);
  }
  else sprintf((PCB).ag_msg, UNEXPECTED_FORMAT, UNNAMED_TOKEN);
  (PCB).error_message = (PCB).ag_msg;


}
static int ag_action_1_r_proc(void);
static int ag_action_2_r_proc(void);
static int ag_action_3_r_proc(void);
static int ag_action_4_r_proc(void);
static int ag_action_1_s_proc(void);
static int ag_action_3_s_proc(void);
static int ag_action_1_proc(void);
static int ag_action_2_proc(void);
static int ag_action_3_proc(void);
static int ag_action_4_proc(void);
static int ag_action_5_proc(void);
static int ag_action_6_proc(void);
static int ag_action_7_proc(void);
static int ag_action_8_proc(void);
static int ag_action_9_proc(void);
static int ag_action_10_proc(void);
static int ag_action_11_proc(void);
static int ag_action_8_proc(void);


static int (*const  ag_r_procs_scan[])(void) = {
  ag_action_1_r_proc,
  ag_action_2_r_proc,
  ag_action_3_r_proc,
  ag_action_4_r_proc
};

static int (*const  ag_s_procs_scan[])(void) = {
  ag_action_1_s_proc,
  ag_action_2_r_proc,
  ag_action_3_s_proc,
  ag_action_4_r_proc
};

static int (*const  ag_gt_procs_scan[])(void) = {
  ag_action_1_proc,
  ag_action_2_proc,
  ag_action_3_proc,
  ag_action_4_proc,
  ag_action_5_proc,
  ag_action_6_proc,
  ag_action_7_proc,
  ag_action_8_proc,
  ag_action_9_proc,
  ag_action_10_proc,
  ag_action_11_proc,
  ag_action_8_proc
};


static int ag_action_10_proc(void) {
  int ag_t = (PCB).token_number;
  do {
    (PCB).pointer = (PCB).la_ptr;
    (PCB).token_number = (mas_token_type) AG_TCV(INPUT_CODE(*(PCB).la_ptr));
    (PCB).la_ptr++;
  } while ((PCB).token_number == (mas_token_type) ag_t);
  (PCB).la_ptr = (PCB).pointer;
  return 1;
}

static int ag_action_11_proc(void) {
  int ag_t = (PCB).token_number;

  do {
    (*(token *) &(PCB).vs[(PCB).ssx]) = *(PCB).pointer;
    (PCB).ssx--;
    (PCB).pointer = (PCB).la_ptr;
    ag_ra();
    if ((PCB).exit_flag != AG_RUNNING_CODE) return 0;
    (PCB).ssx++;
    (PCB).token_number = (mas_token_type) AG_TCV(INPUT_CODE(*(PCB).la_ptr));
    (PCB).la_ptr++;
  }
  while ((PCB).token_number == (mas_token_type) ag_t);
  (PCB).la_ptr = (PCB).pointer;
  return 1;
}

static int ag_action_3_r_proc(void) {
  int ag_sd = ag_fl[(PCB).ag_ap] - 1;
  if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
  (PCB).reduction_token = (mas_token_type) ag_ptt[(PCB).ag_ap];
  ag_ra();
  return (PCB).exit_flag == AG_RUNNING_CODE;
}

static int ag_action_3_s_proc(void) {
  int ag_sd = ag_fl[(PCB).ag_ap] - 1;
  if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
  (PCB).reduction_token = (mas_token_type) ag_ptt[(PCB).ag_ap];
  ag_ra();
  return (PCB).exit_flag == AG_RUNNING_CODE;
}

static int ag_action_4_r_proc(void) {
  int ag_sd = ag_fl[(PCB).ag_ap] - 1;
  if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
  (PCB).reduction_token = (mas_token_type) ag_ptt[(PCB).ag_ap];
  return 1;
}

static int ag_action_2_proc(void) {
  if ((PCB).ssx >= 128) {
    ag_trace_error();
    (PCB).exit_flag = AG_STACK_ERROR_CODE;
    PARSER_STACK_OVERFLOW;
  }
  (*(token *) &(PCB).vs[(PCB).ssx]) = *(PCB).pointer;
  (PCB).ss[(PCB).ssx] = (PCB).sn;
  (PCB).ssx++;
  (PCB).sn = (PCB).ag_ap;
  (PCB).pointer = (PCB).la_ptr;
  return 0;
}

static int ag_action_9_proc(void) {
  if ((PCB).ssx >= 128) {
    ag_trace_error();
    (PCB).exit_flag = AG_STACK_ERROR_CODE;
    PARSER_STACK_OVERFLOW;
  }
  (PCB).vs[(PCB).ssx] = ag_null_value;
  (PCB).ss[(PCB).ssx] = (PCB).sn;
  (PCB).ssx++;
  (PCB).sn = (PCB).ag_ap;
  (PCB).la_ptr = (PCB).pointer;
  return (PCB).exit_flag == AG_RUNNING_CODE;
}

static int ag_action_2_r_proc(void) {
  (PCB).ssx++;
  (PCB).sn = (PCB).ag_ap;
  return 0;
}

static int ag_action_7_proc(void) {
  --(PCB).ssx;
  (PCB).la_ptr = (PCB).pointer;
  (PCB).exit_flag = AG_SUCCESS_CODE;
  return 0;
}

static int ag_action_1_proc(void) {
  (PCB).pointer = (PCB).la_ptr;
  (PCB).exit_flag = AG_SUCCESS_CODE;
  return 0;
}

static int ag_action_1_r_proc(void) {
  (PCB).exit_flag = AG_SUCCESS_CODE;
  return 0;
}

static int ag_action_1_s_proc(void) {
  (PCB).exit_flag = AG_SUCCESS_CODE;
  return 0;
}

static int ag_action_4_proc(void) {
  int ag_sd = ag_fl[(PCB).ag_ap] - 1;
  (PCB).reduction_token = (mas_token_type) ag_ptt[(PCB).ag_ap];
  (*(token *) &(PCB).vs[(PCB).ssx]) = *(PCB).pointer;
  if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
  else (PCB).ss[(PCB).ssx] = (PCB).sn;
  (PCB).pointer = (PCB).la_ptr;
  while ((PCB).exit_flag == AG_RUNNING_CODE) {
    unsigned ag_t1 = ag_sbe[(PCB).sn] + 1;
    unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1;
    do {
      unsigned ag_tx = (ag_t1 + ag_t2)/2;
      if (ag_tstt[ag_tx] < (unsigned char)(PCB).reduction_token) ag_t1 = ag_tx + 1;
      else ag_t2 = ag_tx;
    } while (ag_t1 < ag_t2);
    if (ag_tstt[ag_t1] != (PCB).reduction_token) {
      (PCB).exit_flag = AG_REDUCTION_ERROR_CODE; ag_trace_error();
      REDUCTION_TOKEN_ERROR; break;}
      (PCB).ag_ap = ag_pstt[ag_t1];
    if ((ag_s_procs_scan[ag_astt[ag_t1]])() == 0) break;
  }
  return 0;
}

static int ag_action_3_proc(void) {
  int ag_sd = ag_fl[(PCB).ag_ap] - 1;
  (*(token *) &(PCB).vs[(PCB).ssx]) = *(PCB).pointer;
  if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
  else (PCB).ss[(PCB).ssx] = (PCB).sn;
  (PCB).pointer = (PCB).la_ptr;
  (PCB).reduction_token = (mas_token_type) ag_ptt[(PCB).ag_ap];
  ag_ra();
  while ((PCB).exit_flag == AG_RUNNING_CODE) {
    unsigned ag_t1 = ag_sbe[(PCB).sn] + 1;
    unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1;
    do {
      unsigned ag_tx = (ag_t1 + ag_t2)/2;
      if (ag_tstt[ag_tx] < (unsigned char)(PCB).reduction_token) ag_t1 = ag_tx + 1;
      else ag_t2 = ag_tx;
    } while (ag_t1 < ag_t2);
    if (ag_tstt[ag_t1] != (PCB).reduction_token) {
      (PCB).exit_flag = AG_REDUCTION_ERROR_CODE; ag_trace_error();
      REDUCTION_TOKEN_ERROR; break;}
      (PCB).ag_ap = ag_pstt[ag_t1];
    if ((ag_s_procs_scan[ag_astt[ag_t1]])() == 0) break;
  }
  return 0;
}

static int ag_action_8_proc(void) {
  ag_trace_error();
  (PCB).la_ptr = (PCB).pointer;
  (PCB).exit_flag = AG_SYNTAX_ERROR_CODE;
  ag_diagnose();
  SYNTAX_ERROR;
  (PCB).la_ptr = ++(PCB).pointer;
  return (PCB).exit_flag == AG_RUNNING_CODE;
}

static int ag_action_5_proc(void) {
  int ag_sd = ag_fl[(PCB).ag_ap];
  if (ag_sd) (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
  else {
    (PCB).ss[(PCB).ssx] = (PCB).sn;
  }
  (PCB).la_ptr = (PCB).pointer;
  (PCB).reduction_token = (mas_token_type) ag_ptt[(PCB).ag_ap];
  ag_ra();
  while ((PCB).exit_flag == AG_RUNNING_CODE) {
    unsigned ag_t1 = ag_sbe[(PCB).sn] + 1;
    unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1;
    do {
      unsigned ag_tx = (ag_t1 + ag_t2)/2;
      if (ag_tstt[ag_tx] < (unsigned char)(PCB).reduction_token) ag_t1 = ag_tx + 1;
      else ag_t2 = ag_tx;
    } while (ag_t1 < ag_t2);
    if (ag_tstt[ag_t1] != (PCB).reduction_token) {
      (PCB).exit_flag = AG_REDUCTION_ERROR_CODE; ag_trace_error();
      REDUCTION_TOKEN_ERROR; break;}
      (PCB).ag_ap = ag_pstt[ag_t1];
    if ((ag_r_procs_scan[ag_astt[ag_t1]])() == 0) break;
  }
  return (PCB).exit_flag == AG_RUNNING_CODE;
}

static int ag_action_6_proc(void) {
  int ag_sd = ag_fl[(PCB).ag_ap];
  (PCB).reduction_token = (mas_token_type) ag_ptt[(PCB).ag_ap];
  if (ag_sd) {
    (PCB).sn = (PCB).ss[(PCB).ssx -= ag_sd];
  }
  else {
    if ((PCB).ssx >= 128) {
      ag_trace_error();
      (PCB).exit_flag = AG_STACK_ERROR_CODE;
      PARSER_STACK_OVERFLOW;
    }
    (PCB).vs[(PCB).ssx] = ag_null_value;
    (PCB).ss[(PCB).ssx] = (PCB).sn;
  }
  (PCB).la_ptr = (PCB).pointer;
  while ((PCB).exit_flag == AG_RUNNING_CODE) {
    unsigned ag_t1 = ag_sbe[(PCB).sn] + 1;
    unsigned ag_t2 = ag_sbt[(PCB).sn+1] - 1;
    do {
      unsigned ag_tx = (ag_t1 + ag_t2)/2;
      if (ag_tstt[ag_tx] < (unsigned char)(PCB).reduction_token) ag_t1 = ag_tx + 1;
      else ag_t2 = ag_tx;
    } while (ag_t1 < ag_t2);
    if (ag_tstt[ag_t1] != (PCB).reduction_token) {
      (PCB).exit_flag = AG_REDUCTION_ERROR_CODE; ag_trace_error();
      REDUCTION_TOKEN_ERROR; break;}
      (PCB).ag_ap = ag_pstt[ag_t1];
    if ((ag_r_procs_scan[ag_astt[ag_t1]])() == 0) break;
  }
  return (PCB).exit_flag == AG_RUNNING_CODE;
}


void init_mas(void) {
  (PCB).la_ptr = (PCB).pointer;
  (PCB).ss[0] = (PCB).sn = (PCB).ssx = 0;
  (PCB).exit_flag = AG_RUNNING_CODE;
}

void mas(void) {
  init_mas();
  (PCB).exit_flag = AG_RUNNING_CODE;
  while ((PCB).exit_flag == AG_RUNNING_CODE) {
    unsigned ag_t1 = ag_sbt[(PCB).sn];
    if (ag_tstt[ag_t1]) {
      unsigned ag_t2 = ag_sbe[(PCB).sn] - 1;
      (PCB).token_number = (mas_token_type) AG_TCV(INPUT_CODE(*(PCB).la_ptr));
      (PCB).la_ptr++;
      do {
        unsigned ag_tx = (ag_t1 + ag_t2)/2;
        if (ag_tstt[ag_tx] > (unsigned char)(PCB).token_number)
          ag_t1 = ag_tx + 1;
        else ag_t2 = ag_tx;
      } while (ag_t1 < ag_t2);
      if (ag_tstt[ag_t1] != (unsigned char)(PCB).token_number)
        ag_t1 = ag_sbe[(PCB).sn];
    }
    (PCB).ag_ap = ag_pstt[ag_t1];
    (ag_gt_procs_scan[ag_astt[ag_t1]])();
  }
}