#
#  File: instructions.k3
#  Defines instruction generating routines.
#
#  Copyright 2005 Radboud University of Nijmegen
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Library General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#  CVS ID: "$Id: instructions.k3,v 1.23 2006/08/09 11:13:09 marcs Exp $"
#
MODULE instructions = LABELNR TODOS DEBUGLABELNR LEXICON_ALT_LABEL.

DEFINES	ACTION end of code generation,

        LABEL,
	ACTION new lrec LABEL>,
        ACTION new fail LABEL>,
        ACTION new debuginfo LABEL>,
        FUNCTION new call LABEL> for >NONTERMINAL,
        FUNCTION new fail LABEL> for >NONTERMINAL,
        FUNCTION empty LABEL>,
        FUNCTION new trans LABEL> for >NONTERMINAL at >ALTNO,
        FUNCTION new tree LABEL> for >NONTERMINAL at >ALTNO,
        FUNCTION convert >LABEL to TEXT>,
        FUNCTION convert >TEXT to LABEL>,
        ACTION generate call >LABEL,
        ACTION generate undo >LABEL,
        FUNCTION convert name >ID to LABEL>,
        ACTION generate applied >LABEL,
        ACTION generate >LABEL,
        ACTION export >LABEL,
        ACTION export >TEXT,
        FUNCTION convert weight >INT to LABEL>,
        FUNCTION convert domain >INT to LABEL>,
        ACTION generate null pointer,

        ACTION announce rule (>NONTERMINAL),
        ACTION denounce rule (>NONTERMINAL),
        ACTION create stack frame (>INT1, >INT2, >INT3, >LABEL),
        ACTION create root stack frame (>INT1, >INT2, >INT3),
	ACTION generate clear instruction (>INT),
        ACTION generate fail instruction,

        ACTION announce start lhs,
        ACTION denounce start lhs,

        ACTION announce alt (>ALTNO),
        ACTION denounce alt (>ALTNO),

        ACTION generate success and fail to >LABEL,
        ACTION generate undo success,
        ACTION generate second pass call (>LABEL1, >LABEL2),
        ACTION generate end instruction (>INT1, >INT2),

        ACTION generate commit to >LABEL,
        
        ACTION generate call to rule >INT at >LABEL1 failing to >LABEL2,
        ACTION generate undo call (>INT),
        ACTION generate normal continuation (>LABEL1, >LABEL2),

        ACTION generate lexmatch for >INT failing to >LABEL,
        ACTION generate undo lexmatch for >INT,

        ACTION generate match terminal >INT1 using >INT2 targeting >INT3 failing to >LABEL,
        ACTION generate regexp skip >INT1 using >INT2 targeting >INT3 failing to >LABEL,
        ACTION generate regexp match >INT1 using >INT2 targeting >INT3 failing to >LABEL,
	ACTION generate match other using >INT1 targeting >INT2 failing to >LABEL,
        ACTION generate unmatch terminal targeting >INT,
        ACTION generate unmatch regexp targeting >INT,
	ACTION generate unmatch other targeting >INT,

	ACTION generate input pos using >INT1 targeting >INT2 failing to >LABEL,
	ACTION generate uinput pos using >INT1 targeting >INT2,
        
        ACTION generate integer init >INT1 to >INT2,
        ACTION generate set init >INT to >SET,
        ACTION generate text init >INT to >LABEL,
        ACTION generate adjust integer for >INT1 to param >INT2 failing to >LABEL,
        ACTION generate adjust set for >INT1 to param >INT2 failing to >LABEL,
        ACTION generate adjust text for >INT1 to param >INT2 failing to >LABEL,
        ACTION generate undo adjust integer for >INT1 to param >INT2,
        ACTION generate undo adjust set for >INT1 to param >INT2,
        ACTION generate undo adjust text for >INT1 to param >INT2,
        ACTION generate integer restrict >INT1 to >INT2 failing to >LABEL2,
        ACTION generate set restrict >INT to >SET failing to >LABEL,
        ACTION generate text restrict >INT to >LABEL1 failing to >LABEL2,
        ACTION generate undo restrict integer (>INT),
        ACTION generate undo restrict set (>INT),
        ACTION generate undo restrict text (>INT),
        
        ACTION generate penalty of >INT failing to >LABEL,
        ACTION generate undo penalty of >INT,

        ACTION announce trans (>NONTERMINAL, >ALTNO, >LABEL),
        ACTION denounce trans (>NONTERMINAL, >ALTNO),
        ACTION announce tree (>NONTERMINAL, >ALTNO, >LABEL, LABEL1>),
        ACTION denounce tree (>NONTERMINAL, >ALTNO),

        ACTION generate begin alternative (>LABEL),
        ACTION generate begin lexicon alternative,
        ACTION generate end alternative,
        ACTION generate begin param pack,
        ACTION generate param pack seperator,
        ACTION generate end param pack,
        
        ACTION generate print text (>LABEL),
        ACTION generate print terminal (>INT),
        ACTION generate push formal (>INT),
        ACTION generate push local (>INT),
        ACTION generate print son (>INT),
        ACTION generate print lexicon nonterminal name (>ID),
        ACTION generate print lexicon nonterminal (>INT),
        ACTION generate print regexp (>INT),
	ACTION generate print other (>INT),
        ACTION generate print input pos (>INT),
        ACTION generate print penalty (>INT),
        ACTION generate print integer affix local (>INT),
        ACTION generate print set affix local (>INT1, >INT2),
        ACTION generate print text affix local (>INT),
        ACTION generate print integer affix formal (>INT),
        ACTION generate print set affix formal (>INT1, >INT2),
        ACTION generate print text affix formal (>INT),

        ACTION generate agfl version (>TEXT),
        ACTION generate grammar version (>INT),
        ACTION generate number of lexicon nonterminals (>INT),
        ACTION generate number of syntax terminals (>INT),
        ACTION generate number of regexp matches (>INT),
        ACTION generate number of regexp skips (>INT),
        ACTION generate number of syntax nonterminals (>INT),
        ACTION generate number of memos (>INT),
        ACTION generate number of choices (>INT),
        ACTION generate number of positions (>INT),
        ACTION generate eos terminal (>INT),

        ACTION generate prelude,
        ACTION generate postlude,
        ACTION generate brief comment (>TEXT),
        ACTION generate comment (>TEXT),
        ACTION generate align,
        ACTION generate long (>INT),
        ACTION generate long (>TEXT),
        ACTION generate max long,
        ACTION generate byte (>INT),
        ACTION generate set (>SET),
        
        ACTION generate director test for memo >INT failing to >LABEL,
        ACTION generate negative memo test (>INT, >LABEL),
        ACTION generate negative memo set succeeded (>INT),

        ACTION generate posmemo call to rule >INT at >LABEL1 failing to >LABEL2,

        ACTION generate choice (>INT1, >INT2),
        ACTION generate undo choice (>INT),
        ACTION generate alternative marker (>LABEL),
        ACTION generate undo alternative marker,

        ACTION generate mark lrec (>LABEL),
        ACTION generate umark lrec (>LABEL),
        
        ACTION generate position instruction (>INT),
        ACTION generate trace instruction (>LABEL).

