        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
        %                                                       % 
        %            MINI - a small META system                 % 
        %                                                       % 
        %          Copyright (c) Robert R. Kessler 1979         % 
        %          Mods: MLG, Feb 1981				%
        %                                                       % 
        %          This is the MINI system self definition.     % 
        %          The file MINI-SUPPORT.RED contains the       % 
        %          support routines and MINI.SL is the          % 
        %          Standard LISP translation of this file.      %
        %                                                       % 
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
 
%   The following is the definition of the mini meta system in terms of 
%    itself.  MINI is very similar to META/REDUCE, except a lot of it has 
%    been eliminated.  The following features that are in META/REDUCE, are 
%    not present in MINI: 
%       - Backup is not supported. 
%       - Diphthongs of more than 2 characters are not supported.  Also, in 
%         MINI, the diphthongs must be declared before they are used. 
%       - Format operations are not supported (the => op). 
%       - The symbol table operations are not supported (however, they could 
%         easily be added as calls to the routines. 
%       - The - operator for stripping off a level of parens is not supported. 
%       - The META/REDUCE error operators are not supported (*** *****). 
%    The following is a list of the differences between MINI and META/REDUCE: 
%       - The += operator has been changed to +. to be consistent with the 
%         meanings of the + (PUSH) and . (EVAL) operators. 
%       - The @ operator also includes the semantics that it's token is used 
%         as a rule terminator (for error recovery).  When a token is found 
%         during error recovery that is a rule terminator, the grammar is 
%         reset to its initial stage and scanning continues. 
%       - A new operator @@ has been added that is the same as the @ operator 
%         but it signifies a grammar terminator.  During error recovery, if 
%         a grammar terminator is scanned, parsing will stop. 
%       - The flag MDEFN controls whether a rule defined is EVALED or MPRINTed. 
%       - MINI uses the RLISP token reader and is therefore much faster. 
%         One consequences of this is that comments may be embedded anywhere 
%         in the text and are ignored by %SCAN
%         Also, since %SCAN is used, certain quoted keywords need to have a 
%         escape in front of them.  The ones discovered so far are: '!+ '!- 
%         '!( and '!).  This also means that diphthongs that use these as
%         the first character must also be quoted (i.e.  '!+= or '!-.). 
%         The safe approach is to quote every special character. 
 
%   To define a grammar, call the procedure MINI with the argument being the 
%    root rule name.   Then when the grammar is defined it may be called by 
%    using INVOKE root rule name. 
 
%   The following is the MINI Meta self definition. 
 
GLOBAL '(PNAM); 
 
MINI 'RUL; 
 
%   Define the diphthongs to be used in the grammar. 
DIP: !#!#, !-!>, !+!., !@!@ ; 
 
%   The root rule is called RUL. 
RUL: ('DIP ': ANYTOK[,]* .(DIPBLD #1) '; / 
     (ID  .(SETQ !#LABLIST!# NIL) 
       ( ': ALT            +(DE #2 NIL #1) @; / 
         '= PRUL[,]* @;    .(RULE!-DEFINE '(PUT (QUOTE ##2) (QUOTE RB) 
			     (QUOTE #1)))
                           +(DE ##1 (A) 
                               (RBMATCH A (GET (QUOTE #1) (QUOTE RB)) NIL)))
       .(RULE!-DEFINE #1) .(NEXT!-TOK) ))* @@FIN ; 
 
%   An alternative is a sequence of statements separated by /'s; 
ALT: SEQ < '/ ALT +(OR #2 #1) >; 
 
%   A sequence is a list of items that must be matched. 
SEQ: REP < SEQ +(AND #2 (FAIL!-NOT #1)) >; 
 
%   A repetition may be 0 or more single items (*) or 0 or more items 
%    separated by any token (ID[,]* will parse a list of ID's separated by ,'s. 
REP: ONE 
      <'[ (ID +(#1) / 
           '' ANYKEY +(EQTOK!-NEXT (QUOTE #1)) /
           ANYKEY +(EQTOK!-NEXT (QUOTE #1))) '] +(AND #2 #1) '* BLD!-EXPR /
        '* BLD!-EXPR>;

%   Create an sexpression to build a repetition.
BLD!-EXPR: +(PROG (X) (SETQ X (STK!-LENGTH)) 
                   $1 (COND (#1 (GO $1))) 
                      (BUILD!-REPEAT X) 
                      (RETURN T));

ANYKEY: ANYTOK .(ADDKEY ##1) ;  % Add a new KEY

%   One defines a single item. 
ONE: '' ANYKEY  +(EQTOK!-NEXT (QUOTE #1)) / 
     '@ ANYKEY  .(ADDRTERM ##1)  +(EQTOK (QUOTE #1)) / 
     '@@ ANYKEY .(ADDGTERM ##1)  +(EQTOK (QUOTE #1)) / 
     '+ UNLBLD  +(PUSH #1) / 
     '. EVLBLD  +(PROGN #1 T) / 
     '= EVLBLD  / 
     '< ALT '>  +(PROGN #1 T) / 
     '( ALT ')  / 
     '+. EVLBLD +(PUSH #1) / 
     ID         +(#1) ; 
 
%   This rule defines an un evaled list.  It builds a list with everything 
%    quoted. 
UNLBLD: '( UNLBLD ('. UNLBLD ') +(CONS #2 #1) /
		    UNLBLD* ') +(LIST . (#2 . #1)) /
		   ') +(LIST . #1)) / 
        LBLD    / 
        ID      +(QUOTE #1) ; 
 
%   EVLBLD builds a list of evaled items. 
EVLBLD: '( EVLBLD ('. EVLBLD ') +(CONS #2 #1) /
		    EVLBLD* ') +(#2 . #1) /
		   ') ) / 
        LBLD / 
        ID      ; 
 
LBLD: '# NUM    +(EXTRACT #1) /
      '## NUM   +(REF #1) /
      '$ NUM    +(GENLAB #1) /
      '& NUM    +(CADR (ASSOC #1 (CAR VARLIST))) /
      NUM       /
      STR       /
      '' ('( UNLBLD* ') +(LIST . #1) /
           ANYTOK +(QUOTE #1));
 
%   Defines the pattern matching rules (PATTERN -> BODY). 
PRUL: .(SETQ INDEXLIST!* NIL) 
      PAT '-> (EVLBLD)* 
             +(LAMBDA (VARLIST T1 T2 T3) (AND . #1))
             .(SETQ PNAM (GENSYM)) 
	     .(RULE!-DEFINE (LIST 'PUTD (LIST 'QUOTE PNAM) 
		'(QUOTE EXPR) (LIST 'QUOTE #1)))
             +.(CONS #1 PNAM);
 
%   Defines a pattern. 
%   We now allow the . operator to be the next to last in a ().
PAT: '& ('< PSIMP[/]* '> NUM 
             +.(PROGN (SETQ INDEXLIST!* (CONS ##1 INDEXLIST!*)) 
                  (LIST '!& #2 #1) ) / 
             NUM 
               +.(COND ((MEMQ ##1 INDEXLIST!*) 
                         (LIST '!& '!& #1)) 
                  (T (PROGN (SETQ INDEXLIST!* (CONS ##1 INDEXLIST!*)) 
                         (LIST '!& #1)))) ) 
        / ID 
        / '!( PAT* <'. PAT +.(APPEND #2 #1)> '!) 
        / '' ANYTOK 
        / STR 
        / NUM ; 
 
%   Defines the primitives in a pattern. 
PSIMP: ID / NUM / '( PSIMP* ') / '' ANYTOK; 
 
%   The grammar terminator. 
FIN 
END; 
 
