home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pccts1.zip / ANTLR / ANTLR.G < prev    next >
Text File  |  1993-09-01  |  23KB  |  784 lines

  1. /*
  2.  * antlr.g    --    PCCTS Version 1.xx ANTLR
  3.  *
  4.  * $Id: antlr.g,v 1.5 1993/08/24 14:44:32 pccts Exp pccts $
  5.  * $Revision: 1.5 $
  6.  *
  7.  * Parse an antlr input grammar and build a syntax-diagram.
  8.  *
  9.  * Terence Parr
  10.  * Purdue University
  11.  * August 1990
  12.  *
  13.  * Written in itself (needs at least 1.06 to work)
  14.  *
  15.  * SOFTWARE RIGHTS
  16.  *
  17.  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
  18.  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
  19.  * company may do whatever they wish with source code distributed with
  20.  * PCCTS or the code generated by PCCTS, including the incorporation of
  21.  * PCCTS, or its output, into commerical software.
  22.  * 
  23.  * We encourage users to develop software with PCCTS.  However, we do ask
  24.  * that credit is given to us for developing PCCTS.  By "credit",
  25.  * we mean that if you incorporate our source code into one of your
  26.  * programs (commercial product, research project, or otherwise) that you
  27.  * acknowledge this fact somewhere in the documentation, research report,
  28.  * etc...  If you like PCCTS and have developed a nice tool with the
  29.  * output, please mention that you developed it using PCCTS.  In
  30.  * addition, we ask that this header remain intact in our source code.
  31.  * As long as these guidelines are kept, we expect to continue enhancing
  32.  * this system and expect to make other tools available as they are
  33.  * completed.
  34.  *
  35.  * ANTLR 1.10
  36.  * Terence Parr
  37.  * Purdue University
  38.  * 1989-1993
  39.  */
  40. #header <<
  41.     #ifdef __cplusplus
  42.     #ifndef __STDC__
  43.     #define __STDC__
  44.     #endif
  45.     #endif
  46.     #include "set.h"
  47.     #include <ctype.h>
  48.     #include "syn.h"
  49.     #include "hash.h"
  50.     #include "generic.h"
  51.     #define zzcr_attr(attr,tok,t)
  52.     >>
  53.  
  54. <<
  55. #ifdef __STDC__
  56. static void chkToken(char *, char *, char *);
  57. #else
  58. static void chkToken();
  59. #endif
  60. >>
  61.  
  62. #lexclass STRINGS
  63. #token QuotedTerm "\""        << zzmode(START); >>
  64. #token "\n"                    <<
  65.                             zzline++;
  66.                             warn("eoln found in string");
  67.                             zzskip();
  68.                             >>
  69. #token "\\~[]"                << zzmore(); >>
  70. #token "~[\n\"\\]+"            << zzmore(); >>
  71.  
  72. #lexclass ACTION_STRINGS
  73. #token "\""                    << zzmode(ACTIONS); zzmore(); >>
  74. #token "\n"                    <<
  75.                             zzline++;
  76.                             warn("eoln found in string (in user action)");
  77.                             zzskip();
  78.                             >>
  79. #token "\\~[]"                << zzmore(); >>
  80. #token "~[\n\"\\]+"            << zzmore(); >>
  81.  
  82. #lexclass ACTION_CHARS
  83. #token "'"                    << zzmode(ACTIONS); zzmore(); >>
  84. #token "\n"                    <<
  85.                             zzline++;
  86.                             warn("eoln found in char literal (in user action)");
  87.                             zzskip();
  88.                             >>
  89. #token "\\~[]"                << zzmore(); >>
  90. #token "~[\n'\\]+"            << zzmore(); >>
  91.  
  92. #lexclass ACTION_COMMENTS
  93. #token "\*/"                << zzmode(ACTIONS); zzmore(); >>
  94. #token "\*"                    << zzmore(); >>
  95. #token "\n"                    << zzline++; zzmore(); >>
  96. #token "~[\n\*]+"            << zzmore(); >>
  97.  
  98. #lexclass ACTION_CPP_COMMENTS
  99. #token "\n"                    << zzline++; zzmode(ACTIONS); zzmore(); >>
  100. #token "~[\n]+"                << zzmore(); >>
  101.  
  102. #lexclass CPP_COMMENTS
  103. #token "\n"                    << zzline++; zzmode(START); zzskip(); >>
  104. #token "~[\n]+"                << zzskip(); >>
  105.  
  106. #lexclass COMMENTS
  107. #token "\*/"                << zzmode(START); zzskip(); >>
  108. #token "\*"                    << zzskip(); >>
  109. #token "\n"                    << zzline++; zzskip(); >>
  110. #token "~[\n\*]+"            << zzskip(); >>
  111.  
  112. /*
  113.  * This lexical class accepts actions of type [..] and <<..>>
  114.  *
  115.  * It translates the following special items:
  116.  *
  117.  * $j        --> "zzaArg(current zztasp, j)"
  118.  * $i.j        --> "zzaArg(zztaspi, j)"
  119.  * $i.nondigit> "zzaArg(current zztasp, i).nondigit"
  120.  * $$        --> "zzaRet"
  121.  * $alnum    --> "alnum"            (used to ref parameters)
  122.  * $rule    --> "zzaRet"
  123.  * $retval    --> "_retv.retval" if > 1 return values else "_retv"
  124.  * $[token, text] --> "zzconstr_attr(token, text)"
  125.  * $[]        --> "zzempty_attr()"
  126.  *
  127.  * And, for trees:
  128.  *
  129.  * #0        -->    "(*_root)"
  130.  * #i        --> "zzastArg(i)"
  131.  * #[args]    --> "zzmk_ast(zzastnew(), args)"
  132.  * #[]        --> "zzastnew()"
  133.  * #( root, child1, ..., childn )
  134.             --> "zztmake(root, child1, ...., childn, NULL)"
  135.  * #()        --> "NULL"
  136.  *
  137.  * To escape,
  138.  *
  139.  * \]        --> ]
  140.  * \)        --> )
  141.  * \$        --> $
  142.  * \#        --> #
  143.  *
  144.  * A stack is used to nest action terminators because they can be nested
  145.  * like crazy:  << #[$[..],..] >>
  146.  */
  147. #lexclass ACTIONS
  148. #token Action "\>\>"        << /* these do not nest */
  149.                               zzmode(START);
  150.                               NLATEXT[0] = ' ';
  151.                               NLATEXT[1] = ' ';
  152.                               zzbegexpr[0] = ' ';
  153.                               zzbegexpr[1] = ' ';
  154.                               if ( zzbufovf ) {
  155.                                 warn( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));
  156.                               }
  157.                             >>
  158. #token Pred "\>\>?"         << /* these do not nest */
  159.                               zzmode(START);
  160.                               NLATEXT[0] = ' ';
  161.                               NLATEXT[1] = ' ';
  162.                               zzbegexpr[0] = ' ';
  163.                               zzbegexpr[1] = ' ';
  164.                               zzbegexpr[2] = ' ';
  165.                               if ( zzbufovf ) {
  166.                                 warn( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE));
  167.                               }
  168.                             >>
  169. #token PassAction "\]"        << if ( topint() == ']' ) {
  170.                                   popint();
  171.                                   if ( istackempty() )    /* terminate action */
  172.                                   {
  173.                                       zzmode(START);
  174.                                       NLATEXT[0] = ' ';
  175.                                       zzbegexpr[0] = ' ';
  176.                                       if ( zzbufovf ) {
  177.                                         warn( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));
  178.                                       }
  179.                                   }
  180.                                   else {
  181.                                       /* terminate $[..] and #[..] */
  182.                                       zzreplstr(")");
  183.                                       zzmore();
  184.                                   }
  185.                                }
  186.                                else if ( topint() == '|' ) { /* end of simple [...] */
  187.                                   popint();
  188.                                   zzmore();
  189.                                }
  190.                                else zzmore();
  191.                             >>
  192. #token "\n"                    << zzline++; zzmore(); >>
  193. #token "\>"                    << zzmore(); >>
  194. #token "$"                    << zzmore(); >>
  195. #token "$$"                    << zzreplstr("zzaRet"); zzmore(); >>
  196. #token "$\[\]"                << zzreplstr("zzempty_attr"); zzmore(); >>
  197. #token "$\["                <<
  198.                             pushint(']');
  199.                             zzreplstr("zzconstr_attr(");
  200.                             zzmore();
  201.                             >>
  202. #token "$[0-9]+"            <<{
  203.                             static char buf[100];
  204.                             if ( strlen(zzbegexpr)>85 )
  205.                                 fatal("$i attrib ref too big");
  206.                             sprintf(buf,"zzaArg(zztasp%d,%s)",
  207.                                         BlkLevel-1,zzbegexpr+1);
  208.                             zzreplstr(buf);
  209.                             zzmore();
  210.                             }
  211.                             >>
  212. #token "$[0-9]+."            <<{
  213.                             static char buf[100];
  214.                             if ( strlen(zzbegexpr)>85 )
  215.                                 fatal("$i.field attrib ref too big");
  216.                             zzbegexpr[strlen(zzbegexpr)-1] = ' ';
  217.                             sprintf(buf,"zzaArg(zztasp%d,%s).",
  218.                                         BlkLevel-1,zzbegexpr+1);
  219.                             zzreplstr(buf);
  220.                             zzmore();
  221.                             }
  222.                             >>
  223. #token "$[0-9]+.[0-9]+"        <<{
  224.                             static char buf[100];
  225.                             static char i[20], j[20];
  226.                             char *p,*q;
  227.                             if (strlen(zzbegexpr)>85) fatal("$i.j attrib ref too big");
  228.                             for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) {
  229.                                 if ( q == &i[20] ) fatalFL("i of $i.j attrib ref too big", FileStr[CurFile], zzline );
  230.                                 *q++ = *p;
  231.                             }
  232.                             *q = '\0';
  233.                             for (p++, q= &j[0]; *p!='\0'; p++) {
  234.                                 if ( q == &j[20] ) fatalFL("j of $i.j attrib ref too big", FileStr[CurFile], zzline );
  235.                                 *q++ = *p;
  236.                             }
  237.                             *q = '\0';
  238.                             sprintf(buf,"zzaArg(zztasp%s,%s)",i,j);
  239.                             zzreplstr(buf);
  240.                             zzmore();
  241.                             }
  242.                             >>
  243. #token "$[_a-zA-Z][_a-zA-Z0-9]*"
  244.                             <<{ static char buf[300];
  245.                             zzbegexpr[0] = ' ';
  246.                             if ( CurRule != NULL &&
  247.                                  strcmp(CurRule, &zzbegexpr[1])==0 ) {
  248.                                 zzreplstr("zzaRet");
  249.                             }
  250.                             else if ( CurRetDef != NULL ) {
  251.                                 if ( strmember(CurRetDef, &zzbegexpr[1]) ) {
  252.                                     if ( HasComma( CurRetDef ) ) {
  253.                                         require (strlen(zzbegexpr)<=285,
  254.                                                  "$retval attrib ref too big");
  255.                                         sprintf(buf,"_retv.%s",&zzbegexpr[1]);
  256.                                         zzreplstr(buf);
  257.                                     }
  258.                                     else zzreplstr("_retv");
  259.                                 }
  260.                                 else if ( CurParmDef != NULL ) {
  261.                                     if ( !strmember(CurParmDef, &zzbegexpr[1]) )
  262.                                         warn(eMsg1("$%s not parameter or return value",&zzbegexpr[1]));
  263.                                 }
  264.                                 else warn(eMsg1("$%s not parameter or return value",&zzbegexpr[1]));
  265.                             }
  266.                             }
  267.                             zzmore();
  268.                             >>
  269. #token "#0"                    << zzreplstr("(*_root)"); zzmore(); >>
  270. #token "#\[\]"                << zzreplstr("zzastnew()"); zzmore(); >>
  271. #token "#\(\)"                << zzreplstr("NULL"); zzmore(); >>
  272. #token "#[0-9]+"            <<{
  273.                             static char buf[100];
  274.                             if ( strlen(zzbegexpr)>85 )
  275.                                 fatal("#i AST ref too big");
  276.                             sprintf(buf,"zzastArg(%s)",zzbegexpr+1);
  277.                             zzreplstr(buf);
  278.                             zzmore();
  279.                             }
  280.                             >>
  281. #token "#\["                <<
  282.                             pushint(']');
  283.                             zzreplstr("zzmk_ast(zzastnew(),");
  284.                             zzmore();
  285.                             >>
  286. #token "#\("                <<
  287.                             pushint('}');
  288.                             zzreplstr("zztmake(");
  289.                             zzmore();
  290.                             >>
  291. #token "#"                    << zzmore(); >>
  292. #token "\)"                    <<
  293.                             if ( istackempty() )
  294.                                 zzmore();
  295.                             else if ( topint()==')' ) {
  296.                                 popint();
  297.                             }
  298.                             else if ( topint()=='}' ) {
  299.                                 popint();
  300.                                 /* terminate #(..) */
  301.                                 zzreplstr(", NULL)");
  302.                             }
  303.                             zzmore();
  304.                             >>
  305. #token "\["                    <<
  306.                             pushint('|');    /* look for '|' to terminate simple [...] */
  307.                             zzmore();
  308.                             >>
  309. #token "\("                    <<
  310.                             pushint(')');
  311.                             zzmore();
  312.                             >>
  313.  
  314. #token "\\\]"                << zzreplstr("]");  zzmore(); >>
  315. #token "\\\)"                << zzreplstr(")");  zzmore(); >>
  316. #token "\\>"                << zzreplstr(">");  zzmore(); >>
  317.  
  318.  
  319. #token "'"                    << zzmode(ACTION_CHARS); zzmore();>>
  320. #token "\""                    << zzmode(ACTION_STRINGS); zzmore();>>
  321. #token "\\$"                << zzreplstr("$");  zzmore(); >>
  322. #token "\\#"                << zzreplstr("#");  zzmore(); >>
  323. /*#token "\\\\"                << zzmore(); >> /* need this for some reason */
  324. #token "\\~[\]\)>$#]"        << zzmore(); >> /* escaped char, always ignore */
  325. #token "/"                    << zzmore(); >>
  326. #token "/\*"                << zzmode(ACTION_COMMENTS); zzmore(); >>
  327. #token "\*/"                << warn("Missing /*; found dangling */ in action"); zzmore(); >>
  328. #token "//"                    << zzmode(ACTION_CPP_COMMENTS); zzmore(); >>
  329. #token "~[\n\)\(\\$#\>\]\[\"'/]+" << zzmore(); >>
  330.  
  331. #lexclass START
  332. #token "[\t\ ]+"            << zzskip(); >>                /* Ignore White */
  333. #token "[\n\r]"                << zzline++; zzskip(); >>    /* Track Line # */
  334. #token "\["                 << zzmode(ACTIONS); zzmore();
  335.                                istackreset();
  336.                                pushint(']'); >>
  337. #token "\<\<"               << action_file=CurFile; action_line=zzline;
  338.                                zzmode(ACTIONS); zzmore();
  339.                                istackreset();
  340.                                pushint('>'); >>
  341. #token "\""                    << zzmode(STRINGS); zzmore(); >>
  342. #token "/\*"                << zzmode(COMMENTS); zzskip(); >>
  343. #token "\*/"                << warn("Missing /*; found dangling */"); zzskip(); >>
  344. #token "//"                    << zzmode(CPP_COMMENTS); zzskip(); >>
  345. #token "\>\>"                << warn("Missing <<; found dangling \\>\\>"); zzskip(); >>
  346. #token Eof                    "@"
  347.                             <<    /* L o o k  F o r  A n o t h e r  F i l e */
  348.                             {
  349.                             FILE *new_input;
  350.                             new_input = NextFile();
  351.                             if ( new_input == NULL ) return;
  352.                             fclose( input );
  353.                             input = new_input;
  354.                             zzrdstream( input );
  355.                             /*zzadvance();    /* Get 1st char of this file */
  356.                             zzskip();    /* Skip the Eof (@) char i.e continue */
  357.                             }
  358.                             >>
  359.  
  360. /*
  361.  * Get a grammar -- Build a list of rules like:
  362.  *
  363.  *    o-->Rule1--o
  364.  *    |
  365.  *    o-->Rule2--o
  366.  *    |
  367.  *    ...
  368.  *    |
  369.  *    o-->RuleN--o
  370.  */
  371. grammar :    <<Graph g;>>
  372.             {    "#header" Action
  373.                 <<
  374.                 HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  375.                 require(HdrAction!=NULL, "rule grammar: cannot allocate header action");
  376.                 strcpy(HdrAction, LATEXT(1));
  377.                 >>
  378.             }
  379.             {    "#parser" QuotedTerm
  380.                 <<
  381.                 ParserName=StripQuotes(mystrdup(LATEXT(1)));
  382.                 if ( RulePrefix[0]!='\0' )
  383.                 {
  384.                     warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored");
  385.                     RulePrefix[0]='\0';
  386.                 }
  387.                 >>
  388.             }
  389.             (    <<char *a;>>
  390.                 Action
  391.                 <<
  392.                 a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  393.                 require(a!=NULL, "rule grammar: cannot allocate action");
  394.                 strcpy(a, LATEXT(1));
  395.                 list_add(&BeforeActions, a);
  396.                 >>
  397.             |    laction
  398.             |    aLexclass
  399.             |    token
  400.             |    error
  401.             )*
  402.             rule        <<g=$4; SynDiag = (Junction *) $4.left;>>
  403.             (    rule    <<if ( $1.left!=NULL ) {g.right = NULL; g = Or(g, $1);}>>
  404.             |    aLexclass
  405.             |    token
  406.             |    error
  407.             )*
  408.             (    <<char *a;>>
  409.                 Action
  410.                 <<
  411.                 a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  412.                 require(a!=NULL, "rule grammar: cannot allocate action");
  413.                 strcpy(a, LATEXT(1));
  414.                 list_add(&AfterActions, a);
  415.                 >>
  416.             |    laction
  417.             |    error
  418.             )*
  419.             Eof
  420.         ;
  421.         <<CannotContinue=TRUE;>>
  422.  
  423. /*
  424.  * Build -o-->o-R-o-->o-    where -o-R-o- is the block from rule 'block'.
  425.  * Construct the RuleBlk front and EndRule node on the end of the
  426.  * block.  This is used to add FOLLOW pointers to the rule end.  Add the
  427.  * new rule name to the Rname hash table and sets its rulenum.
  428.  * Store the parameter definitions if any are found.
  429.  *
  430.  * Note that locks are required on the RuleBlk and EndRule nodes to thwart
  431.  * infinite recursion.
  432.  *
  433.  * Return the left graph pointer == NULL to indicate error/dupl rule def.
  434.  */
  435. rule    :    <<RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e;
  436.               char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL;
  437.             >>
  438.             NonTerminal
  439.             <<q=NULL;
  440.               if ( hash_get(Rname, LATEXT(1))!=NULL ) {
  441.                   warn(eMsg1("duplicate rule definition: '%s'",LATEXT(1)))
  442.                   CannotContinue=TRUE;
  443.               }
  444.               else
  445.               {
  446.                     q = (RuleEntry *)hash_add(Rname,
  447.                                         LATEXT(1),
  448.                                         (Entry *)newRuleEntry(LATEXT(1)));
  449.                   CurRule = q->str;
  450.               }
  451.               CurRuleNode = q;
  452.               f = CurFile; l = zzline;
  453.               NumRules++;
  454.             >>
  455.             {    "!"   <<if ( q!=NULL ) q->noAST = TRUE;>> }
  456.             {    <<;>>
  457.                 {"\<"}
  458.                 PassAction
  459.                 <<    pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  460.                     require(pdecl!=NULL, "rule rule: cannot allocate param decl");
  461.                     strcpy(pdecl, LATEXT(1));
  462.                     CurParmDef = pdecl;
  463.                 >>
  464.             }
  465.             {    "\>"
  466.                 PassAction
  467.                 <<    ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  468.                     require(ret!=NULL, "rule rule: cannot allocate ret type");
  469.                     strcpy(ret, LATEXT(1));
  470.                     CurRetDef = ret;
  471.                 >>
  472.             }
  473.             { QuotedTerm <<if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1));>> }
  474.             <<
  475.             if ( GenEClasseForRules && q!=NULL ) {
  476.                 e = newECnode;
  477.                 require(e!=NULL, "cannot allocate error class node");
  478.                 if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);}
  479.                 else a = q->egroup;
  480.                 if ( Tnum( a ) == 0 )
  481.                 {
  482.                     e->tok = addTname( a );
  483.                     list_add(&eclasses, (char *)e);
  484.                     if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);
  485.                     /* refers to itself */
  486.                     list_add(&(e->elist), mystrdup(q->str));
  487.                 }
  488.                 else {
  489.                     warn(eMsg1("default errclass for '%s' would conflict with token/errclass",a));
  490.                     if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);
  491.                     free(e);
  492.                 }
  493.             }
  494.             >>
  495.             <<BlkLevel++;>>
  496.             ":" block        <<r = makeBlk($7);
  497.                               ((Junction *)r.left)->jtype = RuleBlk;
  498.                               if ( q!=NULL ) ((Junction *)r.left)->rname = q->str;
  499.                               ((Junction *)r.left)->file = f;
  500.                               ((Junction *)r.left)->line = l;
  501.                               ((Junction *)r.left)->pdecl = pdecl;
  502.                               ((Junction *)r.left)->ret = ret;
  503.                               ((Junction *)r.left)->lock = makelocks();
  504.                               ((Junction *)r.left)->pred_lock = makelocks();
  505.                               p = newJunction();    /* add EndRule Node */
  506.                               ((Junction *)r.right)->p1 = (Node *)p;
  507.                               r.right = (Node *) p;
  508.                               p->jtype = EndRule;
  509.                               p->lock = makelocks();
  510.                               p->pred_lock = makelocks();
  511.                               ((Junction *)r.left)->end = p;
  512.                               if ( q!=NULL ) q->rulenum = NumRules;
  513.                               $7 = r;
  514.                             >>
  515.             <<--BlkLevel;>>
  516.             ";"
  517.             {    Action
  518.                 <<    a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  519.                     require(a!=NULL, "rule rule: cannot allocate error action");
  520.                     strcpy(a, LATEXT(1));
  521.                     ((Junction *)r.left)->erraction = a;
  522.                 >>
  523.             }
  524.             <<if ( q==NULL ) $0.left = NULL; else $0 = $7;>>
  525.             <<CurRuleNode = NULL;>>
  526.         ;
  527.         <<CannotContinue=TRUE;>>
  528.  
  529. laction    :    <<char *a;>>
  530.             "#lexaction"
  531.             Action
  532.             <<
  533.             a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  534.             require(a!=NULL, "rule laction: cannot allocate action");
  535.             strcpy(a, LATEXT(1));
  536.             list_add(&LexActions, a);
  537.             >>
  538.         ;
  539.  
  540. aLexclass:    "#lexclass" TokenTerm <<lexclass(mystrdup(LATEXT(1)));>>
  541.         ;
  542.  
  543. error    :    <<char *t=NULL; ECnode *e; int go=1; TermEntry *p;>>
  544.             "#errclass"
  545.             (<<;>>    TokenTerm  <<t=mystrdup(LATEXT(1));>>
  546.             |        QuotedTerm <<t=mystrdup(LATEXT(1));>>
  547.             )
  548.             <<e = newECnode;
  549.               require(e!=NULL, "cannot allocate error class node");
  550.               e->lexclass = CurrentLexClass;
  551.               if ( Tnum( (t=StripQuotes(t)) ) == 0 )
  552.               {
  553.                 if ( hash_get(Texpr, t) != NULL )
  554.                     warn(eMsg1("errclass name conflicts with regular expression  '%s'",t));
  555.                   e->tok = addTname( t );
  556.                 require((p=(TermEntry *)hash_get(Tname, t)) != NULL,
  557.                         "hash table mechanism is broken");
  558.                 p->errclassname = 1;    /* entry is errclass name, not token */
  559.                 list_add(&eclasses, (char *)e);
  560.               }
  561.               else
  562.               {
  563.                   warn(eMsg1("redefinition of errclass or conflict w/token '%s'; ignored",t));
  564.                 free( e );
  565.                 go=0;
  566.               }
  567.             >>
  568.             "\{"
  569.                 ( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>>
  570.                 | TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
  571.                 | QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
  572.                 )
  573.                 <<if ( go ) list_add(&(e->elist), t);>>
  574.                 (
  575.                     ( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>>
  576.                     | TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
  577.                     | QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
  578.                     )
  579.                     <<if ( go ) list_add(&(e->elist), t);>>
  580.                 )*
  581.             "\}"
  582.         ;
  583.  
  584. token    :    <<char *t=NULL, *e=NULL, *a=NULL;>>
  585.             "#token"
  586.             { TokenTerm  <<t=mystrdup(LATEXT(1));>> }
  587.             { QuotedTerm <<e=mystrdup(LATEXT(1));>> }
  588.             {    Action
  589.                 <<
  590.                     a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  591.                     require(a!=NULL, "rule token: cannot allocate action");
  592.                     strcpy(a, LATEXT(1));
  593.                 >>
  594.             }
  595.             <<chkToken(t, e, a);>>
  596.         ;
  597.         <<CannotContinue=TRUE;>>
  598.  
  599. block    :    <<
  600.             Graph g, b;
  601.             >>
  602.             alt                <<b = g = $1;>>
  603.             <<
  604.             if ( ((Junction *)g.left)->p1->ntype == nAction )
  605.             {
  606.                 if ( !((ActionNode *)(((Junction *)g.left)->p1))->is_predicate )
  607.                 {
  608.                     ((ActionNode *)(((Junction *)g.left)->p1))->init_action = TRUE;
  609.                 }
  610.             }
  611.             >>
  612.             (    "\|"
  613.                 alt            <<g = Or(g, $2);>>
  614.             )*
  615.             <<$0 = b;>>
  616.         ;
  617.         <<CannotContinue=TRUE;>>
  618.  
  619. alt        :    <<int n=0; Graph g; g.left=g.right=NULL;>>
  620.             (    element     <<n++; g = Cat(g, $1);>>
  621.             )*
  622.             <<if ( n == 0 ) g = emptyAlt();
  623.               $0 = g;
  624.             >>
  625.         ;
  626.         <<CannotContinue=TRUE;>>
  627.  
  628. element    :    <<TokNode *p; RuleRefNode *q;>>
  629.             TokenTerm
  630.             <<$0 = buildToken(LATEXT(1));>>
  631.             (    <<p = (TokNode *) ((Junction *)$$.left)->p1;>>
  632.                 "^"    <<p->astnode=ASTroot;>>
  633.             |        <<p->astnode=ASTchild;>>
  634.             |    "!" <<p->astnode=ASTexclude;>>
  635.             )
  636.         |    QuotedTerm
  637.             <<$0 = buildToken(LATEXT(1));>>    
  638.             (    <<p = (TokNode *) ((Junction *)$$.left)->p1;>>
  639.                 "^"    <<p->astnode=ASTroot;>>
  640.             |        <<p->astnode=ASTchild;>>
  641.             |    "!" <<p->astnode=ASTexclude;>>
  642.             )
  643.         |    NonTerminal
  644.             <<$0 = buildRuleRef(LATEXT(1));>>
  645.             { "!" <<q = (RuleRefNode *) ((Junction *)$$.left)->p1;
  646.                     q->astnode=ASTexclude;>>
  647.             }
  648.             {    {"\<"}
  649.                 PassAction <<addParm(((Junction *)$$.left)->p1, LATEXT(1));>>
  650.             }
  651.             {    <<char *a; RuleRefNode *rr=(RuleRefNode *) ((Junction *)$$.left)->p1;
  652.                   >>
  653.                 "\>"
  654.                 PassAction
  655.                 <<
  656.                     a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  657.                     require(a!=NULL, "rule element: cannot allocate assignment");
  658.                     strcpy(a, LATEXT(1));
  659.                     rr->assign = a;
  660.                 >>
  661.             }
  662.         |    Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>>
  663.         |    Pred   <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>>
  664.             {    <<char *a; ActionNode *act = (ActionNode *) ((Junction *)$$.left)->p1;>>
  665.                 PassAction
  666.                 <<
  667.                 a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
  668.                 require(a!=NULL, "rule element: cannot allocate predicate fail action");
  669.                 strcpy(a, LATEXT(1));
  670.                 act->pred_fail = a;
  671.                 >>
  672.             }
  673.         |    <<BlkLevel++;>>
  674.             "\(" block <<$0 = $2; --BlkLevel;>> "\)"
  675.             (    "\*"        <<$$ = makeLoop($$);>>
  676.             |    "\+"        <<$$ = makePlus($$);>>
  677.             |    "?"            <<$$ = makeBlk($$);
  678.                               FoundGuessBlk = 1;
  679.                               ((Junction *) ((Junction *)$$.left)->p1)->guess=1;
  680.                             >>
  681.             |                <<$$ = makeBlk($$);>>
  682.             )
  683.             { PassAction <<addParm(((Junction *)$$.left)->p1, LATEXT(1));>> }
  684.         |    <<BlkLevel++;>>
  685.             "\{" block <<$0 = makeOpt($2); --BlkLevel;>> "\}"
  686.             { PassAction <<addParm(((Junction *)$$.left)->p1, LATEXT(1));>> }
  687.         |    ":"        <<warn(eMsg1("missing ';' on rule %s", CurRule));
  688.                       CannotContinue=TRUE;>>
  689.         |    "\*"    <<warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE;>>
  690.         |    "\+"    <<warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE;>>
  691.         |    "\>"    <<warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE;>>
  692.         |    PassAction <<warn("[...] out of context 'rule > [...]'");
  693.                          CannotContinue=TRUE;>>
  694.         ;
  695.         <<CannotContinue=TRUE;>>
  696.  
  697. #token NonTerminal        "[a-z] [A-Za-z0-9_]*"
  698. #token TokenTerm        "[A-Z] [A-Za-z0-9_]*"
  699. #token "#[A-Za-z0-9_]*"    <<warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); >>
  700.  
  701. <<
  702. /* semantics of #token */
  703. static void
  704. #ifdef __STDC__
  705. chkToken(char *t, char *e, char *a)
  706. #else
  707. chkToken(t,e,a)
  708. char *t, *e, *a;
  709. #endif
  710. {
  711.     if ( t==NULL && e==NULL ) {            /* none found */
  712.         warn("#token requires at least token name or rexpr");
  713.     }
  714.     else if ( t!=NULL && e!=NULL ) {    /* both found */
  715.         Tklink(t, e);
  716.         if ( a!=NULL ) {
  717.             if ( hasAction(e) ) {
  718.                 warn(eMsg1("redefinition of action for %s; ignored",e));
  719.             }
  720.             else setHasAction(e, a);
  721.         }
  722.     }
  723.     else if ( t!=NULL ) {                /* only one found */
  724.         if ( Tnum( t ) == 0 ) addTname( t );
  725.         else {
  726.             warn(eMsg1("redefinition of token %s; ignored",t));
  727.         }
  728.         if ( a!=NULL ) {
  729.             warn(eMsg1("action cannot be attached to a token name (%s); ignored",t));
  730.             free(a);
  731.         }
  732.     }
  733.     else if ( e!=NULL ) {
  734.         if ( Tnum( e ) == 0 ) addTexpr( e );
  735.         else {
  736.             if ( hasAction(e) ) {
  737.                 warn(eMsg1("redefinition of action for %s; ignored",e));
  738.             }
  739.             else if ( a==NULL ) {
  740.                 warn(eMsg1("redefinition of expr %s; ignored",e));
  741.             }
  742.         }
  743.         if ( a!=NULL ) setHasAction(e, a);
  744.     }
  745. }
  746. >>
  747. <<
  748. /* This is designed for use with 1.10, but if created with 1.06,
  749.  * must define SetWordType.  Also define EOF for 1.06.
  750. #define zzEOF_TOKEN 1
  751. typedef unsigned SetWordType;
  752.  */
  753.  
  754. /* ANTLR-specific syntax error message generator 
  755.  * (define USER_ZZSYN when compiling so don't get 2 definitions)
  756.  */
  757. void
  758. #ifdef __STDC__
  759. zzsyn(char *text, unsigned tok, char *egroup, SetWordType *eset, unsigned etok, int k, char *bad_text)
  760. #else
  761. zzsyn(text, tok, egroup, eset, etok, k, bad_text)
  762. char *text, *egroup, *bad_text;
  763. unsigned tok;
  764. unsigned etok;
  765. int k;
  766. SetWordType *eset;
  767. #endif
  768. {
  769.     fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline);
  770.     fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);
  771.     if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
  772.     if ( k==1 ) fprintf(stderr, " missing");
  773.     else
  774.     {
  775.         fprintf(stderr, "; \"%s\" not", bad_text);
  776.         if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
  777.     }
  778.     if ( zzset_deg(eset)>0 ) zzedecode(eset);
  779.     else fprintf(stderr, " %s", zztokens[etok]);
  780.     if ( strlen(egroup) > 0 ) fprintf(stderr, " in %s", egroup);
  781.     fprintf(stderr, "\n");
  782. }
  783. >>
  784.