USES globals, io, set, id, rule, intermediate, properties, textstorage.

PRELUDE init instructions:
  init todos,
    init labels,
    init lexicon alternative label.

ACTION init lexicon alternative label:
  convert "LexAlt" to LEXICON_ALT_LABEL,
    ["from lexicon" -> TEXT],
    postpone transduction TEXT at LEXICON_ALT_LABEL.

ACTION end of code generation:
  generate postponed constants.


#
# Label handling
#
LABEL :: empty; TEXT.
LABELNR = INT.
DEBUGLABELNR = INT.
LEXICON_ALT_LABEL = LABEL.

ACTION init labels:
  [ 0 -> LABELNR ], [ 0 -> DEBUGLABELNR ].

FUNCTION incr >INT>:
  [ INT + 1 -> INT ].

FUNCTION convert >LABEL to TEXT>:
  [ LABEL -> TEXT ];
  [ LABEL -> empty ], ?;
  ?.

FUNCTION convert >TEXT to LABEL>:
  [ TEXT -> LABEL ].

FUNCTION empty LABEL>:
  [ empty -> LABEL ].

ACTION new lrec LABEL>:
  convert LABELNR to TEXT,
    incr LABELNR,
    convert ("L" + TEXT) to LABEL.

ACTION new fail LABEL>:
  convert LABELNR to TEXT,
    incr LABELNR,
    convert ("L" + TEXT) to LABEL.

