V10/cmd/ideal/idlex.l
%{
#include "ideal.h"
#include "y.tab.h"
extern int lineno, yylval;
extern boolean flyback;
#define BUFLEN 100
struct filenode {
struct filenode *next;
FILE *file;
int lineno;
char *name;
char buf[BUFLEN];
int head;
};
struct filenode *filestack = NULL;
FILE *curfile;
#undef input
#undef unput
boolean file_start = TRUE;
boolean just_popped = FALSE;
void filepush ();
void filepop ();
char input ();
void unput ();
%}
%Start PROGRAM COMMENT OUTSIDE LIBRARY INCLUDE
%%
%{
int numitems, i;
char item[5][20];
char cmd[20];
static int ISnest, bracenest, commnest, omode;
if (file_start) {
BEGIN OUTSIDE;
ISnest = 0;
};
file_start = FALSE;
%}
<OUTSIDE>^\.IS.*\n {
BEGIN PROGRAM;
if (!ISnest)
printf ("%s", yytext);
ISnest ++;
bracenest = commnest = 0;
}
<OUTSIDE>[ \t] {
if (just_popped) {
if (omode == LIBFIL)
BEGIN LIBRARY;
else if (omode == CHATTY)
BEGIN INCLUDE;
else impossible ("idlex");
just_popped = FALSE;
} else
printf ("%s", yytext);
}
<OUTSIDE>. {
printf ("%s", yytext);
}
<OUTSIDE>\n {
if (just_popped) {
BEGIN PROGRAM;
just_popped = FALSE;
} else {
printf ("\n");
}
}
<PROGRAM>box return(yylval = BOX);
<PROGRAM>var return(yylval = VAR);
<PROGRAM>bdlist return(yylval = BDLIST);
<PROGRAM>boundary return(yylval = BDLIST);
<PROGRAM>put return(yylval = PUT);
<PROGRAM>conn return(yylval = CONN);
<PROGRAM>to return(yylval = TO);
<PROGRAM>using return(yylval = USING);
<PROGRAM>construct return(yylval = CONSTRUCT);
<PROGRAM>draw return(yylval = DRAW);
<PROGRAM>opaque return(yylval = OPAQUE);
<PROGRAM>left return(yylval = LEFT);
<PROGRAM>text return(yylval = CENTER);
<PROGRAM>right return(yylval = RIGHT);
<PROGRAM>spline return(yylval = SPLINE);
<PROGRAM>at return(yylval = AT);
<PROGRAM>interior return(yylval = INTERIOR);
<PROGRAM>exterior return(yylval = EXTERIOR);
<PROGRAM>[a-zA-Z][a-zA-Z0-9]* {
yylval = lookup(&yytext[0]);
return(NAME);
}
<PROGRAM>[0-9]+|[0-9]*\.[0-9]+|[0-9]+\.[0-9]*|[0-9]+\.?[0-9]*[eE]\ *[+\-]?[0-9]+|[0-9]*\.[0-9]+[eE]\ *[+\-]?[0-9]+ {
float temp;
sscanf(yytext, "%f", &temp);
yylval = (int) fextlgen(temp);
return(CONST);
}
<PROGRAM>^\.\.\.forget.* {
numitems = sscanf (yytext, "%s %s %s %s %s %s",
cmd,
&item[0][0],
&item[1][0],
&item[2][0],
&item[3][0],
&item[4][0]
);
numitems --;
for (i = 0; i < numitems; i ++)
forget (lookup (&item[i][0]));
}
<PROGRAM>^\.\.\.radians.* radflag = TRUE;
<PROGRAM>^\.\.\.degrees.* radflag = FALSE;
<PROGRAM>^\.\.\.libfile {
omode = LIBFIL;
BEGIN LIBRARY;
}
<LIBRARY>[ \t]+ ;
<LIBRARY>[^ \t\n]+ {
idinclude (yytext, LIBFIL);
BEGIN OUTSIDE + 1;
}
<LIBRARY>\n {
BEGIN PROGRAM + 1;
}
<PROGRAM>^\.\.\.include {
omode = CHATTY;
BEGIN INCLUDE;
}
<INCLUDE>[ \t]+ ;
<INCLUDE>[^ \t\n]+ {
idinclude (yytext, CHATTY);
BEGIN OUTSIDE + 1;
}
<INCLUDE>\n {
BEGIN PROGRAM + 1;
}
<PROGRAM>^\.I[EF].*\n {
interpret ();
ISnest --;
if (!ISnest)
printf ("%s", yytext);
if (bracenest > 0)
fprintf (stderr, "ideal: excess {\n");
BEGIN OUTSIDE;
}
<PROGRAM>^\..* {
sscanf (yytext, "%s", cmd);
if (strcmp (cmd, "...libfile") && strcmp (cmd, "...include"))
printf ("%s\n", yytext);
else
REJECT;
}
<PROGRAM>#.* ;
<PROGRAM>"/*" {
commnest = 1;
BEGIN COMMENT;
}
<COMMENT>"/*" {
commnest ++;
}
<COMMENT>"*/" {
commnest --;
if (!commnest)
BEGIN PROGRAM;
}
<COMMENT>. ;
<COMMENT>\n {
}
<PROGRAM>"'"[^']* {
if (yytext[yyleng-1] == '\\') {
yytext[yyleng-1] = yytext[yyleng];
yyleng --;
yymore();
} else {
char *temp;
temp = malloc((unsigned) yyleng+1);
yytext[yyleng] = '\0';
strcpy(temp, &yytext[1]);
yylval = (int) temp;
input();
return(STRING);
}
}
<PROGRAM>\"[^\"]* {
if (yytext[yyleng-1] == '\\') {
yytext[yyleng-1] = yytext[yyleng];
yyleng --;
yymore();
} else {
char *temp;
temp = malloc((unsigned) yyleng+1);
yytext[yyleng] = '\0';
strcpy(temp, &yytext[1]);
yylval = (int) temp;
input();
return(STRING);
}
}
<PROGRAM>[ \t]+ {
if (just_popped) {
if (omode == LIBFIL)
BEGIN LIBRARY;
else if (omode == CHATTY)
BEGIN INCLUDE;
else impossible ("idlex");
just_popped = FALSE;
}
}
<PROGRAM>\n {
}
<PROGRAM>"{" {
bracenest ++;
return (yylval = LBRACE);
}
<PROGRAM>"}" {
bracenest --;
if (bracenest < 0)
fprintf (stderr, "ideal: excess }\n");
return (yylval = RBRACE);
}
<PROGRAM>[\<\>\(\)\[\]\+\-\*\/\=\,\;\:\.\^\~] return(yytext[0]);
<PROGRAM>. fprintf(stderr, "ideal: unknown input token %s flushed\n", &yytext[0]);
%%
void filepush (f)
FILE *f;
{
struct filenode *newfile;
newfile = (struct filenode *) calloc (1, sizeof (struct filenode));
if (newfile) {
newfile->next = filestack;
newfile->file = curfile = f;
newfile->head = -1;
if (filestack)
filestack->lineno = lineno;
newfile->name = malloc ((unsigned)strlen(filename)+1);
strcpy (newfile->name, filename);
filestack = newfile;
lineno = 1;
} else {
fprintf (stderr, "ideal: no room for file descriptor\n");
exit (1);
}
}
void filepop ()
{
struct filenode *oldfile;
if (filestack) {
if (filestack->head > -1)
fprintf (stderr, "ideal: characters ignored in file %s\n", filename);
oldfile = filestack;
filestack = filestack->next;
fclose (oldfile->file);
if (filestack) {
curfile = filestack->file;
lineno = filestack->lineno;
filename = filestack->name;
} else
curfile = NULL;
free ((char *)oldfile);
} else {
fprintf (stderr, "ideal: file stack botch\n");
exit (1);
}
}
int idgetc (f)
struct filenode *f;
{
int c;
if (!f)
return (EOF);
if (f->head > -1) {
c = f->buf[f->head--];
} else
c = getc(f->file);
return (c);
}
char input ()
{
int c;
c = 0;
if (filestack)
c = idgetc(filestack);
while (c == EOF && filestack) {
filepop();
if (filestack) {
c = idgetc(filestack);
just_popped = TRUE;
}
else
c = EOF;
}
if (c == '\n')
lineno++;
return ((c == EOF)?0:c);
}
void unput (c)
char c;
{
struct filenode *f;
if (f = filestack) {
if (f->head < BUFLEN) {
f->buf[++f->head] = c;
if (c == '\n')
-- lineno;
} else {
fprintf (stderr, "ideal: out of pushback space\n");
exit (1);
}
}
}