home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / FORTH / FLEX.ARC / PARSE.Y < prev    next >
Text File  |  1988-10-09  |  9KB  |  486 lines

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