ACTION new debuginfo LABEL>:
  convert DEBUGLABELNR to TEXT,
    incr DEBUGLABELNR,
    convert ("Ldebug" + TEXT) to LABEL.

FUNCTION new call LABEL> for >NONTERMINAL:
  convert NONTERMINAL to INT,
    convert INT to TEXT,
    convert ("Lnont_" + TEXT) to LABEL.

FUNCTION new fail LABEL> for >NONTERMINAL:
  convert NONTERMINAL to INT,
    convert INT to TEXT,
    convert ("Lfail_" + TEXT) to LABEL.

FUNCTION new trans LABEL> for >NONTERMINAL at >ALTNO:
  convert NONTERMINAL to INT,
    convert INT to TEXT1,
    convert ALTNO to label TEXT2,
    convert ("Ltrans_" + TEXT1 + "_" + TEXT2) to LABEL.

FUNCTION new tree LABEL> for >NONTERMINAL at >ALTNO:
  convert NONTERMINAL to INT,
    convert INT to TEXT1,
    convert ALTNO to label TEXT2,
    convert ("Ltree_" + TEXT1 + "_" + TEXT2) to LABEL.

ACTION generate >LABEL:
  put LABEL def.

ACTION put >LABEL def:
  convert LABEL to TEXT,
    output code (TEXT + ":\n").

ACTION put >LABEL use:
  convert LABEL to TEXT,
    output code (TEXT).

ACTION generate call >LABEL:
  put LABEL def.

ACTION generate undo >LABEL:
  put LABEL def.

FUNCTION convert name >ID to LABEL>:
  convert ID to TEXT,
    ["Lid" + TEXT -> TEXT],
    convert TEXT to LABEL.

ACTION generate applied >LABEL:
  convert LABEL to TEXT,
    output code ("\tLONG(" + TEXT + ")\n").

ACTION export >LABEL:
  if underscore option,
    convert LABEL to TEXT,
    ["_" + TEXT -> TEXT],
    generate align,
    output code ("\tGLOBAL(" + TEXT + ")\n"),
    convert TEXT to LABEL,
    put LABEL def;
  convert LABEL to TEXT,
    generate align,
    output code ("\tGLOBAL(" + TEXT + ")\n"),
    put LABEL def.

ACTION export >TEXT:
  convert TEXT to LABEL,
    export LABEL.

FUNCTION convert weight >INT to LABEL>:
  bindec (INT, TEXT),
    ["Lwght" + TEXT -> TEXT],
    convert TEXT to LABEL.

FUNCTION convert domain >INT to LABEL>:
  bindec (INT, TEXT),
    ["Ldom" + TEXT -> TEXT],
    convert TEXT to LABEL.

ACTION generate null pointer:
  output code ("\tLONG(0)\n").


#####################
#                   #
#  Helper macro's:  #
#                   #
#####################

ACTION generate byte (>INT):
  bindec (INT, TEXT),
    output code ("\tBYTE(" + TEXT + ")\n").

ACTION generate long (>INT):
  bindec (INT, TEXT),
    generate long (TEXT).

ACTION generate long (>TEXT):
  output code ("\tLONG(" + TEXT + ")\n").

ACTION generate max long:
  generate long ("LONG_MAX").

ACTION generate align:
  output code ("\tALIGN\n").

ACTION generate text (>TEXT):
  output code ("\tTEXT(\"" + TEXT + "\")\n").

ACTION generate set (>SET):
  convert SET to hex TEXT,
    generate long (TEXT).


###############
#             #
#  Comments:  #
#             #
###############

ACTION newline:
  output code ("\n").

ACTION short comment (>TEXT):
  output code ("\t/* " + TEXT + " */\n").

ACTION long comment (>TEXT):
  output code ("/*\n** " + TEXT + "\n*/\n").

ACTION announce rule (>NONTERMINAL):
  convert NONTERMINAL to TEXT,
    long comment ("Start of code for " + TEXT).

ACTION denounce rule (>NONTERMINAL):
#  convert NONTERMINAL to TEXT,
#    long comment ("End of code for " + TEXT),
    output code ("\n").

ACTION announce start lhs:
  short comment ("begin LHS").

ACTION denounce start lhs:
  short comment ("end LHS").

