home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / GNU / FLE236AS.ZIP / PARSE.Y < prev    next >
Encoding:
Text File  |  1992-02-22  |  15.0 KB  |  708 lines

  1.  
  2. /* parse.y - parser for flex input */
  3.  
  4. %token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL EOF_OP
  5.  
  6. %{
  7. /*-
  8.  * Copyright (c) 1990 The Regents of the University of California.
  9.  * All rights reserved.
  10.  *
  11.  * This code is derived from software contributed to Berkeley by
  12.  * Vern Paxson.
  13.  * 
  14.  * The United States Government has rights in this work pursuant
  15.  * to contract no. DE-AC03-76SF00098 between the United States
  16.  * Department of Energy and the University of California.
  17.  *
  18.  * Redistribution and use in source and binary forms are permitted provided
  19.  * that: (1) source distributions retain this entire copyright notice and
  20.  * comment, and (2) distributions including binaries display the following
  21.  * acknowledgement:  ``This product includes software developed by the
  22.  * University of California, Berkeley and its contributors'' in the
  23.  * documentation or other materials provided with the distribution and in
  24.  * all advertising materials mentioning features or use of this software.
  25.  * Neither the name of the University nor the names of its contributors may
  26.  * be used to endorse or promote products derived from this software without
  27.  * specific prior written permission.
  28.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  29.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  30.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  31.  */
  32.  
  33. #ifndef lint
  34. static char rcsid[] =
  35.     "@(#) $Header: /usr/fsys/odin/a/vern/flex/RCS/parse.y,v 2.7 90/06/27 23:48:31 vern Exp $ (LBL)";
  36. #endif
  37.  
  38. #include "flexdef.h"
  39.  
  40. int pat, scnum, eps, headcnt, trailcnt, anyccl, lastchar, i, actvp, rulelen;
  41. int trlcontxt, xcluflg, cclsorted, varlength, variable_trail_rule;
  42. Char clower();
  43.  
  44. static int madeany = false;  /* whether we've made the '.' character class */
  45. int previous_continued_action;    /* whether the previous rule's action was '|' */
  46.  
  47. void yyerror PROTO((char *));
  48. void build_eof_action PROTO((void));
  49. #ifdef MSDOS                /* bison uses alloca () */
  50. #include <malloc.h>
  51. #endif
  52. %}
  53.  
  54. %%
  55. goal            :  initlex sect1 sect1end sect2 initforrule
  56.             { /* add default rule */
  57.             int def_rule;
  58.  
  59.             pat = cclinit();
  60.             cclnegate( pat );
  61.  
  62.             def_rule = mkstate( -pat );
  63.  
  64.             finish_rule( def_rule, false, 0, 0 );
  65.  
  66.             for ( i = 1; i <= lastsc; ++i )
  67.                 scset[i] = mkbranch( scset[i], def_rule );
  68.  
  69.             if ( spprdflt )
  70.                 fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )",
  71.                    temp_action_file );
  72.             else
  73.                 fputs( "ECHO", temp_action_file );
  74.  
  75.             fputs( ";\n\tYY_BREAK\n", temp_action_file );
  76.             }
  77.         ;
  78.  
  79. initlex         :
  80.             {
  81.             /* initialize for processing rules */
  82.  
  83.             /* create default DFA start condition */
  84.             scinstal( "INITIAL", false );
  85.             }
  86.         ;
  87.  
  88. sect1        :  sect1 startconddecl WHITESPACE namelist1 '\n'
  89.         |
  90.         |  error '\n'
  91.             { synerr( "unknown error processing section 1" ); }
  92.         ;
  93.  
  94. sect1end    :  SECTEND
  95.         ;
  96.  
  97. startconddecl   :  SCDECL
  98.             {
  99.             /* these productions are separate from the s1object
  100.              * rule because the semantics must be done before
  101.              * we parse the remainder of an s1object
  102.              */
  103.  
  104.             xcluflg = false;
  105.             }
  106.  
  107.         |  XSCDECL
  108.             { xcluflg = true; }
  109.         ;
  110.  
  111. namelist1    :  namelist1 WHITESPACE NAME
  112.             { scinstal( nmstr, xcluflg ); }
  113.  
  114.         |  NAME
  115.             { scinstal( nmstr, xcluflg ); }
  116.  
  117.         |  error
  118.                         { synerr( "bad start condition list" ); }
  119.         ;
  120.  
  121. sect2           :  sect2 initforrule flexrule '\n'
  122.         |
  123.         ;
  124.  
  125. initforrule     :
  126.             {
  127.             /* initialize for a parse of one rule */
  128.             trlcontxt = variable_trail_rule = varlength = false;
  129.             trailcnt = headcnt = rulelen = 0;
  130.             current_state_type = STATE_NORMAL;
  131.             previous_continued_action = continued_action;
  132.             new_rule();
  133.             }
  134.         ;
  135.  
  136. flexrule        :  scon '^' rule
  137.                         {
  138.             pat = $3;
  139.             finish_rule( pat, variable_trail_rule,
  140.                      headcnt, trailcnt );
  141.  
  142.             for ( i = 1; i <= actvp; ++i )
  143.                 scbol[actvsc[i]] =
  144.                 mkbranch( scbol[actvsc[i]], pat );
  145.  
  146.             if ( ! bol_needed )
  147.                 {
  148.                 bol_needed = true;
  149.  
  150.                 if ( performance_report )
  151.                 pinpoint_message( 
  152.                 "'^' operator results in sub-optimal performance" );
  153.                 }
  154.             }
  155.  
  156.         |  scon rule
  157.                         {
  158.             pat = $2;
  159.             finish_rule( pat, variable_trail_rule,
  160.                      headcnt, trailcnt );
  161.  
  162.             for ( i = 1; i <= actvp; ++i )
  163.                 scset[actvsc[i]] =
  164.                 mkbranch( scset[actvsc[i]], pat );
  165.             }
  166.  
  167.                 |  '^' rule
  168.             {
  169.             pat = $2;
  170.             finish_rule( pat, variable_trail_rule,
  171.                      headcnt, trailcnt );
  172.  
  173.             /* add to all non-exclusive start conditions,
  174.              * including the default (0) start condition
  175.              */
  176.  
  177.             for ( i = 1; i <= lastsc; ++i )
  178.                 if ( ! scxclu[i] )
  179.                 scbol[i] = mkbranch( scbol[i], pat );
  180.  
  181.             if ( ! bol_needed )
  182.                 {
  183.                 bol_needed = true;
  184.  
  185.                 if ( performance_report )
  186.                 pinpoint_message(
  187.                 "'^' operator results in sub-optimal performance" );
  188.                 }
  189.             }
  190.  
  191.                 |  rule
  192.             {
  193.             pat = $1;
  194.             finish_rule( pat, variable_trail_rule,
  195.                      headcnt, trailcnt );
  196.  
  197.             for ( i = 1; i <= lastsc; ++i )
  198.                 if ( ! scxclu[i] )
  199.                 scset[i] = mkbranch( scset[i], pat );
  200.             }
  201.  
  202.                 |  scon EOF_OP
  203.             { build_eof_action(); }
  204.  
  205.                 |  EOF_OP
  206.             {
  207.             /* this EOF applies to all start conditions
  208.              * which don't already have EOF actions
  209.              */
  210.             actvp = 0;
  211.  
  212.             for ( i = 1; i <= lastsc; ++i )
  213.                 if ( ! sceof[i] )
  214.                 actvsc[++actvp] = i;
  215.  
  216.             if ( actvp == 0 )
  217.                 pinpoint_message(
  218.         "warning - all start conditions already have <<EOF>> rules" );
  219.  
  220.             else
  221.                 build_eof_action();
  222.             }
  223.  
  224.                 |  error
  225.             { synerr( "unrecognized rule" ); }
  226.         ;
  227.  
  228. scon            :  '<' namelist2 '>'
  229.         ;
  230.  
  231. namelist2       :  namelist2 ',' NAME
  232.                         {
  233.             if ( (scnum = sclookup( nmstr )) == 0 )
  234.                 format_pinpoint_message(
  235.                 "undeclared start condition %s", nmstr );
  236.  
  237.             else
  238.                 actvsc[++actvp] = scnum;
  239.             }
  240.  
  241.         |  NAME
  242.             {
  243.             if ( (scnum = sclookup( nmstr )) == 0 )
  244.                 format_pinpoint_message(
  245.                 "undeclared start condition %s", nmstr );
  246.             else
  247.                 actvsc[actvp = 1] = scnum;
  248.             }
  249.  
  250.         |  error
  251.             { synerr( "bad start condition list" ); }
  252.         ;
  253.  
  254. rule            :  re2 re
  255.             {
  256.             if ( transchar[lastst[$2]] != SYM_EPSILON )
  257.                 /* provide final transition \now/ so it
  258.                  * will be marked as a trailing context
  259.                  * state
  260.                  */
  261.                 $2 = link_machines( $2, mkstate( SYM_EPSILON ) );
  262.  
  263.             mark_beginning_as_normal( $2 );
  264.             current_state_type = STATE_NORMAL;
  265.  
  266.             if ( previous_continued_action )
  267.                 {
  268.                 /* we need to treat this as variable trailing
  269.                  * context so that the backup does not happen
  270.                  * in the action but before the action switch
  271.                  * statement.  If the backup happens in the
  272.                  * action, then the rules "falling into" this
  273.                  * one's action will *also* do the backup,
  274.                  * erroneously.
  275.                  */
  276.                 if ( ! varlength || headcnt != 0 )
  277.                 {
  278.                 fprintf( stderr,
  279.     "%s: warning - trailing context rule at line %d made variable because\n",
  280.                      program_name, linenum );
  281.                 fprintf( stderr,
  282.                      "      of preceding '|' action\n" );
  283.                 }
  284.  
  285.                 /* mark as variable */
  286.                 varlength = true;
  287.                 headcnt = 0;
  288.                 }
  289.  
  290.             if ( varlength && headcnt == 0 )
  291.                 { /* variable trailing context rule */
  292.                 /* mark the first part of the rule as the accepting
  293.                  * "head" part of a trailing context rule
  294.                  */
  295.                 /* by the way, we didn't do this at the beginning
  296.                  * of this production because back then
  297.                  * current_state_type was set up for a trail
  298.                  * rule, and add_accept() can create a new
  299.                  * state ...
  300.                  */
  301.                 add_accept( $1, num_rules | YY_TRAILING_HEAD_MASK );
  302.                 variable_trail_rule = true;
  303.                 }
  304.             
  305.             else
  306.                 trailcnt = rulelen;
  307.  
  308.             $$ = link_machines( $1, $2 );
  309.             }
  310.  
  311.         |  re2 re '$'
  312.             { synerr( "trailing context used twice" ); }
  313.  
  314.         |  re '$'
  315.                         {
  316.             if ( trlcontxt )
  317.                 {
  318.                 synerr( "trailing context used twice" );
  319.                 $$ = mkstate( SYM_EPSILON );
  320.                 }
  321.  
  322.             else if ( previous_continued_action )
  323.                 {
  324.                 /* see the comment in the rule for "re2 re"
  325.                  * above
  326.                  */
  327.                 if ( ! varlength || headcnt != 0 )
  328.                 {
  329.                 fprintf( stderr,
  330.     "%s: warning - trailing context rule at line %d made variable because\n",
  331.                      program_name, linenum );
  332.                 fprintf( stderr,
  333.                      "      of preceding '|' action\n" );
  334.                 }
  335.  
  336.                 /* mark as variable */
  337.                 varlength = true;
  338.                 headcnt = 0;
  339.                 }
  340.  
  341.             trlcontxt = true;
  342.  
  343.             if ( ! varlength )
  344.                 headcnt = rulelen;
  345.  
  346.             ++rulelen;
  347.             trailcnt = 1;
  348.  
  349.             eps = mkstate( SYM_EPSILON );
  350.             $$ = link_machines( $1,
  351.                  link_machines( eps, mkstate( '\n' ) ) );
  352.             }
  353.  
  354.         |  re
  355.             {
  356.                 $$ = $1;
  357.  
  358.             if ( trlcontxt )
  359.                 {
  360.                 if ( varlength && headcnt == 0 )
  361.                 /* both head and trail are variable-length */
  362.                 variable_trail_rule = true;
  363.                 else
  364.                 trailcnt = rulelen;
  365.                 }
  366.                 }
  367.         ;
  368.  
  369.  
  370. re              :  re '|' series
  371.                         {
  372.             varlength = true;
  373.             $$ = mkor( $1, $3 );
  374.             }
  375.  
  376.         |  series
  377.             { $$ = $1; }
  378.         ;
  379.  
  380.  
  381. re2        :  re '/'
  382.             {
  383.             /* this rule is written separately so
  384.              * the reduction will occur before the trailing
  385.              * series is parsed
  386.              */
  387.  
  388.             if ( trlcontxt )
  389.                 synerr( "trailing context used twice" );
  390.             else
  391.                 trlcontxt = true;
  392.  
  393.             if ( varlength )
  394.                 /* we hope the trailing context is fixed-length */
  395.                 varlength = false;
  396.             else
  397.                 headcnt = rulelen;
  398.  
  399.             rulelen = 0;
  400.  
  401.             current_state_type = STATE_TRAILING_CONTEXT;
  402.             $$ = $1;
  403.             }
  404.         ;
  405.  
  406. series          :  series singleton
  407.                         {
  408.             /* this is where concatenation of adjacent patterns
  409.              * gets done
  410.              */
  411.             $$ = link_machines( $1, $2 );
  412.             }
  413.  
  414.         |  singleton
  415.             { $$ = $1; }
  416.         ;
  417.  
  418. singleton       :  singleton '*'
  419.                         {
  420.             varlength = true;
  421.  
  422.             $$ = mkclos( $1 );
  423.             }
  424.  
  425.         |  singleton '+'
  426.             {
  427.             varlength = true;
  428.  
  429.             $$ = mkposcl( $1 );
  430.             }
  431.  
  432.         |  singleton '?'
  433.             {
  434.             varlength = true;
  435.  
  436.             $$ = mkopt( $1 );
  437.             }
  438.  
  439.         |  singleton '{' NUMBER ',' NUMBER '}'
  440.             {
  441.             varlength = true;
  442.  
  443.             if ( $3 > $5 || $3 < 0 )
  444.                 {
  445.                 synerr( "bad iteration values" );
  446.                 $$ = $1;
  447.                 }
  448.             else
  449.                 {
  450.                 if ( $3 == 0 )
  451.                 $$ = mkopt( mkrep( $1, $3, $5 ) );
  452.                 else
  453.                 $$ = mkrep( $1, $3, $5 );
  454.                 }
  455.             }
  456.  
  457.         |  singleton '{' NUMBER ',' '}'
  458.             {
  459.             varlength = true;
  460.  
  461.             if ( $3 <= 0 )
  462.                 {
  463.                 synerr( "iteration value must be positive" );
  464.                 $$ = $1;
  465.                 }
  466.  
  467.             else
  468.                 $$ = mkrep( $1, $3, INFINITY );
  469.             }
  470.  
  471.         |  singleton '{' NUMBER '}'
  472.             {
  473.             /* the singleton could be something like "(foo)",
  474.              * in which case we have no idea what its length
  475.              * is, so we punt here.
  476.              */
  477.             varlength = true;
  478.  
  479.             if ( $3 <= 0 )
  480.                 {
  481.                 synerr( "iteration value must be positive" );
  482.                 $$ = $1;
  483.                 }
  484.  
  485.             else
  486.                 $$ = link_machines( $1, copysingl( $1, $3 - 1 ) );
  487.             }
  488.  
  489.         |  '.'
  490.             {
  491.             if ( ! madeany )
  492.                 {
  493.                 /* create the '.' character class */
  494.                 anyccl = cclinit();
  495.                 ccladd( anyccl, '\n' );
  496.                 cclnegate( anyccl );
  497.  
  498.                 if ( useecs )
  499.                 mkeccl( ccltbl + cclmap[anyccl],
  500.                     ccllen[anyccl], nextecm,
  501.                     ecgroup, csize, csize );
  502.  
  503.                 madeany = true;
  504.                 }
  505.  
  506.             ++rulelen;
  507.  
  508.             $$ = mkstate( -anyccl );
  509.             }
  510.  
  511.         |  fullccl
  512.             {
  513.             if ( ! cclsorted )
  514.                 /* sort characters for fast searching.  We use a
  515.                  * shell sort since this list could be large.
  516.                  */
  517.                 cshell( ccltbl + cclmap[$1], ccllen[$1], true );
  518.  
  519.             if ( useecs )
  520.                 mkeccl( ccltbl + cclmap[$1], ccllen[$1],
  521.                     nextecm, ecgroup, csize, csize );
  522.  
  523.             ++rulelen;
  524.  
  525.             $$ = mkstate( -$1 );
  526.             }
  527.  
  528.         |  PREVCCL
  529.             {
  530.             ++rulelen;
  531.  
  532.             $$ = mkstate( -$1 );
  533.             }
  534.  
  535.         |  '"' string '"'
  536.             { $$ = $2; }
  537.  
  538.         |  '(' re ')'
  539.             { $$ = $2; }
  540.  
  541.         |  CHAR
  542.             {
  543.             ++rulelen;
  544.  
  545.             if ( caseins && $1 >= 'A' && $1 <= 'Z' )
  546.                 $1 = clower( $1 );
  547.  
  548.             $$ = mkstate( $1 );
  549.             }
  550.         ;
  551.  
  552. fullccl        :  '[' ccl ']'
  553.             { $$ = $2; }
  554.  
  555.         |  '[' '^' ccl ']'
  556.             {
  557.             /* *Sigh* - to be compatible Unix lex, negated ccls
  558.              * match newlines
  559.              */
  560. #ifdef NOTDEF
  561.             ccladd( $3, '\n' ); /* negated ccls don't match '\n' */
  562.             cclsorted = false; /* because we added the newline */
  563. #endif
  564.             cclnegate( $3 );
  565.             $$ = $3;
  566.             }
  567.         ;
  568.  
  569. ccl             :  ccl CHAR '-' CHAR
  570.                         {
  571.             if ( $2 > $4 )
  572.                 synerr( "negative range in character class" );
  573.  
  574.             else
  575.                 {
  576.                 if ( caseins )
  577.                 {
  578.                 if ( $2 >= 'A' && $2 <= 'Z' )
  579.                     $2 = clower( $2 );
  580.                 if ( $4 >= 'A' && $4 <= 'Z' )
  581.                     $4 = clower( $4 );
  582.                 }
  583.  
  584.                 for ( i = $2; i <= $4; ++i )
  585.                     ccladd( $1, i );
  586.  
  587.                 /* keep track if this ccl is staying in alphabetical
  588.                  * order
  589.                  */
  590.                 cclsorted = cclsorted && ($2 > lastchar);
  591.                 lastchar = $4;
  592.                 }
  593.  
  594.             $$ = $1;
  595.             }
  596.  
  597.         |  ccl CHAR
  598.                 {
  599.             if ( caseins )
  600.                 if ( $2 >= 'A' && $2 <= 'Z' )
  601.                 $2 = clower( $2 );
  602.  
  603.             ccladd( $1, $2 );
  604.             cclsorted = cclsorted && ($2 > lastchar);
  605.             lastchar = $2;
  606.             $$ = $1;
  607.             }
  608.  
  609.         |
  610.             {
  611.             cclsorted = true;
  612.             lastchar = 0;
  613.             $$ = cclinit();
  614.             }
  615.         ;
  616.  
  617. string        :  string CHAR
  618.                         {
  619.             if ( caseins )
  620.                 if ( $2 >= 'A' && $2 <= 'Z' )
  621.                 $2 = clower( $2 );
  622.  
  623.             ++rulelen;
  624.  
  625.             $$ = link_machines( $1, mkstate( $2 ) );
  626.             }
  627.  
  628.         |
  629.             { $$ = mkstate( SYM_EPSILON ); }
  630.         ;
  631.  
  632. %%
  633.  
  634.  
  635. /* build_eof_action - build the "<<EOF>>" action for the active start
  636.  *                    conditions
  637.  */
  638.  
  639. void build_eof_action()
  640.  
  641.     {
  642.     register int i;
  643.  
  644.     for ( i = 1; i <= actvp; ++i )
  645.     {
  646.     if ( sceof[actvsc[i]] )
  647.         format_pinpoint_message(
  648.         "multiple <<EOF>> rules for start condition %s",
  649.             scname[actvsc[i]] );
  650.  
  651.     else
  652.         {
  653.         sceof[actvsc[i]] = true;
  654.         fprintf( temp_action_file, "case YY_STATE_EOF(%s):\n",
  655.              scname[actvsc[i]] );
  656.         }
  657.     }
  658.  
  659.     line_directive_out( temp_action_file );
  660.     }
  661.  
  662.  
  663. /* synerr - report a syntax error */
  664.  
  665. void synerr( str )
  666. char str[];
  667.  
  668.     {
  669.     syntaxerror = true;
  670.     pinpoint_message( str );
  671.     }
  672.  
  673.  
  674. /* format_pinpoint_message - write out a message formatted with one string,
  675.  *                 pinpointing its location
  676.  */
  677.  
  678. void format_pinpoint_message( msg, arg )
  679. char msg[], arg[];
  680.  
  681.     {
  682.     char errmsg[MAXLINE];
  683.  
  684.     (void) sprintf( errmsg, msg, arg );
  685.     pinpoint_message( errmsg );
  686.     }
  687.  
  688.  
  689. /* pinpoint_message - write out a message, pinpointing its location */
  690.  
  691. void pinpoint_message( str )
  692. char str[];
  693.  
  694.     {
  695.     fprintf( stderr, "\"%s\", line %d: %s\n", infilename, linenum, str );
  696.     }
  697.  
  698.  
  699. /* yyerror - eat up an error message from the parser;
  700.  *         currently, messages are ignore
  701.  */
  702.  
  703. void yyerror( msg )
  704. char msg[];
  705.  
  706.     {
  707.     }
  708.