home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / intercal.zip / src / lexer.l < prev    next >
Text File  |  1996-09-03  |  7KB  |  311 lines

  1. %{
  2. /*
  3.  * NAME
  4.  *   lexer.l -- source for the C-INTERCAL lexical analyzer.
  5.  *
  6. LICENSE TERMS
  7.     Copyright (C) 1996 Eric S. Raymond 
  8.  
  9.     This program is free software; you can redistribute it and/or modify
  10.     it under the terms of the GNU General Public License as published by
  11.     the Free Software Foundation; either version 2 of the License, or
  12.     (at your option) any later version.
  13.  
  14.     This program is distributed in the hope that it will be useful,
  15.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.     GNU General Public License for more details.
  18.  
  19.     You should have received a copy of the GNU General Public License
  20.     along with this program; if not, write to the Free Software
  21.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include <memory.h>
  28. #include "ick.h"
  29. #include "y.tab.h"
  30. #include "lose.h"
  31.  
  32. #define YY_NO_UNPUT
  33.  
  34. #ifndef yywrap
  35. static int yywrap(void)
  36. {
  37.     return 1;
  38. }
  39. #endif /* yywrap */
  40.  
  41. #ifdef YYLINENO_BY_HAND
  42. int     yylineno = 1;
  43. #endif /* YYLINENO_BY_HAND */
  44.  
  45. #ifdef MAIN
  46. YYSTYPE    yylval;
  47. #endif /* MAIN */
  48.  
  49. char *textlines[MAXLINES];
  50. int politesse = 0;
  51. int stbeginline = 0;
  52.  
  53. #ifdef FLEX_SCANNER
  54. static char linebuf[YY_BUF_SIZE];
  55. #else /* FLEX_SCANNER */
  56. static char linebuf[YYLMAX];
  57. #endif /* FLEX_SCANNER */
  58.  
  59. static char *lineptr = linebuf;
  60.  
  61. bool re_send_token = FALSE;
  62.  
  63. int lexer(void);
  64. static int myatoi(char *text);
  65.  
  66. #define SETLINENO                    \
  67.     {if (stbeginline == 0)    stbeginline = yylineno;    \
  68.      else if (stbeginline < 0)    stbeginline = 0;}
  69.  
  70. /*
  71.  * The spectacular ugliness of INTERCAL syntax requires that the lexical
  72.  * analyzer have two levels. One, embedded in the getc() function, handles
  73.  * logical-line continuation and the ! abbrev, and stashes each logical
  74.  * line away in a buffer accessible to the code generator (this is necessary
  75.  * for the * construct to be interpreted correctly). The upper level is
  76.  * generated by lex(1) and does normal tokenizing.
  77.  */
  78.  
  79. #undef getc(s)
  80. int getc(FILE *fp)
  81. {
  82.     extern FILE* yyin;
  83.  
  84.     static bool bangflag = FALSE;
  85.     static bool backflag = FALSE;
  86.  
  87.     if (bangflag)
  88.     {
  89.     bangflag = FALSE;
  90.     /*    *lineptr++ = '!'; */
  91.     return('.');
  92.     }
  93.     else if (backflag)    /* converting ctrl-H (backspace) to two chars "^H" */
  94.     {
  95.     backflag = FALSE;
  96.     /*    *lineptr++ = '\010'; */
  97.     return('H');
  98.     }
  99.     else
  100.     {
  101.     int c = fgetc(fp);
  102.  
  103.     if (feof(yyin))
  104.     {
  105.         *lineptr = '\0';
  106.         return(EOF);
  107.     }
  108. #ifdef BACKSLASH_CONTINUATION
  109.     else if (c == '\\')
  110.     {
  111.         do {
  112.         c = fgetc(fp);
  113. #ifdef    YYLINENO_BY_HAND
  114.         if( c == '\n' ) yylineno++;
  115. #endif    /* YYLINENO_BY_HAND */
  116.         } while
  117.         (c != '\\' && isspace(c));
  118.     }
  119. #endif    /* BACKSLASH_CONTINUATION */
  120.     if (c == '!')
  121.     {
  122.         *lineptr++ = '!';
  123.         bangflag = TRUE;
  124.         return(c = '\'');
  125.     }
  126.     else if (c == '\010')    /* convert ctrl-H (backspace) to
  127.                    two chars "^" and "H" so lex can take it */
  128.     {
  129.         *lineptr++ = '\010';
  130.         backflag = TRUE;
  131.         return(c = '^');
  132.     }
  133.     else if (c == '\n')
  134.     {
  135.         *lineptr = '\0';
  136.         lineptr = linebuf;
  137.         textlines[yylineno] = strcpy((char *)malloc(1+strlen(linebuf)),linebuf);
  138. #ifdef YYLINENO_BY_HAND
  139.         yylineno++;
  140. #endif /* YYLINENO_BY_HAND */
  141.         return('\n');
  142.     }
  143.     else
  144.     {
  145. #ifdef ACCEPT_LOWERCASE
  146.         if (islower(c))
  147.         c = toupper(c);
  148. #endif /* ACCEPT_LOWERCASE */
  149.         return(*lineptr++ = c);
  150.     }
  151.     }
  152. }
  153.  
  154. /* replace YY_INPUT so that it uses our getc function. */
  155. #undef YY_INPUT
  156. #define YY_INPUT(buf,result,max_size) \
  157.     { \
  158.       int c = getc(yyin); \
  159.       if (c == EOF) { \
  160.         if (ferror(yyin)) \
  161.           YY_FATAL_ERROR("input in flex scanner failed"); \
  162.         result = YY_NULL; \
  163.       } else { \
  164.         buf[0] = c; \
  165.         result = 1; \
  166.       } \
  167.     }
  168.  
  169. %}
  170.  
  171. W    [\ \t\n]*
  172. D    [0-9][\ \t\n0-9]*
  173.  
  174. %%
  175.  
  176. {D}        {yylval.numval = myatoi(yytext); return(NUMBER);}
  177. \.        {return(ONESPOT);}
  178. \:        {return(TWOSPOT);}
  179. \,        {return(TAIL);}
  180. \;        {return(HYBRID);}
  181. \#        {return(MESH);}
  182.  
  183. \$        {return(MINGLE);}
  184. \~        {return(SELECT);}
  185.  
  186. \&        {yylval.numval = AND; return(UNARY);}
  187. V        {yylval.numval = OR; return(UNARY);}
  188. "V^H-"        |
  189. \?        {yylval.numval = XOR; return(UNARY);}
  190. \^        {yylval.numval = FIN; return(UNARY);}
  191. @        {yylval.numval = WHIRL; return(UNARY);}
  192. [2-5]{W}@    {yylval.numval = WHIRL + myatoi(yytext) - 1; return(UNARY);}
  193.  
  194. \'        {return(SPARK);}
  195. \"        {return(EARS);}
  196.  
  197. \({W}{D}\)    {SETLINENO; yylval.numval = myatoi(yytext); return(LABEL);}
  198.  
  199. DO        {SETLINENO; return(DO);}
  200. PLEASE        {SETLINENO; politesse++; return(DO);}
  201. DO{W}PLEASE    {SETLINENO; politesse++; return(DO);}
  202. PLEASE{W}DO    {SETLINENO; politesse++; return(DO);}
  203. NOT        {return(NOT);}
  204. N\'T        {return(NOT);}
  205.  
  206. \%{W}{D}    {yylval.numval = myatoi(yytext);
  207.                  if (yylval.numval && yylval.numval < 100)
  208.            return(OHOHSEVEN);
  209.          else
  210.            lose(E017, yylineno, (char *)NULL);}
  211. SUB        {return(SUB);}
  212. BY        {return(BY);}
  213.  
  214. \<-        {return(GETS);}
  215. CALCULATING    {yylval.numval = GETS; return(GERUND);}
  216.  
  217. NEXT        {stbeginline = 0; return(NEXT);}
  218. NEXTING        {yylval.numval = NEXT; return(GERUND);}
  219. FORGET        {return(FORGET);}
  220. FORGETTING    {yylval.numval = FORGET; return(GERUND);}
  221. RESUME        {return(RESUME);}
  222. RESUMING    {yylval.numval = RESUME; return(GERUND);}
  223. STASH        {return(STASH);}
  224. STASHING    {yylval.numval = STASH; return(GERUND);}
  225. RETRIEVE    {return(RETRIEVE);}
  226. RETRIEVING    {yylval.numval = RETRIEVE; return(GERUND);}
  227. IGNORE        {return(IGNORE);}
  228. IGNORING    {yylval.numval = IGNORE; return(GERUND);}
  229. REMEMBER    {return(REMEMBER);}
  230. REMEMBERING    {yylval.numval = REMEMBER; return(GERUND);}
  231. ABSTAIN{W}FROM    {return(ABSTAIN);}
  232. ABSTAINING    {yylval.numval = ABSTAIN; return(GERUND);}
  233. REINSTATE    {return(REINSTATE);}
  234. REINSTATING    {yylval.numval = REINSTATE; return(GERUND);}
  235. READ{W}OUT    {return(READ_OUT);}
  236. READING{W}OUT    {yylval.numval = READ_OUT; return(GERUND);}
  237. WRITE{W}IN    {return(WRITE_IN);}
  238. WRITING{W}IN    {yylval.numval = WRITE_IN; return(GERUND);}
  239. COME{W}FROM    {stbeginline = -stbeginline; return(COME_FROM);}
  240. COMING{W}FROM    {yylval.numval = COME_FROM; return(GERUND);}
  241. GIVE{W}UP    {return(GIVE_UP);}
  242.  
  243. \+        {return(INTERSECTION);}
  244.  
  245. {W}         ;
  246. .        {yylval.numval = yytext[0]; return(BADCHAR);}
  247.  
  248.  
  249. %%
  250.  
  251. int lexer(void)
  252. {
  253.     static int tok = BADCHAR;
  254.  
  255.     if (re_send_token)
  256.     re_send_token = FALSE;
  257.     else 
  258.     {
  259.     tok = yylex();
  260. #ifdef YYDEBUG
  261.     if (yydebug)
  262.         (void) fprintf(stdout, "yylex: returning token %d\n", tok); 
  263. #endif /* YYDEBUG */
  264.     }
  265.  
  266. #ifdef YYDEBUG
  267.     if (yydebug)
  268.     (void) fprintf(stdout, "lexer: returning token %d\n", tok); 
  269. #endif /* YYDEBUG */
  270.     return(tok);
  271. }
  272.  
  273. static int myatoi(char *text)
  274. {
  275. #define MAXTEXT 100
  276.     static char buf[MAXTEXT];
  277.     register int i;
  278.  
  279.     for(buf[i = 0] = '\0';*text && i < MAXTEXT;text++) {
  280.     if(isdigit(*text)) {
  281.         buf[i++] = *text;
  282.     }
  283.     }
  284.     buf[i] = '\0';
  285.     return atoi(buf);
  286. }
  287.  
  288. void yyerror(char *errtype)
  289. {
  290. #ifdef MAIN
  291.     (void) printf("lextest: lexer error: %s.\n", errtype);
  292. #else /* MAIN */
  293.     /* lose(E017, yylineno, (char *)NULL); */
  294.     (void) errtype;
  295. #endif /* MAIN */
  296. }
  297.  
  298. #ifdef MAIN
  299. int main(void)
  300. {
  301.     int    t;
  302.  
  303.     while ((t = yylex()) > 0)
  304.     {
  305.         (void) printf("%03d %09d\n", t, yylval.numval);
  306.         yylval.numval = 0;
  307.     }
  308.     return 0;
  309. }
  310. #endif /* MAIN */
  311.