ACTION announce alt (>ALTNO):
  convert ALTNO to printable TEXT,
    short comment ("begin alt " + TEXT).

ACTION denounce alt (>ALTNO):
  convert ALTNO to printable TEXT,
    short comment ("end alt " + TEXT).

ACTION generate print lexicon nonterminal name (>ID):
  convert name ID to LABEL2,
    convert LABEL2 to TEXT3,
    output code ("\tPRINT_N(" + TEXT3 + ")\n").

ACTION announce trans (>NONTERMINAL, >ALTNO, >LABEL):
  convert NONTERMINAL to TEXT1,
    convert ALTNO to printable TEXT2,
    short comment ("Start of trans " + TEXT2 + " of " + TEXT1),
    put LABEL def.

ACTION denounce trans (>NONTERMINAL, >ALTNO):
  convert NONTERMINAL to TEXT1,
    convert ALTNO to printable TEXT2,
    output code ("\tRETRN\n"),
#    short comment ("End of trans " + TEXT2 + " of " + TEXT1),
    newline.

ACTION announce tree (>NONTERMINAL, >ALTNO, >LABEL, LABEL1>):
  convert NONTERMINAL to TEXT1,
    convert ALTNO to printable TEXT2,
    short comment ("Start of tree " + TEXT2 + " of " + TEXT1),
    convert NONTERMINAL to INT,
    convert INT to TEXT9,
    convert ALTNO to label TEXT,
    ["Lalttext_" + TEXT9 + "_" + TEXT -> TEXT],
    convert TEXT to LABEL1,
    postpone transduction TEXT2 at LABEL1,
    put LABEL def,
    (is invisible in tree (NONTERMINAL);
     convert NONTERMINAL to ID and ARITY,
       convert name ID to LABEL2,
       convert LABEL2 to TEXT3,
       output code ("\tPRINT_N(" + TEXT3 + ")\n")).

ACTION denounce tree (>NONTERMINAL, >ALTNO):
  convert NONTERMINAL to TEXT1,
    convert ALTNO to printable TEXT2,
    output code ("\tRETRN\n"),
#    short comment ("End of tree " + TEXT2 + " of " + TEXT1),
    newline.

ACTION generate begin alternative (>LABEL):
  convert LABEL to TEXT,
    output code ("\tPRINT_ABEG(" + TEXT + ")\n").

ACTION generate begin lexicon alternative:
  generate begin alternative (LEXICON_ALT_LABEL).

ACTION generate end alternative:
  output code ("\tPRINT_AEND\n").

ACTION generate begin param pack:
  output code ("\tPRINT_PBEG\n").

ACTION generate param pack seperator:
  output code ("\tPRINT_PSEP\n").

ACTION generate end param pack:
  output code ("\tPRINT_PEND\n").

ACTION generate brief comment (>TEXT):
  short comment (TEXT).

ACTION generate comment (>TEXT):
  long comment (TEXT).

ACTION generate prelude:
  get include path (TEXT),
    output code ("#include \"" + TEXT + "/machdep.h\"\n"),
    get basename (TEXT),
    long comment ("Generated code part of " + TEXT),
    output code ("\tSTARTCODE\n").

ACTION generate postlude:
  output code ("\tENDCODE\n\n"),
    long comment ("Data for the generated code.").


#######################
#                     #
#  Various constants  #
#                     #
#######################

ACTION generate agfl version (>TEXT):
  long comment ("KUN AGFL system version " + TEXT),
    export "agfl_version",
    generate text (TEXT).

ACTION generate grammar version (>INT):
  export "gra_version",
    generate long (INT).

ACTION generate number of lexicon nonterminals (>INT):
  export "nr_lexicon_nonterminals",
    generate long (INT).

ACTION generate number of syntax terminals (>INT):
  export "nr_terminals",
    generate long (INT).

ACTION generate number of regexp matches (>INT):
  export "nr_match_regexps",
    generate long (INT).

ACTION generate number of regexp skips (>INT):
  export "nr_skip_regexps",
    generate long (INT).

ACTION generate number of syntax nonterminals (>INT):
  export "nr_syntax_nonterminals",
    generate long (INT).

ACTION generate number of memos (>INT):
  export "nr_memos",
    generate long (INT).

ACTION generate number of choices (>INT):
  export "nr_choices",
    generate long (INT).

ACTION generate number of positions (>INT):
  export "nr_positions",
    generate long (INT).

