home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 290_01 / parse.y < prev    next >
Text File  |  1990-05-14  |  10KB  |  519 lines

  1. /*
  2. **    file:        parse.y
  3. **    purpose:    parser for flex input
  4. **    mods:        1989.12.30 - Roberto Artigas Jr
  5. **            Corrected this file so it would generate
  6. **            the correct 'parse.c' file. It seems that
  7. **            ADDITIONAL headers were added to the
  8. **            'parse.c' file but were not ADDED here.
  9. **            No ONE person seems to have run this file
  10. **            through YACC/BISON for a while.
  11. */
  12.  
  13. /*
  14.  * Copyright (c) 1987, the University of California
  15.  * 
  16.  * The United States Government has rights in this work pursuant to
  17.  * contract no. DE-AC03-76SF00098 between the United States Department of
  18.  * Energy and the University of California.
  19.  * 
  20.  * This program may be redistributed.  Enhancements and derivative works
  21.  * may be created provided the new works, if made available to the general
  22.  * public, are made available for use by anyone.
  23.  */
  24.  
  25. %token CHAR NUMBER SECTEND SCDECL XSCDECL WHITESPACE NAME PREVCCL
  26.  
  27. %{
  28. #include "flexdef.h"
  29. #include "ecs.h"            /* RA.1989.12.30 */
  30. #include "nfa.h"            /* RA.1989.12.30 */
  31. #include "sym.h"            /* RA.1989.12.30 */
  32. #include "ccl.h"            /* RA.1989.12.30 */
  33. #include "misc.h"            /* RA.1989.12.30 */
  34.  
  35. int pat, scnum, eps,
  36.  headcnt, trailcnt, anyccl,
  37.  lastchar, i, actvp, rulelen;
  38. int trlcontxt, xcluflg,
  39.  cclsorted, varlength;
  40.  
  41. static int madeany = false;  /* whether we've made the '.' character class */
  42.  
  43. %}
  44.  
  45. %%
  46. goal            :  initlex sect1 sect1end sect2
  47.             { /* add default rule */
  48.             int def_rule;
  49.  
  50.             pat = cclinit();
  51.             cclnegate( pat );
  52.  
  53.             def_rule = mkstate( -pat );
  54.  
  55.             add_accept( def_rule, 0, 0 );
  56.  
  57.             for ( i = 1; i <= lastsc; ++i )
  58.                 scset[i] = mkbranch( scset[i], def_rule );
  59.  
  60.             fputs( "YY_DEFAULT_ACTION;\n\tYY_BREAK\n",
  61.                    temp_action_file );
  62.             }
  63.         ;
  64.  
  65. initlex         :
  66.             {
  67.             /* initialize for processing rules */
  68.  
  69.             /* create default DFA start condition */
  70.             scinstal( "INITIAL", false );
  71.             }
  72.         ;
  73.             
  74. sect1        :  sect1 startconddecl WHITESPACE namelist1 '\n'
  75.         |
  76.         |  error '\n'
  77.             { synerr( "unknown error processing section 1" ); }
  78.         ;
  79.  
  80. sect1end    :  SECTEND
  81.         ;
  82.  
  83. startconddecl   :  SCDECL
  84.             {
  85.             /* these productions are separate from the s1object
  86.              * rule because the semantics must be done before
  87.              * we parse the remainder of an s1object
  88.              */
  89.  
  90.             xcluflg = false;
  91.             }
  92.         
  93.         |  XSCDECL
  94.             { xcluflg = true; }
  95.         ;
  96.  
  97. namelist1    :  namelist1 WHITESPACE NAME
  98.             { scinstal( nmstr, xcluflg ); }
  99.  
  100.         |  NAME
  101.             { scinstal( nmstr, xcluflg ); }
  102.  
  103.         |  error
  104.                         { synerr( "bad start condition list" ); }
  105.         ;
  106.  
  107. sect2           :  sect2 initforrule flexrule '\n'
  108.         |
  109.         ;
  110.  
  111. initforrule     :
  112.             {
  113.             /* initialize for a parse of one rule */
  114.             trlcontxt = varlength = false;
  115.             trailcnt = headcnt = rulelen = 0;
  116.             }
  117.         ;
  118.  
  119. flexrule        :  scon '^' re eol 
  120.                         {
  121.             pat = link_machines( $3, $4 );
  122.             add_accept( pat, headcnt, trailcnt );
  123.  
  124.             for ( i = 1; i <= actvp; ++i )
  125.                 scbol[actvsc[i]] = mkbranch( scbol[actvsc[i]], pat );
  126.             }
  127.  
  128.         |  scon re eol 
  129.                         {
  130.             pat = link_machines( $2, $3 );
  131.             add_accept( pat, headcnt, trailcnt );
  132.  
  133.             for ( i = 1; i <= actvp; ++i )
  134.                 scset[actvsc[i]] = mkbranch( scset[actvsc[i]], pat );
  135.             }
  136.  
  137.                 |  '^' re eol 
  138.             {
  139.             pat = link_machines( $2, $3 );
  140.             add_accept( pat, headcnt, trailcnt );
  141.  
  142.             /* add to all non-exclusive start conditions,
  143.              * including the default (0) start condition
  144.              */
  145.  
  146.             for ( i = 1; i <= lastsc; ++i )
  147.                 if ( ! scxclu[i] )
  148.                 scbol[i] = mkbranch( scbol[i], pat );
  149.             }
  150.  
  151.                 |  re eol 
  152.             {
  153.             pat = link_machines( $1, $2 );
  154.             add_accept( pat, headcnt, trailcnt );
  155.  
  156.             for ( i = 1; i <= lastsc; ++i )
  157.                 if ( ! scxclu[i] )
  158.                 scset[i] = mkbranch( scset[i], pat );
  159.             }
  160.  
  161.                 |  error
  162.             { synerr( "unrecognized rule" ); }
  163.         ;
  164.  
  165. scon            :  '<' namelist2 '>'
  166.         ;
  167.  
  168. namelist2       :  namelist2 ',' NAME
  169.                         {
  170.             if ( (scnum = sclookup( nmstr )) == 0 )
  171.                 synerr( "undeclared start condition" );
  172.  
  173.             else
  174.                 actvsc[++actvp] = scnum;
  175.             }
  176.  
  177.         |  NAME
  178.             {
  179.             if ( (scnum = sclookup( nmstr )) == 0 )
  180.                 synerr( "undeclared start condition" );
  181.             else
  182.                 actvsc[actvp = 1] = scnum;
  183.             }
  184.  
  185.         |  error
  186.             { synerr( "bad start condition list" ); }
  187.         ;
  188.  
  189. eol             :  '$'
  190.                         {
  191.             if ( trlcontxt )
  192.                 {
  193.                 synerr( "trailing context used twice" );
  194.                 $$ = mkstate( SYM_EPSILON );
  195.                 }
  196.             else
  197.                 {
  198.                 trlcontxt = true;
  199.  
  200.                 if ( ! varlength )
  201.                 headcnt = rulelen;
  202.  
  203.                 ++rulelen;
  204.                 trailcnt = 1;
  205.  
  206.                 eps = mkstate( SYM_EPSILON );
  207.                 $$ = link_machines( eps, mkstate( '\n' ) );
  208.                 }
  209.             }
  210.  
  211.         |
  212.                 {
  213.                 $$ = mkstate( SYM_EPSILON );
  214.  
  215.             if ( trlcontxt )
  216.                 {
  217.                 if ( varlength && headcnt == 0 )
  218.                 /* both head and trail are variable-length */
  219.                 synerr( "illegal trailing context" );
  220.  
  221.                 else
  222.                 trailcnt = rulelen;
  223.                 }
  224.                 }
  225.         ;
  226.  
  227. re              :  re '|' series
  228.                         {
  229.             varlength = true;
  230.  
  231.             $$ = mkor( $1, $3 );
  232.             }
  233.  
  234.         |  re2 series
  235.             { $$ = link_machines( $1, $2 ); }
  236.  
  237.         |  series
  238.             { $$ = $1; }
  239.         ;
  240.  
  241.  
  242. re2        :  re '/'
  243.             {
  244.             /* this rule is separate from the others for "re" so
  245.              * that the reduction will occur before the trailing
  246.              * series is parsed
  247.              */
  248.  
  249.             if ( trlcontxt )
  250.                 synerr( "trailing context used twice" );
  251.             else
  252.                 trlcontxt = true;
  253.  
  254.             if ( varlength )
  255.                 /* the trailing context had better be fixed-length */
  256.                 varlength = false;
  257.             else
  258.                 headcnt = rulelen;
  259.  
  260.             rulelen = 0;
  261.             $$ = $1;
  262.             }
  263.         ;
  264.  
  265. series          :  series singleton
  266.                         {
  267.             /* this is where concatenation of adjacent patterns
  268.              * gets done
  269.              */
  270.             $$ = link_machines( $1, $2 );
  271.             }
  272.  
  273.         |  singleton
  274.             { $$ = $1; }
  275.         ;
  276.  
  277. singleton       :  singleton '*'
  278.                         {
  279.             varlength = true;
  280.  
  281.             $$ = mkclos( $1 );
  282.             }
  283.             
  284.         |  singleton '+'
  285.             {
  286.             varlength = true;
  287.  
  288.             $$ = mkposcl( $1 );
  289.             }
  290.  
  291.         |  singleton '?'
  292.             {
  293.             varlength = true;
  294.  
  295.             $$ = mkopt( $1 );
  296.             }
  297.  
  298.         |  singleton '{' NUMBER ',' NUMBER '}'
  299.             {
  300.             varlength = true;
  301.  
  302.             if ( $3 > $5 || $3 <= 0 )
  303.                 {
  304.                 synerr( "bad iteration values" );
  305.                 $$ = $1;
  306.                 }
  307.             else
  308.                 $$ = mkrep( $1, $3, $5 );
  309.             }
  310.                 
  311.         |  singleton '{' NUMBER ',' '}'
  312.             {
  313.             varlength = true;
  314.  
  315.             if ( $3 <= 0 )
  316.                 {
  317.                 synerr( "iteration value must be positive" );
  318.                 $$ = $1;
  319.                 }
  320.  
  321.             else
  322.                 $$ = mkrep( $1, $3, INFINITY );
  323.             }
  324.  
  325.         |  singleton '{' NUMBER '}'
  326.             {
  327.             /* the singleton could be something like "(foo)",
  328.              * in which case we have no idea what its length
  329.              * is, so we punt here.
  330.              */
  331.             varlength = true;
  332.  
  333.             if ( $3 <= 0 )
  334.                 {
  335.                 synerr( "iteration value must be positive" );
  336.                 $$ = $1;
  337.                 }
  338.  
  339.             else
  340.                 $$ = link_machines( $1, copysingl( $1, $3 - 1 ) );
  341.             }
  342.  
  343.         |  '.'
  344.             {
  345.             if ( ! madeany )
  346.                 {
  347.                 /* create the '.' character class */
  348.                 anyccl = cclinit();
  349.                 ccladd( anyccl, '\n' );
  350.                 cclnegate( anyccl );
  351.  
  352.                 if ( useecs )
  353.                 mkeccl( ccltbl + cclmap[anyccl],
  354.                     ccllen[anyccl], nextecm,
  355.                     ecgroup, CSIZE );
  356.                 
  357.                 madeany = true;
  358.                 }
  359.  
  360.             ++rulelen;
  361.  
  362.             $$ = mkstate( -anyccl );
  363.             }
  364.  
  365.         |  fullccl
  366.             {
  367.             if ( ! cclsorted )
  368.                 /* sort characters for fast searching.  We use a
  369.                  * shell sort since this list could be large.
  370.                  */
  371.                 cshell( ccltbl + cclmap[$1], ccllen[$1] );
  372.  
  373.             if ( useecs )
  374.                 mkeccl( ccltbl + cclmap[$1], ccllen[$1],
  375.                     nextecm, ecgroup, CSIZE );
  376.                      
  377.             ++rulelen;
  378.  
  379.             $$ = mkstate( -$1 );
  380.             }
  381.  
  382.         |  PREVCCL
  383.             {
  384.             ++rulelen;
  385.  
  386.             $$ = mkstate( -$1 );
  387.             }
  388.  
  389.         |  '"' string '"'
  390.             { $$ = $2; }
  391.  
  392.         |  '(' re ')'
  393.             { $$ = $2; }
  394.  
  395.         |  CHAR
  396.             {
  397.             ++rulelen;
  398.  
  399.             if ( $1 == '\0' )
  400.                 synerr( "null in rule" );
  401.  
  402.             if ( caseins && $1 >= 'A' && $1 <= 'Z' )
  403.                 $1 = clower( $1 );
  404.  
  405.             $$ = mkstate( $1 );
  406.             }
  407.         ;
  408.  
  409. fullccl        :  '[' ccl ']'
  410.             { $$ = $2; }
  411.  
  412.         |  '[' '^' ccl ']'
  413.             {
  414.             /* *Sigh* - to be compatible Unix lex, negated ccls
  415.              * match newlines
  416.              */
  417. #ifdef NOTDEF
  418.             ccladd( $3, '\n' ); /* negated ccls don't match '\n' */
  419.             cclsorted = false; /* because we added the newline */
  420. #endif
  421.             cclnegate( $3 );
  422.             $$ = $3;
  423.             }
  424.         ;
  425.  
  426. ccl             :  ccl CHAR '-' CHAR
  427.                         {
  428.             if ( $2 > $4 )
  429.                 synerr( "negative range in character class" );
  430.  
  431.             else
  432.                 {
  433.                 if ( caseins )
  434.                 {
  435.                 if ( $2 >= 'A' && $2 <= 'Z' )
  436.                     $2 = clower( $2 );
  437.                 if ( $4 >= 'A' && $4 <= 'Z' )
  438.                     $4 = clower( $4 );
  439.                 }
  440.  
  441.                 for ( i = $2; i <= $4; ++i )
  442.                     ccladd( $1, i );
  443.  
  444.                 /* keep track if this ccl is staying in alphabetical
  445.                  * order
  446.                  */
  447.                 cclsorted = cclsorted && ($2 > lastchar);
  448.                 lastchar = $4;
  449.                 }
  450.             
  451.             $$ = $1;
  452.             }
  453.  
  454.         |  ccl CHAR
  455.                 {
  456.             if ( caseins )
  457.                 if ( $2 >= 'A' && $2 <= 'Z' )
  458.                 $2 = clower( $2 );
  459.  
  460.             ccladd( $1, $2 );
  461.             cclsorted = cclsorted && ($2 > lastchar);
  462.             lastchar = $2;
  463.             $$ = $1;
  464.             }
  465.  
  466.         |
  467.             {
  468.             cclsorted = true;
  469.             lastchar = 0;
  470.             $$ = cclinit();
  471.             }
  472.         ;
  473.  
  474. string        :  string CHAR
  475.                         {
  476.             if ( caseins )
  477.                 if ( $2 >= 'A' && $2 <= 'Z' )
  478.                 $2 = clower( $2 );
  479.  
  480.             ++rulelen;
  481.  
  482.             $$ = link_machines( $1, mkstate( $2 ) );
  483.             }
  484.  
  485.         |
  486.             { $$ = mkstate( SYM_EPSILON ); }
  487.         ;
  488.  
  489. %%
  490. /*
  491. **    function:    synerr
  492. **    purpose:    Report a syntax error
  493. **    mods:        1989.12.30 - Roberto Artigas Jr
  494. **            Changed return type to void
  495. */
  496. void
  497. synerr( str )
  498. char str[];                /* Error message */
  499. {
  500.   syntaxerror = true;            /* We have an error! */
  501.   fprintf(stderr,            /* Error file */
  502.     "Syntax error at line %d: %s\n",    /* Message text */
  503.     linenum,                /* Line number */
  504.     str);                /* Error message */
  505. };                    /* synerr */
  506.  
  507.  
  508. /*
  509. **    function:    yyerror
  510. **    purpose:    Eat up an error message from the parser
  511. **    mods:        1989.12.30 - Roberto Artigas Jr
  512. **            Changed return type to void
  513. */
  514. void
  515. yyerror( msg )
  516. char msg[];                /* Error message */
  517. {
  518. };                    /* yyerror */
  519.