home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / flex254.zip / parse.y < prev    next >
GNU Bison Grammar  |  1997-07-26  |  18KB  |  914 lines

  1. /* parse.y - parser for flex input */
  2.  
  3. %token CHAR NUMBER SECTEND SCDECL XSCDECL NAME PREVCCL EOF_OP
  4. %token OPTION_OP OPT_OUTFILE OPT_PREFIX OPT_YYCLASS
  5.  
  6. %token CCE_ALNUM CCE_ALPHA CCE_BLANK CCE_CNTRL CCE_DIGIT CCE_GRAPH
  7. %token CCE_LOWER CCE_PRINT CCE_PUNCT CCE_SPACE CCE_UPPER CCE_XDIGIT
  8.  
  9. %{
  10. /*-
  11.  * Copyright (c) 1990 The Regents of the University of California.
  12.  * All rights reserved.
  13.  *
  14.  * This code is derived from software contributed to Berkeley by
  15.  * Vern Paxson.
  16.  * 
  17.  * The United States Government has rights in this work pursuant
  18.  * to contract no. DE-AC03-76SF00098 between the United States
  19.  * Department of Energy and the University of California.
  20.  *
  21.  * Redistribution and use in source and binary forms with or without
  22.  * modification are permitted provided that: (1) source distributions retain
  23.  * this entire copyright notice and comment, and (2) distributions including
  24.  * binaries display the following acknowledgement:  ``This product includes
  25.  * software developed by the University of California, Berkeley and its
  26.  * contributors'' in the documentation or other materials provided with the
  27.  * distribution and in all advertising materials mentioning features or use
  28.  * of this software.  Neither the name of the University nor the names of
  29.  * its contributors may be used to endorse or promote products derived from
  30.  * this software without specific prior written permission.
  31.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  32.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  33.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  34.  */
  35.  
  36. /* $Header: /home/daffy/u0/vern/flex/RCS/parse.y,v 2.28 95/04/21 11:51:51 vern Exp $ */
  37.  
  38.  
  39. /* Some versions of bison are broken in that they use alloca() but don't
  40.  * declare it properly.  The following is the patented (just kidding!)
  41.  * #ifdef chud to fix the problem, courtesy of Francois Pinard.
  42.  */
  43. #ifdef YYBISON
  44. /* AIX requires this to be the first thing in the file.  What a piece.  */
  45. # ifdef _AIX
  46.  #pragma alloca
  47. # endif
  48. #endif
  49.  
  50. #include "flexdef.h"
  51.  
  52. /* The remainder of the alloca() cruft has to come after including flexdef.h,
  53.  * so HAVE_ALLOCA_H is (possibly) defined.
  54.  */
  55. #ifdef YYBISON
  56. # ifdef __GNUC__
  57. #  ifndef alloca
  58. #   define alloca __builtin_alloca
  59. #  endif
  60. # else
  61. #  if HAVE_ALLOCA_H
  62. #   include <alloca.h>
  63. #  else
  64. #   ifdef __hpux
  65. void *alloca ();
  66. #   else
  67. #    ifdef __TURBOC__
  68. #     include <malloc.h>
  69. #    else
  70. char *alloca ();
  71. #    endif
  72. #   endif
  73. #  endif
  74. # endif
  75. #endif
  76.  
  77. /* Bletch, ^^^^ that was ugly! */
  78.  
  79.  
  80. int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, rulelen;
  81. int trlcontxt, xcluflg, currccl, cclsorted, varlength, variable_trail_rule;
  82.  
  83. int *scon_stk;
  84. int scon_stk_ptr;
  85.  
  86. static int madeany = false;  /* whether we've made the '.' character class */
  87. int previous_continued_action;    /* whether the previous rule's action was '|' */
  88.  
  89. /* Expand a POSIX character class expression. */
  90. #define CCL_EXPR(func) \
  91.     { \
  92.     int c; \
  93.     for ( c = 0; c < csize; ++c ) \
  94.         if ( isascii(c) && func(c) ) \
  95.             ccladd( currccl, c ); \
  96.     }
  97.  
  98. /* While POSIX defines isblank(), it's not ANSI C. */
  99. #define IS_BLANK(c) ((c) == ' ' || (c) == '\t')
  100.  
  101. /* On some over-ambitious machines, such as DEC Alpha's, the default
  102.  * token type is "long" instead of "int"; this leads to problems with
  103.  * declaring yylval in flexdef.h.  But so far, all the yacc's I've seen
  104.  * wrap their definitions of YYSTYPE with "#ifndef YYSTYPE"'s, so the
  105.  * following should ensure that the default token type is "int".
  106.  */
  107. #define YYSTYPE int
  108.  
  109. %}
  110.  
  111. %%
  112. goal        :  initlex sect1 sect1end sect2 initforrule
  113.             { /* add default rule */
  114.             int def_rule;
  115.  
  116.             pat = cclinit();
  117.             cclnegate( pat );
  118.  
  119.             def_rule = mkstate( -pat );
  120.  
  121.             /* Remember the number of the default rule so we
  122.              * don't generate "can't match" warnings for it.
  123.              */
  124.             default_rule = num_rules;
  125.  
  126.             finish_rule( def_rule, false, 0, 0 );
  127.  
  128.             for ( i = 1; i <= lastsc; ++i )
  129.                 scset[i] = mkbranch( scset[i], def_rule );
  130.  
  131.             if ( spprdflt )
  132.                 add_action(
  133.                 "YY_FATAL_ERROR( \"flex scanner jammed\" )" );
  134.             else
  135.                 add_action( "ECHO" );
  136.  
  137.             add_action( ";\n\tYY_BREAK\n" );
  138.             }
  139.         ;
  140.  
  141. initlex        :
  142.             { /* initialize for processing rules */
  143.  
  144.             /* Create default DFA start condition. */
  145.             scinstal( "INITIAL", false );
  146.             }
  147.         ;
  148.  
  149. sect1        :  sect1 startconddecl namelist1
  150.         |  sect1 options
  151.         |
  152.         |  error
  153.             { synerr( "unknown error processing section 1" ); }
  154.         ;
  155.  
  156. sect1end    :  SECTEND
  157.             {
  158.             check_options();
  159.             scon_stk = allocate_integer_array( lastsc + 1 );
  160.             scon_stk_ptr = 0;
  161.             }
  162.         ;
  163.  
  164. startconddecl    :  SCDECL
  165.             { xcluflg = false; }
  166.  
  167.         |  XSCDECL
  168.             { xcluflg = true; }
  169.         ;
  170.  
  171. namelist1    :  namelist1 NAME
  172.             { scinstal( nmstr, xcluflg ); }
  173.  
  174.         |  NAME
  175.             { scinstal( nmstr, xcluflg ); }
  176.  
  177.         |  error
  178.             { synerr( "bad start condition list" ); }
  179.         ;
  180.  
  181. options        :  OPTION_OP optionlist
  182.         ;
  183.  
  184. optionlist    :  optionlist option
  185.         |
  186.         ;
  187.  
  188. option        :  OPT_OUTFILE '=' NAME
  189.             {
  190.             outfilename = copy_string( nmstr );
  191.             did_outfilename = 1;
  192.             }
  193.         |  OPT_PREFIX '=' NAME
  194.             { prefix = copy_string( nmstr ); }
  195.         |  OPT_YYCLASS '=' NAME
  196.             { yyclass = copy_string( nmstr ); }
  197.         ;
  198.  
  199. sect2        :  sect2 scon initforrule flexrule '\n'
  200.             { scon_stk_ptr = $2; }
  201.         |  sect2 scon '{' sect2 '}'
  202.             { scon_stk_ptr = $2; }
  203.         |
  204.         ;
  205.  
  206. initforrule    :
  207.             {
  208.             /* Initialize for a parse of one rule. */
  209.             trlcontxt = variable_trail_rule = varlength = false;
  210.             trailcnt = headcnt = rulelen = 0;
  211.             current_state_type = STATE_NORMAL;
  212.             previous_continued_action = continued_action;
  213.             in_rule = true;
  214.  
  215.             new_rule();
  216.             }
  217.         ;
  218.  
  219. flexrule    :  '^' rule
  220.             {
  221.             pat = $2;
  222.             finish_rule( pat, variable_trail_rule,
  223.                 headcnt, trailcnt );
  224.  
  225.             if ( scon_stk_ptr > 0 )
  226.                 {
  227.                 for ( i = 1; i <= scon_stk_ptr; ++i )
  228.                     scbol[scon_stk[i]] =
  229.                         mkbranch( scbol[scon_stk[i]],
  230.                                 pat );
  231.                 }
  232.  
  233.             else
  234.                 {
  235.                 /* Add to all non-exclusive start conditions,
  236.                  * including the default (0) start condition.
  237.                  */
  238.  
  239.                 for ( i = 1; i <= lastsc; ++i )
  240.                     if ( ! scxclu[i] )
  241.                         scbol[i] = mkbranch( scbol[i],
  242.                                     pat );
  243.                 }
  244.  
  245.             if ( ! bol_needed )
  246.                 {
  247.                 bol_needed = true;
  248.  
  249.                 if ( performance_report > 1 )
  250.                     pinpoint_message(
  251.             "'^' operator results in sub-optimal performance" );
  252.                 }
  253.             }
  254.  
  255.         |  rule
  256.             {
  257.             pat = $1;
  258.             finish_rule( pat, variable_trail_rule,
  259.                 headcnt, trailcnt );
  260.  
  261.             if ( scon_stk_ptr > 0 )
  262.                 {
  263.                 for ( i = 1; i <= scon_stk_ptr; ++i )
  264.                     scset[scon_stk[i]] =
  265.                         mkbranch( scset[scon_stk[i]],
  266.                                 pat );
  267.                 }
  268.  
  269.             else
  270.                 {
  271.                 for ( i = 1; i <= lastsc; ++i )
  272.                     if ( ! scxclu[i] )
  273.                         scset[i] =
  274.                             mkbranch( scset[i],
  275.                                 pat );
  276.                 }
  277.             }
  278.  
  279.         |  EOF_OP
  280.             {
  281.             if ( scon_stk_ptr > 0 )
  282.                 build_eof_action();
  283.     
  284.             else
  285.                 {
  286.                 /* This EOF applies to all start conditions
  287.                  * which don't already have EOF actions.
  288.                  */
  289.                 for ( i = 1; i <= lastsc; ++i )
  290.                     if ( ! sceof[i] )
  291.                         scon_stk[++scon_stk_ptr] = i;
  292.  
  293.                 if ( scon_stk_ptr == 0 )
  294.                     warn(
  295.             "all start conditions already have <<EOF>> rules" );
  296.  
  297.                 else
  298.                     build_eof_action();
  299.                 }
  300.             }
  301.  
  302.         |  error
  303.             { synerr( "unrecognized rule" ); }
  304.         ;
  305.  
  306. scon_stk_ptr    :
  307.             { $$ = scon_stk_ptr; }
  308.         ;
  309.  
  310. scon        :  '<' scon_stk_ptr namelist2 '>'
  311.             { $$ = $2; }
  312.  
  313.         |  '<' '*' '>'
  314.             {
  315.             $$ = scon_stk_ptr;
  316.  
  317.             for ( i = 1; i <= lastsc; ++i )
  318.                 {
  319.                 int j;
  320.  
  321.                 for ( j = 1; j <= scon_stk_ptr; ++j )
  322.                     if ( scon_stk[j] == i )
  323.                         break;
  324.  
  325.                 if ( j > scon_stk_ptr )
  326.                     scon_stk[++scon_stk_ptr] = i;
  327.                 }
  328.             }
  329.  
  330.         |
  331.             { $$ = scon_stk_ptr; }
  332.         ;
  333.  
  334. namelist2    :  namelist2 ',' sconname
  335.  
  336.         |  sconname
  337.  
  338.         |  error
  339.             { synerr( "bad start condition list" ); }
  340.         ;
  341.  
  342. sconname    :  NAME
  343.             {
  344.             if ( (scnum = sclookup( nmstr )) == 0 )
  345.                 format_pinpoint_message(
  346.                     "undeclared start condition %s",
  347.                     nmstr );
  348.             else
  349.                 {
  350.                 for ( i = 1; i <= scon_stk_ptr; ++i )
  351.                     if ( scon_stk[i] == scnum )
  352.                         {
  353.                         format_warn(
  354.                             "<%s> specified twice",
  355.                             scname[scnum] );
  356.                         break;
  357.                         }
  358.  
  359.                 if ( i > scon_stk_ptr )
  360.                     scon_stk[++scon_stk_ptr] = scnum;
  361.                 }
  362.             }
  363.         ;
  364.  
  365. rule        :  re2 re
  366.             {
  367.             if ( transchar[lastst[$2]] != SYM_EPSILON )
  368.                 /* Provide final transition \now/ so it
  369.                  * will be marked as a trailing context
  370.                  * state.
  371.                  */
  372.                 $2 = link_machines( $2,
  373.                         mkstate( SYM_EPSILON ) );
  374.  
  375.             mark_beginning_as_normal( $2 );
  376.             current_state_type = STATE_NORMAL;
  377.  
  378.             if ( previous_continued_action )
  379.                 {
  380.                 /* We need to treat this as variable trailing
  381.                  * context so that the backup does not happen
  382.                  * in the action but before the action switch
  383.                  * statement.  If the backup happens in the
  384.                  * action, then the rules "falling into" this
  385.                  * one's action will *also* do the backup,
  386.                  * erroneously.
  387.                  */
  388.                 if ( ! varlength || headcnt != 0 )
  389.                     warn(
  390.         "trailing context made variable due to preceding '|' action" );
  391.  
  392.                 /* Mark as variable. */
  393.                 varlength = true;
  394.                 headcnt = 0;
  395.                 }
  396.  
  397.             if ( lex_compat || (varlength && headcnt == 0) )
  398.                 { /* variable trailing context rule */
  399.                 /* Mark the first part of the rule as the
  400.                  * accepting "head" part of a trailing
  401.                  * context rule.
  402.                  *
  403.                  * By the way, we didn't do this at the
  404.                  * beginning of this production because back
  405.                  * then current_state_type was set up for a
  406.                  * trail rule, and add_accept() can create
  407.                  * a new state ...
  408.                  */
  409.                 add_accept( $1,
  410.                     num_rules | YY_TRAILING_HEAD_MASK );
  411.                 variable_trail_rule = true;
  412.                 }
  413.             
  414.             else
  415.                 trailcnt = rulelen;
  416.  
  417.             $$ = link_machines( $1, $2 );
  418.             }
  419.  
  420.         |  re2 re '$'
  421.             { synerr( "trailing context used twice" ); }
  422.  
  423.         |  re '$'
  424.             {
  425.             headcnt = 0;
  426.             trailcnt = 1;
  427.             rulelen = 1;
  428.             varlength = false;
  429.  
  430.             current_state_type = STATE_TRAILING_CONTEXT;
  431.  
  432.             if ( trlcontxt )
  433.                 {
  434.                 synerr( "trailing context used twice" );
  435.                 $$ = mkstate( SYM_EPSILON );
  436.                 }
  437.  
  438.             else if ( previous_continued_action )
  439.                 {
  440.                 /* See the comment in the rule for "re2 re"
  441.                  * above.
  442.                  */
  443.                 warn(
  444.         "trailing context made variable due to preceding '|' action" );
  445.  
  446.                 varlength = true;
  447.                 }
  448.  
  449.             if ( lex_compat || varlength )
  450.                 {
  451.                 /* Again, see the comment in the rule for
  452.                  * "re2 re" above.
  453.                  */
  454.                 add_accept( $1,
  455.                     num_rules | YY_TRAILING_HEAD_MASK );
  456.                 variable_trail_rule = true;
  457.                 }
  458.  
  459.             trlcontxt = true;
  460.  
  461.             eps = mkstate( SYM_EPSILON );
  462.             $$ = link_machines( $1,
  463.                 link_machines( eps, mkstate( '\n' ) ) );
  464.             }
  465.  
  466.         |  re
  467.             {
  468.             $$ = $1;
  469.  
  470.             if ( trlcontxt )
  471.                 {
  472.                 if ( lex_compat || (varlength && headcnt == 0) )
  473.                     /* Both head and trail are
  474.                      * variable-length.
  475.                      */
  476.                     variable_trail_rule = true;
  477.                 else
  478.                     trailcnt = rulelen;
  479.                 }
  480.             }
  481.         ;
  482.  
  483.  
  484. re        :  re '|' series
  485.             {
  486.             varlength = true;
  487.             $$ = mkor( $1, $3 );
  488.             }
  489.  
  490.         |  series
  491.             { $$ = $1; }
  492.         ;
  493.  
  494.  
  495. re2        :  re '/'
  496.             {
  497.             /* This rule is written separately so the
  498.              * reduction will occur before the trailing
  499.              * series is parsed.
  500.              */
  501.  
  502.             if ( trlcontxt )
  503.                 synerr( "trailing context used twice" );
  504.             else
  505.                 trlcontxt = true;
  506.  
  507.             if ( varlength )
  508.                 /* We hope the trailing context is
  509.                  * fixed-length.
  510.                  */
  511.                 varlength = false;
  512.             else
  513.                 headcnt = rulelen;
  514.  
  515.             rulelen = 0;
  516.  
  517.             current_state_type = STATE_TRAILING_CONTEXT;
  518.             $$ = $1;
  519.             }
  520.         ;
  521.  
  522. series        :  series singleton
  523.             {
  524.             /* This is where concatenation of adjacent patterns
  525.              * gets done.
  526.              */
  527.             $$ = link_machines( $1, $2 );
  528.             }
  529.  
  530.         |  singleton
  531.             { $$ = $1; }
  532.         ;
  533.  
  534. singleton    :  singleton '*'
  535.             {
  536.             varlength = true;
  537.  
  538.             $$ = mkclos( $1 );
  539.             }
  540.  
  541.         |  singleton '+'
  542.             {
  543.             varlength = true;
  544.             $$ = mkposcl( $1 );
  545.             }
  546.  
  547.         |  singleton '?'
  548.             {
  549.             varlength = true;
  550.             $$ = mkopt( $1 );
  551.             }
  552.  
  553.         |  singleton '{' NUMBER ',' NUMBER '}'
  554.             {
  555.             varlength = true;
  556.  
  557.             if ( $3 > $5 || $3 < 0 )
  558.                 {
  559.                 synerr( "bad iteration values" );
  560.                 $$ = $1;
  561.                 }
  562.             else
  563.                 {
  564.                 if ( $3 == 0 )
  565.                     {
  566.                     if ( $5 <= 0 )
  567.                         {
  568.                         synerr(
  569.                         "bad iteration values" );
  570.                         $$ = $1;
  571.                         }
  572.                     else
  573.                         $$ = mkopt(
  574.                             mkrep( $1, 1, $5 ) );
  575.                     }
  576.                 else
  577.                     $$ = mkrep( $1, $3, $5 );
  578.                 }
  579.             }
  580.  
  581.         |  singleton '{' NUMBER ',' '}'
  582.             {
  583.             varlength = true;
  584.  
  585.             if ( $3 <= 0 )
  586.                 {
  587.                 synerr( "iteration value must be positive" );
  588.                 $$ = $1;
  589.                 }
  590.  
  591.             else
  592.                 $$ = mkrep( $1, $3, INFINITY );
  593.             }
  594.  
  595.         |  singleton '{' NUMBER '}'
  596.             {
  597.             /* The singleton could be something like "(foo)",
  598.              * in which case we have no idea what its length
  599.              * is, so we punt here.
  600.              */
  601.             varlength = true;
  602.  
  603.             if ( $3 <= 0 )
  604.                 {
  605.                 synerr( "iteration value must be positive" );
  606.                 $$ = $1;
  607.                 }
  608.  
  609.             else
  610.                 $$ = link_machines( $1,
  611.                         copysingl( $1, $3 - 1 ) );
  612.             }
  613.  
  614.         |  '.'
  615.             {
  616.             if ( ! madeany )
  617.                 {
  618.                 /* Create the '.' character class. */
  619.                 anyccl = cclinit();
  620.                 ccladd( anyccl, '\n' );
  621.                 cclnegate( anyccl );
  622.  
  623.                 if ( useecs )
  624.                     mkeccl( ccltbl + cclmap[anyccl],
  625.                         ccllen[anyccl], nextecm,
  626.                         ecgroup, csize, csize );
  627.  
  628.                 madeany = true;
  629.                 }
  630.  
  631.             ++rulelen;
  632.  
  633.             $$ = mkstate( -anyccl );
  634.             }
  635.  
  636.         |  fullccl
  637.             {
  638.             if ( ! cclsorted )
  639.                 /* Sort characters for fast searching.  We
  640.                  * use a shell sort since this list could
  641.                  * be large.
  642.                  */
  643.                 cshell( ccltbl + cclmap[$1], ccllen[$1], true );
  644.  
  645.             if ( useecs )
  646.                 mkeccl( ccltbl + cclmap[$1], ccllen[$1],
  647.                     nextecm, ecgroup, csize, csize );
  648.  
  649.             ++rulelen;
  650.  
  651.             $$ = mkstate( -$1 );
  652.             }
  653.  
  654.         |  PREVCCL
  655.             {
  656.             ++rulelen;
  657.  
  658.             $$ = mkstate( -$1 );
  659.             }
  660.  
  661.         |  '"' string '"'
  662.             { $$ = $2; }
  663.  
  664.         |  '(' re ')'
  665.             { $$ = $2; }
  666.  
  667.         |  CHAR
  668.             {
  669.             ++rulelen;
  670.  
  671.             if ( caseins && $1 >= 'A' && $1 <= 'Z' )
  672.                 $1 = clower( $1 );
  673.  
  674.             $$ = mkstate( $1 );
  675.             }
  676.         ;
  677.  
  678. fullccl        :  '[' ccl ']'
  679.             { $$ = $2; }
  680.  
  681.         |  '[' '^' ccl ']'
  682.             {
  683.             cclnegate( $3 );
  684.             $$ = $3;
  685.             }
  686.         ;
  687.  
  688. ccl        :  ccl CHAR '-' CHAR
  689.             {
  690.             if ( caseins )
  691.                 {
  692.                 if ( $2 >= 'A' && $2 <= 'Z' )
  693.                     $2 = clower( $2 );
  694.                 if ( $4 >= 'A' && $4 <= 'Z' )
  695.                     $4 = clower( $4 );
  696.                 }
  697.  
  698.             if ( $2 > $4 )
  699.                 synerr( "negative range in character class" );
  700.  
  701.             else
  702.                 {
  703.                 for ( i = $2; i <= $4; ++i )
  704.                     ccladd( $1, i );
  705.  
  706.                 /* Keep track if this ccl is staying in
  707.                  * alphabetical order.
  708.                  */
  709.                 cclsorted = cclsorted && ($2 > lastchar);
  710.                 lastchar = $4;
  711.                 }
  712.  
  713.             $$ = $1;
  714.             }
  715.  
  716.         |  ccl CHAR
  717.             {
  718.             if ( caseins && $2 >= 'A' && $2 <= 'Z' )
  719.                 $2 = clower( $2 );
  720.  
  721.             ccladd( $1, $2 );
  722.             cclsorted = cclsorted && ($2 > lastchar);
  723.             lastchar = $2;
  724.             $$ = $1;
  725.             }
  726.  
  727.         |  ccl ccl_expr
  728.             {
  729.             /* Too hard to properly maintain cclsorted. */
  730.             cclsorted = false;
  731.             $$ = $1;
  732.             }
  733.  
  734.         |
  735.             {
  736.             cclsorted = true;
  737.             lastchar = 0;
  738.             currccl = $$ = cclinit();
  739.             }
  740.         ;
  741.  
  742. ccl_expr:       CCE_ALNUM    { CCL_EXPR(isalnum) }
  743.         |  CCE_ALPHA    { CCL_EXPR(isalpha) }
  744.         |  CCE_BLANK    { CCL_EXPR(IS_BLANK) }
  745.         |  CCE_CNTRL    { CCL_EXPR(iscntrl) }
  746.         |  CCE_DIGIT    { CCL_EXPR(isdigit) }
  747.         |  CCE_GRAPH    { CCL_EXPR(isgraph) }
  748.         |  CCE_LOWER    { CCL_EXPR(islower) }
  749.         |  CCE_PRINT    { CCL_EXPR(isprint) }
  750.         |  CCE_PUNCT    { CCL_EXPR(ispunct) }
  751.         |  CCE_SPACE    { CCL_EXPR(isspace) }
  752.         |  CCE_UPPER    {
  753.                 if ( caseins )
  754.                     CCL_EXPR(islower)
  755.                 else
  756.                     CCL_EXPR(isupper)
  757.                 }
  758.         |  CCE_XDIGIT    { CCL_EXPR(isxdigit) }
  759.         ;
  760.         
  761. string        :  string CHAR
  762.             {
  763.             if ( caseins && $2 >= 'A' && $2 <= 'Z' )
  764.                 $2 = clower( $2 );
  765.  
  766.             ++rulelen;
  767.  
  768.             $$ = link_machines( $1, mkstate( $2 ) );
  769.             }
  770.  
  771.         |
  772.             { $$ = mkstate( SYM_EPSILON ); }
  773.         ;
  774.  
  775. %%
  776.  
  777.  
  778. /* build_eof_action - build the "<<EOF>>" action for the active start
  779.  *                    conditions
  780.  */
  781.  
  782. void build_eof_action()
  783.     {
  784.     register int i;
  785.     char action_text[MAXLINE];
  786.  
  787.     for ( i = 1; i <= scon_stk_ptr; ++i )
  788.         {
  789.         if ( sceof[scon_stk[i]] )
  790.             format_pinpoint_message(
  791.                 "multiple <<EOF>> rules for start condition %s",
  792.                 scname[scon_stk[i]] );
  793.  
  794.         else
  795.             {
  796.             sceof[scon_stk[i]] = true;
  797.             sprintf( action_text, "case YY_STATE_EOF(%s):\n",
  798.                 scname[scon_stk[i]] );
  799.             add_action( action_text );
  800.             }
  801.         }
  802.  
  803.     line_directive_out( (FILE *) 0, 1 );
  804.  
  805.     /* This isn't a normal rule after all - don't count it as
  806.      * such, so we don't have any holes in the rule numbering
  807.      * (which make generating "rule can never match" warnings
  808.      * more difficult.
  809.      */
  810.     --num_rules;
  811.     ++num_eof_rules;
  812.     }
  813.  
  814.  
  815. /* format_synerr - write out formatted syntax error */
  816.  
  817. void format_synerr( msg, arg )
  818. char msg[], arg[];
  819.     {
  820.     char errmsg[MAXLINE];
  821.  
  822.     (void) sprintf( errmsg, msg, arg );
  823.     synerr( errmsg );
  824.     }
  825.  
  826.  
  827. /* synerr - report a syntax error */
  828.  
  829. void synerr( str )
  830. char str[];
  831.     {
  832.     syntaxerror = true;
  833.     pinpoint_message( str );
  834.     }
  835.  
  836.  
  837. /* format_warn - write out formatted warning */
  838.  
  839. void format_warn( msg, arg )
  840. char msg[], arg[];
  841.     {
  842.     char warn_msg[MAXLINE];
  843.  
  844.     (void) sprintf( warn_msg, msg, arg );
  845.     warn( warn_msg );
  846.     }
  847.  
  848.  
  849. /* warn - report a warning, unless -w was given */
  850.  
  851. void warn( str )
  852. char str[];
  853.     {
  854.     line_warning( str, linenum );
  855.     }
  856.  
  857. /* format_pinpoint_message - write out a message formatted with one string,
  858.  *                 pinpointing its location
  859.  */
  860.  
  861. void format_pinpoint_message( msg, arg )
  862. char msg[], arg[];
  863.     {
  864.     char errmsg[MAXLINE];
  865.  
  866.     (void) sprintf( errmsg, msg, arg );
  867.     pinpoint_message( errmsg );
  868.     }
  869.  
  870.  
  871. /* pinpoint_message - write out a message, pinpointing its location */
  872.  
  873. void pinpoint_message( str )
  874. char str[];
  875.     {
  876.     line_pinpoint( str, linenum );
  877.     }
  878.  
  879.  
  880. /* line_warning - report a warning at a given line, unless -w was given */
  881.  
  882. void line_warning( str, line )
  883. char str[];
  884. int line;
  885.     {
  886.     char warning[MAXLINE];
  887.  
  888.     if ( ! nowarn )
  889.         {
  890.         sprintf( warning, "warning, %s", str );
  891.         line_pinpoint( warning, line );
  892.         }
  893.     }
  894.  
  895.  
  896. /* line_pinpoint - write out a message, pinpointing it at the given line */
  897.  
  898. void line_pinpoint( str, line )
  899. char str[];
  900. int line;
  901.     {
  902.     fprintf( stderr, "\"%s\", line %d: %s\n", infilename, line, str );
  903.     }
  904.  
  905.  
  906. /* yyerror - eat up an error message from the parser;
  907.  *         currently, messages are ignore
  908.  */
  909.  
  910. void yyerror( msg )
  911. char msg[];
  912.     {
  913.     }
  914.