ACTION generate eos terminal (>INT):
  export "eos_terminal",
    generate long (INT).


###################
#                 #
#  Instructions:  #
#                 #
###################

### Stack frame freakin':

ACTION create stack frame (>INT1, >INT2, >INT3, >LABEL):
  convert INT1 to TEXT1,
    convert INT2 to TEXT2,
    convert INT3 to TEXT3,
    convert LABEL to TEXT4,
    output code ("\tCREATE(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ", " + TEXT4 + ")\n").

ACTION create root stack frame (>INT1, >INT2, >INT3):
  convert INT1 to TEXT1,
    convert INT2 to TEXT2,
    convert INT3 to TEXT3,
    output code ("\tROOT_CREATE(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate clear instruction (>INT):
  convert INT to TEXT,
  output code ("\tCLEAR(" + TEXT + ")\n").

ACTION generate fail instruction:
  output code ("\tFAIL\n").


### Root-rule instructions:

ACTION generate success and fail to >LABEL:
  convert LABEL to TEXT,
    output code ("\tSUCCESS(" + TEXT + ")\n").

ACTION generate undo success:
  output code ("\tUSUCCESS\n").

ACTION generate second pass call (>LABEL1, >LABEL2):
  convert LABEL1 to TEXT1,
    convert LABEL2 to TEXT2,
    output code ("\tPASS2(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate end instruction (>INT1, >INT2):
  convert INT1 to TEXT1,
    convert INT2 to TEXT2,
    output code ("\tEND(" + TEXT1 + ", " + TEXT2 + ")\n").


### Call instructions:

ACTION generate call to rule >INT at >LABEL1 failing to >LABEL2:
  convert INT to TEXT1,
    convert LABEL1 to TEXT2,
    convert LABEL2 to TEXT3,
    output code ("\tCALL(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate undo call (>INT):
  convert INT to TEXT,
    output code ("\tUCALL(" + TEXT + ")\n").

ACTION generate normal continuation (>LABEL1, >LABEL2):
  convert LABEL1 to TEXT1,
    convert LABEL2 to TEXT2,
    output code ("\tCONT(" + TEXT1 + ", " + TEXT2 + ")\n").


### Lexicon match instructions:
ACTION generate lexmatch for >INT failing to >LABEL:
  convert INT to TEXT1,
    convert LABEL to TEXT2,
    output code ("\tLEX_MATCH(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate undo lexmatch for >INT:
  convert INT to TEXT, output code ("\tLEX_UMATCH(" + TEXT + ")\n").

#
# Match instructions:
#
ACTION generate match terminal >INT1 using >INT2 targeting >INT3 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert INT3 to TEXT3, convert LABEL to TEXT4,
    output code ("\tMATCH(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ", " + TEXT4 + ")\n").

ACTION generate regexp skip >INT1 using >INT2 targeting >INT3 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert INT3 to TEXT3, convert LABEL to TEXT4,
    output code ("\tSKIP_RE(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ", " + TEXT4 + ")\n").

ACTION generate regexp match >INT1 using >INT2 targeting >INT3 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert INT3 to TEXT3, convert LABEL to TEXT4,
    output code ("\tMATCH_RE(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ", " + TEXT4 + ")\n").

ACTION generate match other using >INT1 targeting >INT2 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert LABEL to TEXT3,
    output code ("\tMATCH_OTHER(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate unmatch terminal targeting >INT:
  convert INT to TEXT, output code ("\tUMATCH(" + TEXT + ")\n").

ACTION generate unmatch regexp targeting >INT:
  convert INT to TEXT, output code ("\tUMATCH_RE(" + TEXT + ")\n").

ACTION generate unmatch other targeting >INT:
  convert INT to TEXT, output code ("\tUMATCH_OTHER(" + TEXT + ")\n").

#
# Input position instructions
#
ACTION generate input pos using >INT1 targeting >INT2 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert LABEL to TEXT3,
    output code ("\tINPUT_POS(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate uinput pos using >INT1 targeting >INT2:
  convert INT1 to TEXT1, convert INT2 to TEXT2,
    output code ("\tUINPUT_POS(" + TEXT1 + ", " + TEXT2 + ")\n").

#
# Affix operations:
#
ACTION generate integer init >INT1 to >INT2:
  convert INT1 to TEXT1, convert INT2 to TEXT2,
    output code ("\tINIT_I(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate set init >INT to >SET:
  convert INT to TEXT1, convert SET to hex TEXT2,
    output code ("\tINIT_S(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate text init >INT to >LABEL:
  convert INT to TEXT1, convert LABEL to TEXT2,
    output code ("\tINIT_T(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate adjust integer for >INT1 to param >INT2 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert LABEL to TEXT3,
    output code ("\tADJUST_I(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate adjust set for >INT1 to param >INT2 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert LABEL to TEXT3,
    output code ("\tADJUST_S(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate adjust text for >INT1 to param >INT2 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert LABEL to TEXT3,
    output code ("\tADJUST_T(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate undo adjust integer for >INT1 to param >INT2:
  convert INT1 to TEXT1, convert INT2 to TEXT2,
    output code ("\tUADJUST_I(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate undo adjust set for >INT1 to param >INT2:
  convert INT1 to TEXT1, convert INT2 to TEXT2,
    output code ("\tUADJUST_S(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate undo adjust text for >INT1 to param >INT2:
  convert INT1 to TEXT1, convert INT2 to TEXT2,
    output code ("\tUADJUST_T(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate integer restrict >INT1 to >INT2 failing to >LABEL:
  convert INT1 to TEXT1, convert INT2 to TEXT2, convert LABEL to TEXT3,
    output code ("\tRESTRICT_I(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate set restrict >INT to >SET failing to >LABEL:
  convert INT to TEXT1, convert SET to hex TEXT2, convert LABEL to TEXT3,
    output code ("\tRESTRICT_S(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate text restrict >INT to >LABEL1 failing to >LABEL2:
  convert INT to TEXT1, convert LABEL1 to TEXT2, convert LABEL2 to TEXT3,
    output code ("\tRESTRICT_T(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").

ACTION generate undo restrict integer (>INT):
  convert INT to TEXT, output code ("\tURESTRICT_I(" + TEXT + ")\n").

ACTION generate undo restrict set (>INT):
  convert INT to TEXT, output code ("\tURESTRICT_S(" + TEXT + ")\n").

ACTION generate undo restrict text (>INT):
  convert INT to TEXT, output code ("\tURESTRICT_T(" + TEXT + ")\n").

#
# Penalties:
#
ACTION generate penalty of >INT failing to >LABEL:
  convert INT to TEXT1, convert LABEL to TEXT2,
    output code ("\tPENALTY(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate undo penalty of >INT:
  convert INT to TEXT, output code ("\tUPENALTY(" + TEXT + ")\n").

#
# Commit:
#
ACTION generate commit to >LABEL:
  convert LABEL to TEXT, output code ("\tCOMMIT(" + TEXT + ")\n").

#
# Second pass instructions:
#
ACTION generate print text (>LABEL):
  convert LABEL to TEXT, output code ("\tPRINT_VAL(" + TEXT + ")\n").

ACTION generate print terminal (>INT):
  convert INT to TEXT, output code ("\tPRINT_TERM(" + TEXT + ")\n").

ACTION generate push formal (>INT):
  convert INT to TEXT, output code ("\tPUSH_F(" + TEXT + ")\n").

ACTION generate push local (>INT):
  convert INT to TEXT, output code ("\tPUSH_L(" + TEXT + ")\n").

ACTION generate print son (>INT):
  convert INT to TEXT, output code ("\tPRINT_SON(" + TEXT + ")\n").

ACTION generate print lexicon nonterminal (>INT):
  convert INT to TEXT, output code ("\tPRINT_LEX(" + TEXT + ")\n").

ACTION generate print regexp (>INT):
  convert INT to TEXT, output code ("\tPRINT_RE(" + TEXT + ")\n").

ACTION generate print other (>INT):
  convert INT to TEXT, output code ("\tPRINT_OTHER(" + TEXT + ")\n").

ACTION generate print input pos (>INT):
  convert INT to TEXT, output code ("\tPRINT_POS(" + TEXT + ")\n").

ACTION generate print penalty (>INT):
  convert INT to TEXT, output code ("\tPRINT_PEN(" + TEXT + ")\n").

ACTION generate print integer affix local (>INT):
  convert INT to TEXT, output code ("\tPRINT_IL(" + TEXT + ")\n").

ACTION generate print set affix local (>INT1, >INT2):
  convert INT1 to TEXT1, convert INT2 to TEXT2,
    output code ("\tPRINT_SL(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate print text affix local (>INT):
  convert INT to TEXT, output code ("\tPRINT_TL(" + TEXT + ")\n").

ACTION generate print integer affix formal (>INT):
  convert INT to TEXT, output code ("\tPRINT_IF(" + TEXT + ")\n").

ACTION generate print set affix formal (>INT1, >INT2):
  convert INT1 to TEXT1, convert INT2 to TEXT2,
    output code ("\tPRINT_SF(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate print text affix formal (>INT):
  convert INT to TEXT, output code ("\tPRINT_TF(" + TEXT + ")\n").

ACTION announce param pack:
  output code ("\tPRINT_PBEG\n").

ACTION denounce param pack:
  output code ("\tPRINT_PEND\n").

ACTION generate param seperator:
  output code ("\tPRINT_PSEP\n").


#
# Postponed texts with labels
#
TODOS = TODO_GEN_LIST.
TODO_GEN_LIST :: TODO_GEN_ITEM TODO_GEN_LIST;
                 nil.
TODO_GEN_ITEM :: LABEL with transduction TEXT.

ACTION init todos:
  [ nil -> TODOS ].

ACTION postpone transduction >TEXT at >LABEL:
  [LABEL with transduction TEXT -> TODO_GEN_ITEM],
    [TODO_GEN_ITEM TODOS -> TODOS].

ACTION generate postponed constants:
  generate postponed constants (TODOS).

ACTION generate postponed constants (>TODO_GEN_LIST):
  [TODO_GEN_LIST -> nil];
  [TODO_GEN_LIST -> TODO_GEN_ITEM TODO_GEN_LIST],
    generate postponed item (TODO_GEN_ITEM),
    generate postponed constants (TODO_GEN_LIST);
  ?.

ACTION generate postponed item (>TODO_GEN_ITEM):
  [TODO_GEN_ITEM -> LABEL with transduction TEXT],
    generate align,
    put LABEL def,
    generate text (TEXT).


#
# Optimization instructions
#
ACTION generate director test for memo >INT failing to >LABEL:
  convert INT to TEXT1,
    convert LABEL to TEXT2,
    output code ("\tTMEMO(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate negative memo test (>INT, >LABEL):
  convert INT to TEXT1,
    convert LABEL to TEXT2,
    output code ("\tTSMEMO(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate negative memo set succeeded (>INT):
  convert INT to TEXT,
    output code ("\tSMEMO_S(" + TEXT + ")\n").


#####################################
#                                   #
#  Generative grammar instructions  #
#                                   #
#####################################

ACTION generate choice (>INT1, >INT2):
  convert INT1 to TEXT1,
    convert INT2 to TEXT2,
    output code ("\tCHOICE(" + TEXT1 + ", " + TEXT2 + ")\n").

ACTION generate undo choice (>INT):
  convert INT to TEXT,
    output code ("\tUCHOICE(" + TEXT + ")\n").

ACTION generate alternative marker (>LABEL):
  convert LABEL to TEXT,
    output code ("\tALT_MARKER(" + TEXT + ")\n").

ACTION generate undo alternative marker:
  output code ("\tUALT_MARKER\n").

ACTION generate posmemo call to rule >INT at >LABEL1 failing to >LABEL2:
  convert INT to TEXT1,
    convert LABEL1 to TEXT2,
    convert LABEL2 to TEXT3,
    output code ("\tROOT_CALL(" + TEXT1 + ", " + TEXT2 + ", " + TEXT3 + ")\n").


# 
# Left recursion instructions
#
ACTION generate mark lrec (>LABEL):
  output code ("\tMARK_LREC\n").

ACTION generate umark lrec (>LABEL):
  convert LABEL to TEXT,
    output code ("\tUMARK_LREC(" + TEXT + ")\n").


# Position instruction

ACTION generate position instruction (>INT):
  convert INT to TEXT,
    output code ("\tPOSITION(" + TEXT + ")\n").

#######################
#                     #
#  Trace instruction  #
#                     #
#######################

ACTION generate trace instruction (>LABEL):
  convert LABEL to TEXT,
    output code ("\tTRACE(" + TEXT + ")\n").

