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

  1. /* scan.l - scanner 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. %{
  16. #include "flexdef.h"
  17. #include "parse.h"
  18.  
  19. #define ACTION_ECHO fprintf( temp_action_file, "%s", yytext )
  20. #define MARK_END_OF_PROLOG fprintf( temp_action_file, "%%%% end of prolog\n" );
  21.  
  22. #undef YY_DECL
  23. #define YY_DECL \
  24.     int flexscan()
  25.  
  26. #define RETURNCHAR \
  27.     yylval = yytext[0]; \
  28.     return ( CHAR );
  29.  
  30. #define RETURNNAME \
  31.     (void) strcpy( nmstr, yytext ); \
  32.     return ( NAME );
  33.  
  34. #define PUT_BACK_STRING(str, start) \
  35.     for ( i = strlen( str ) - 1; i >= start; --i ) \
  36.         unput(str[i])
  37. %}
  38.  
  39. %x SECT2 SECT2PROLOG SECT3 CODEBLOCK PICKUPDEF SC CARETISBOL NUM QUOTE
  40. %x FIRSTCCL CCL ACTION RECOVER BRACEERROR C_COMMENT C_COMMENT_2 ACTION_COMMENT
  41. %x ACTION_STRING PERCENT_BRACE_ACTION
  42.  
  43. WS        [ \t]+
  44.  
  45. OPTWS        [ \t]*
  46.  
  47. NAME        [a-z_][a-z_0-9]*
  48.  
  49. SCNAME        {NAME}
  50.  
  51. ESCSEQ        \\([^^\n]|"^".|0[0-9]{1,3})
  52.  
  53. %%
  54.     static int bracelevel, didadef;
  55.     int i, cclval;
  56.     char nmdef[MAXLINE], myesc();
  57.  
  58. ^{WS}.*\n        ++linenum; ECHO; /* indented code */
  59. ^#.*\n            ++linenum; ECHO; /* treat as a comment */
  60. ^"/*"            ECHO; BEGIN(C_COMMENT);
  61. ^"%s"(tart)?        return ( SCDECL );
  62. ^"%x"            return ( XSCDECL );
  63. ^"%{".*\n        ++linenum; line_directive_out( stdout ); BEGIN(CODEBLOCK);
  64. {WS}            return ( WHITESPACE );
  65.  
  66. ^"%%".*            {
  67.             sectnum = 2;
  68.             line_directive_out( stdout );
  69.             BEGIN(SECT2PROLOG);
  70.             return ( SECTEND );
  71.             }
  72.  
  73. ^"%"[^sx{%].*\n        {
  74.             fprintf( stderr,
  75.                  "old-style lex command at line %d ignored:\n\t%s",
  76.                  linenum, yytext );
  77.             ++linenum;
  78.             }
  79.  
  80. ^{NAME}            {
  81.             (void) strcpy( nmstr, yytext );
  82.             didadef = false;
  83.             BEGIN(PICKUPDEF);
  84.             }
  85.  
  86. {SCNAME}        RETURNNAME;
  87. ^{OPTWS}\n        ++linenum; /* allows blank lines in section 1 */
  88. \n            ++linenum; return ( '\n' );
  89. .            synerr( "illegal character" ); BEGIN(RECOVER);
  90.  
  91.  
  92. <C_COMMENT>"*/"        ECHO; BEGIN(0);
  93. <C_COMMENT>"*/".*\n    ++linenum; ECHO; BEGIN(0);
  94. <C_COMMENT>[^*\n]+    ECHO;
  95. <C_COMMENT>"*"        ECHO;
  96. <C_COMMENT>\n        ++linenum; ECHO;
  97.  
  98. <CODEBLOCK>^"%}".*\n    ++linenum; BEGIN(0);
  99. <CODEBLOCK>.*\n        ++linenum; ECHO;
  100.  
  101. <PICKUPDEF>{WS}        /* separates name and definition */
  102.  
  103. <PICKUPDEF>[^ \t\n].*    {
  104.             (void) strcpy( nmdef, yytext );
  105.  
  106.             for ( i = strlen( nmdef ) - 1;
  107.                   i >= 0 &&
  108.                   nmdef[i] == ' ' || nmdef[i] == '\t';
  109.                   --i )
  110.                 ;
  111.  
  112.             nmdef[i + 1] = '\0';
  113.  
  114.                         ndinstal( nmstr, nmdef );
  115.             didadef = true;
  116.             }
  117.  
  118. <PICKUPDEF>\n        {
  119.             if ( ! didadef )
  120.                 synerr( "incomplete name definition" );
  121.             BEGIN(0);
  122.             ++linenum;
  123.             }
  124.  
  125. <RECOVER>.*\n        ++linenum; BEGIN(0); RETURNNAME;
  126.  
  127.  
  128. <SECT2PROLOG>.*\n/[^ \t\n]    {
  129.             ++linenum;
  130.             ACTION_ECHO;
  131.             MARK_END_OF_PROLOG;
  132.             BEGIN(SECT2);
  133.             }
  134.  
  135. <SECT2PROLOG>.*\n    ++linenum; ACTION_ECHO;
  136.  
  137. <SECT2>^{OPTWS}\n    ++linenum; /* allow blank lines in section 2 */
  138.  
  139.     /* this horrible mess of a rule matches indented lines which
  140.      * do not contain "/*".  We need to make the distinction because
  141.      * otherwise this rule will be taken instead of the rule which
  142.      * matches the beginning of comments like this one
  143.      */
  144. <SECT2>^{WS}([^/\n]|"/"[^*\n])*("/"?)\n    {
  145.             synerr( "indented code found outside of action" );
  146.             ++linenum;
  147.             }
  148.  
  149. <SECT2>"<"        BEGIN(SC); return ( '<' );
  150. <SECT2>^"^"        return ( '^' );
  151. <SECT2>\"        BEGIN(QUOTE); return ( '"' );
  152. <SECT2>"{"/[0-9]        BEGIN(NUM); return ( '{' );
  153. <SECT2>"{"[^0-9\n][^}\n]*    BEGIN(BRACEERROR);
  154. <SECT2>"$"/[ \t\n]    return ( '$' );
  155.  
  156. <SECT2>{WS}"%{"        {
  157.             bracelevel = 1;
  158.             BEGIN(PERCENT_BRACE_ACTION);
  159.             return ( '\n' );
  160.             }
  161. <SECT2>{WS}"|".*\n    ++linenum; return ( '\n' );
  162.  
  163. <SECT2>^{OPTWS}"/*"    ACTION_ECHO; BEGIN(C_COMMENT_2);
  164.  
  165. <SECT2>{WS}        { /* needs to be separate from following rule due to
  166.                * bug with trailing context
  167.                */
  168.             bracelevel = 0;
  169.             BEGIN(ACTION);
  170.             return ( '\n' );
  171.             }
  172.  
  173. <SECT2>{OPTWS}/\n    {
  174.             bracelevel = 0;
  175.             BEGIN(ACTION);
  176.             return ( '\n' );
  177.             }
  178.  
  179. <SECT2>^{OPTWS}\n    ++linenum; return ( '\n' );
  180.  
  181. <SECT2>^"%%".*        {
  182.             /* guarantee that the SECT3 rule will have something
  183.              * to match
  184.              */
  185.             yyless(1);
  186.             sectnum = 3;
  187.             BEGIN(SECT3);
  188.             return ( EOF ); /* to stop the parser */
  189.             }
  190.  
  191. <SECT2>"["([^\\\]\n]|{ESCSEQ})+"]"    {
  192.             (void) strcpy( nmstr, yytext );
  193.  
  194.             /* check to see if we've already encountered this ccl */
  195.             if ( (cclval = ccllookup( nmstr )) )
  196.                 {
  197.                 yylval = cclval;
  198.                 ++cclreuse;
  199.                 return ( PREVCCL );
  200.                 }
  201.             else
  202.                 {
  203.                 /* we fudge a bit.  We know that this ccl will
  204.                  * soon be numbered as lastccl + 1 by cclinit
  205.                  */
  206.                 cclinstal( nmstr, lastccl + 1 );
  207.  
  208.                 /* push back everything but the leading bracket
  209.                  * so the ccl can be rescanned
  210.                  */
  211.                 PUT_BACK_STRING(nmstr, 1);
  212.  
  213.                 BEGIN(FIRSTCCL);
  214.                 return ( '[' );
  215.                 }
  216.             }
  217.  
  218. <SECT2>"{"{NAME}"}"    {
  219.             register char *nmdefptr;
  220.             char *ndlookup();
  221.  
  222.             (void) strcpy( nmstr, yytext );
  223.             nmstr[yyleng - 1] = '\0';  /* chop trailing brace */
  224.  
  225.             /* lookup from "nmstr + 1" to chop leading brace */
  226.             if ( ! (nmdefptr = ndlookup( nmstr + 1 )) )
  227.                 synerr( "undefined {name}" );
  228.  
  229.             else
  230.                 { /* push back name surrounded by ()'s */
  231.                 unput(')');
  232.                 PUT_BACK_STRING(nmdefptr, 0);
  233.                 unput('(');
  234.                 }
  235.             }
  236.  
  237. <SECT2>[/|*+?.()]    return ( yytext[0] );
  238. <SECT2>.        RETURNCHAR;
  239. <SECT2>\n        ++linenum; return ( '\n' );
  240.  
  241.  
  242. <SC>","            return ( ',' );
  243. <SC>">"            BEGIN(SECT2); return ( '>' );
  244. <SC>">"/"^"        BEGIN(CARETISBOL); return ( '>' );
  245. <SC>{SCNAME}        RETURNNAME;
  246. <SC>.            synerr( "bad start condition name" );
  247.  
  248. <CARETISBOL>"^"        BEGIN(SECT2); return ( '^' );
  249.  
  250.  
  251. <QUOTE>[^"\n]        RETURNCHAR;
  252. <QUOTE>\"        BEGIN(SECT2); return ( '"' );
  253.  
  254. <QUOTE>\n        {
  255.             synerr( "missing quote" );
  256.             BEGIN(SECT2);
  257.             ++linenum;
  258.             return ( '"' );
  259.             }
  260.  
  261.  
  262. <FIRSTCCL>"^"/[^-\n]    BEGIN(CCL); return ( '^' );
  263. <FIRSTCCL>"^"/-        return ( '^' );
  264. <FIRSTCCL>-        BEGIN(CCL); yylval = '-'; return ( CHAR );
  265. <FIRSTCCL>.        BEGIN(CCL); RETURNCHAR;
  266.  
  267. <CCL>-/[^\]\n]        return ( '-' );
  268. <CCL>[^\]\n]        RETURNCHAR;
  269. <CCL>"]"            BEGIN(SECT2); return ( ']' );
  270.  
  271.  
  272. <NUM>[0-9]+        {
  273.             yylval = myctoi( yytext );
  274.             return ( NUMBER );
  275.             }
  276.  
  277. <NUM>","            return ( ',' );
  278. <NUM>"}"            BEGIN(SECT2); return ( '}' );
  279.  
  280. <NUM>.            {
  281.             synerr( "bad character inside {}'s" );
  282.             BEGIN(SECT2);
  283.             return ( '}' );
  284.             }
  285.  
  286. <NUM>\n            {
  287.             synerr( "missing }" );
  288.             BEGIN(SECT2);
  289.             ++linenum;
  290.             return ( '}' );
  291.             }
  292.  
  293.  
  294. <BRACEERROR>"}"        synerr( "bad name in {}'s" ); BEGIN(SECT2);
  295. <BRACEERROR>\n        synerr( "missing }" ); ++linenum; BEGIN(SECT2);
  296.  
  297.  
  298. <PERCENT_BRACE_ACTION>{OPTWS}"%}".*    bracelevel = 0;
  299. <PERCENT_BRACE_ACTION>.*        ACTION_ECHO;
  300. <PERCENT_BRACE_ACTION>\n        {
  301.             ++linenum;
  302.             ACTION_ECHO;
  303.             if ( bracelevel == 0 )
  304.                 {
  305.                 fputs( "\tYY_BREAK\n", temp_action_file );
  306.                 BEGIN(SECT2);
  307.                 }
  308.             }
  309.  
  310. <ACTION>"{"        ACTION_ECHO; ++bracelevel;
  311. <ACTION>"}"        ACTION_ECHO; --bracelevel;
  312. <ACTION>[^{}"'/\n]+    ACTION_ECHO;
  313. <ACTION>"/*"        ACTION_ECHO; BEGIN(ACTION_COMMENT);
  314. <ACTION>"'"([^'\\\n]|\\.)*"'"    ACTION_ECHO; /* character constant */
  315. <ACTION>\"        ACTION_ECHO; BEGIN(ACTION_STRING);
  316. <ACTION>\n        {
  317.             ++linenum;
  318.             ACTION_ECHO;
  319.             if ( bracelevel == 0 )
  320.                 {
  321.                 fputs( "\tYY_BREAK\n", temp_action_file );
  322.                 BEGIN(SECT2);
  323.                 }
  324.             }
  325. <ACTION>.        ACTION_ECHO;
  326.  
  327. <ACTION_COMMENT>"*/"    ACTION_ECHO; BEGIN(ACTION);
  328. <ACTION_COMMENT>[^*\n]+    ACTION_ECHO;
  329. <ACTION_COMMENT>"*"    ACTION_ECHO;
  330. <ACTION_COMMENT>\n    ++linenum; ACTION_ECHO;
  331. <ACTION_COMMENT>.    ACTION_ECHO;
  332.  
  333. <C_COMMENT_2>"*/"    ACTION_ECHO; BEGIN(SECT2);
  334. <C_COMMENT_2>"*/".*\n    ++linenum; ACTION_ECHO; BEGIN(SECT2);
  335. <C_COMMENT_2>[^*\n]+    ACTION_ECHO;
  336. <C_COMMENT_2>"*"    ACTION_ECHO;
  337. <C_COMMENT_2>\n        ++linenum; ACTION_ECHO;
  338.  
  339. <ACTION_STRING>[^"\\\n]+    ACTION_ECHO;
  340. <ACTION_STRING>\\.    ACTION_ECHO;
  341. <ACTION_STRING>\n    ++linenum; ACTION_ECHO;
  342. <ACTION_STRING>\"    ACTION_ECHO; BEGIN(ACTION);
  343. <ACTION_STRING>.    ACTION_ECHO;
  344.  
  345.  
  346. <SECT2,QUOTE,CCL>{ESCSEQ}    {
  347.             yylval = myesc( yytext );
  348.             return ( CHAR );
  349.             }
  350.  
  351. <FIRSTCCL>{ESCSEQ}    {
  352.             yylval = myesc( yytext );
  353.             BEGIN(CCL);
  354.             return ( CHAR );
  355.             }
  356.  
  357.  
  358. <SECT3>.|\n        {
  359.             register int numchars;
  360.  
  361.             /* black magic - we know the names of a flex scanner's
  362.              * internal variables.  We cap the input buffer with
  363.              * an end-of-string and dump it to the output.
  364.              */
  365.             YY_DO_BEFORE_SCAN; /* recover from setting up yytext */
  366.  
  367. #ifdef FLEX_FAST_SKEL
  368.             fputs( yy_c_buf_p + 1, stdout );
  369. #else
  370.             yy_ch_buf[yy_e_buf_p + 1] = '\0';
  371.  
  372.             /* ignore the first character; it's the second '%'
  373.              * put back by the yyless(1) above
  374.              */
  375.             fputs( yy_ch_buf + yy_c_buf_p + 1, stdout );
  376. #endif
  377.  
  378.             /* if we don't do this, the data written by write()
  379.              * can get overwritten when stdout is finally flushed
  380.              */
  381.             (void) fflush( stdout );
  382.  
  383.             while ( (numchars = read( fileno(yyin), yy_ch_buf,
  384.                           YY_BUF_MAX )) > 0 )
  385.                 (void) write( fileno(stdout), yy_ch_buf, numchars );
  386.     
  387.             if ( numchars < 0 )
  388.                 flexerror( "fatal read error in section 3" );
  389.  
  390.             return ( EOF );
  391.             }
  392. %%
  393.