home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
intercal.zip
/
src
/
lexer.l
< prev
next >
Wrap
Text File
|
1996-09-03
|
7KB
|
311 lines
%{
/*
* NAME
* lexer.l -- source for the C-INTERCAL lexical analyzer.
*
LICENSE TERMS
Copyright (C) 1996 Eric S. Raymond
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <memory.h>
#include "ick.h"
#include "y.tab.h"
#include "lose.h"
#define YY_NO_UNPUT
#ifndef yywrap
static int yywrap(void)
{
return 1;
}
#endif /* yywrap */
#ifdef YYLINENO_BY_HAND
int yylineno = 1;
#endif /* YYLINENO_BY_HAND */
#ifdef MAIN
YYSTYPE yylval;
#endif /* MAIN */
char *textlines[MAXLINES];
int politesse = 0;
int stbeginline = 0;
#ifdef FLEX_SCANNER
static char linebuf[YY_BUF_SIZE];
#else /* FLEX_SCANNER */
static char linebuf[YYLMAX];
#endif /* FLEX_SCANNER */
static char *lineptr = linebuf;
bool re_send_token = FALSE;
int lexer(void);
static int myatoi(char *text);
#define SETLINENO \
{if (stbeginline == 0) stbeginline = yylineno; \
else if (stbeginline < 0) stbeginline = 0;}
/*
* The spectacular ugliness of INTERCAL syntax requires that the lexical
* analyzer have two levels. One, embedded in the getc() function, handles
* logical-line continuation and the ! abbrev, and stashes each logical
* line away in a buffer accessible to the code generator (this is necessary
* for the * construct to be interpreted correctly). The upper level is
* generated by lex(1) and does normal tokenizing.
*/
#undef getc(s)
int getc(FILE *fp)
{
extern FILE* yyin;
static bool bangflag = FALSE;
static bool backflag = FALSE;
if (bangflag)
{
bangflag = FALSE;
/* *lineptr++ = '!'; */
return('.');
}
else if (backflag) /* converting ctrl-H (backspace) to two chars "^H" */
{
backflag = FALSE;
/* *lineptr++ = '\010'; */
return('H');
}
else
{
int c = fgetc(fp);
if (feof(yyin))
{
*lineptr = '\0';
return(EOF);
}
#ifdef BACKSLASH_CONTINUATION
else if (c == '\\')
{
do {
c = fgetc(fp);
#ifdef YYLINENO_BY_HAND
if( c == '\n' ) yylineno++;
#endif /* YYLINENO_BY_HAND */
} while
(c != '\\' && isspace(c));
}
#endif /* BACKSLASH_CONTINUATION */
if (c == '!')
{
*lineptr++ = '!';
bangflag = TRUE;
return(c = '\'');
}
else if (c == '\010') /* convert ctrl-H (backspace) to
two chars "^" and "H" so lex can take it */
{
*lineptr++ = '\010';
backflag = TRUE;
return(c = '^');
}
else if (c == '\n')
{
*lineptr = '\0';
lineptr = linebuf;
textlines[yylineno] = strcpy((char *)malloc(1+strlen(linebuf)),linebuf);
#ifdef YYLINENO_BY_HAND
yylineno++;
#endif /* YYLINENO_BY_HAND */
return('\n');
}
else
{
#ifdef ACCEPT_LOWERCASE
if (islower(c))
c = toupper(c);
#endif /* ACCEPT_LOWERCASE */
return(*lineptr++ = c);
}
}
}
/* replace YY_INPUT so that it uses our getc function. */
#undef YY_INPUT
#define YY_INPUT(buf,result,max_size) \
{ \
int c = getc(yyin); \
if (c == EOF) { \
if (ferror(yyin)) \
YY_FATAL_ERROR("input in flex scanner failed"); \
result = YY_NULL; \
} else { \
buf[0] = c; \
result = 1; \
} \
}
%}
W [\ \t\n]*
D [0-9][\ \t\n0-9]*
%%
{D} {yylval.numval = myatoi(yytext); return(NUMBER);}
\. {return(ONESPOT);}
\: {return(TWOSPOT);}
\, {return(TAIL);}
\; {return(HYBRID);}
\# {return(MESH);}
\$ {return(MINGLE);}
\~ {return(SELECT);}
\& {yylval.numval = AND; return(UNARY);}
V {yylval.numval = OR; return(UNARY);}
"V^H-" |
\? {yylval.numval = XOR; return(UNARY);}
\^ {yylval.numval = FIN; return(UNARY);}
@ {yylval.numval = WHIRL; return(UNARY);}
[2-5]{W}@ {yylval.numval = WHIRL + myatoi(yytext) - 1; return(UNARY);}
\' {return(SPARK);}
\" {return(EARS);}
\({W}{D}\) {SETLINENO; yylval.numval = myatoi(yytext); return(LABEL);}
DO {SETLINENO; return(DO);}
PLEASE {SETLINENO; politesse++; return(DO);}
DO{W}PLEASE {SETLINENO; politesse++; return(DO);}
PLEASE{W}DO {SETLINENO; politesse++; return(DO);}
NOT {return(NOT);}
N\'T {return(NOT);}
\%{W}{D} {yylval.numval = myatoi(yytext);
if (yylval.numval && yylval.numval < 100)
return(OHOHSEVEN);
else
lose(E017, yylineno, (char *)NULL);}
SUB {return(SUB);}
BY {return(BY);}
\<- {return(GETS);}
CALCULATING {yylval.numval = GETS; return(GERUND);}
NEXT {stbeginline = 0; return(NEXT);}
NEXTING {yylval.numval = NEXT; return(GERUND);}
FORGET {return(FORGET);}
FORGETTING {yylval.numval = FORGET; return(GERUND);}
RESUME {return(RESUME);}
RESUMING {yylval.numval = RESUME; return(GERUND);}
STASH {return(STASH);}
STASHING {yylval.numval = STASH; return(GERUND);}
RETRIEVE {return(RETRIEVE);}
RETRIEVING {yylval.numval = RETRIEVE; return(GERUND);}
IGNORE {return(IGNORE);}
IGNORING {yylval.numval = IGNORE; return(GERUND);}
REMEMBER {return(REMEMBER);}
REMEMBERING {yylval.numval = REMEMBER; return(GERUND);}
ABSTAIN{W}FROM {return(ABSTAIN);}
ABSTAINING {yylval.numval = ABSTAIN; return(GERUND);}
REINSTATE {return(REINSTATE);}
REINSTATING {yylval.numval = REINSTATE; return(GERUND);}
READ{W}OUT {return(READ_OUT);}
READING{W}OUT {yylval.numval = READ_OUT; return(GERUND);}
WRITE{W}IN {return(WRITE_IN);}
WRITING{W}IN {yylval.numval = WRITE_IN; return(GERUND);}
COME{W}FROM {stbeginline = -stbeginline; return(COME_FROM);}
COMING{W}FROM {yylval.numval = COME_FROM; return(GERUND);}
GIVE{W}UP {return(GIVE_UP);}
\+ {return(INTERSECTION);}
{W} ;
. {yylval.numval = yytext[0]; return(BADCHAR);}
%%
int lexer(void)
{
static int tok = BADCHAR;
if (re_send_token)
re_send_token = FALSE;
else
{
tok = yylex();
#ifdef YYDEBUG
if (yydebug)
(void) fprintf(stdout, "yylex: returning token %d\n", tok);
#endif /* YYDEBUG */
}
#ifdef YYDEBUG
if (yydebug)
(void) fprintf(stdout, "lexer: returning token %d\n", tok);
#endif /* YYDEBUG */
return(tok);
}
static int myatoi(char *text)
{
#define MAXTEXT 100
static char buf[MAXTEXT];
register int i;
for(buf[i = 0] = '\0';*text && i < MAXTEXT;text++) {
if(isdigit(*text)) {
buf[i++] = *text;
}
}
buf[i] = '\0';
return atoi(buf);
}
void yyerror(char *errtype)
{
#ifdef MAIN
(void) printf("lextest: lexer error: %s.\n", errtype);
#else /* MAIN */
/* lose(E017, yylineno, (char *)NULL); */
(void) errtype;
#endif /* MAIN */
}
#ifdef MAIN
int main(void)
{
int t;
while ((t = yylex()) > 0)
{
(void) printf("%03d %09d\n", t, yylval.numval);
yylval.numval = 0;
}
return 0;
}
#endif /* MAIN */