190 lines
5.1 KiB
Plaintext
190 lines
5.1 KiB
Plaintext
|
%{
|
||
|
/* scan.l: the (f)lex description file for the scanner. */
|
||
|
|
||
|
/* This file is part of bc written for MINIX.
|
||
|
Copyright (C) 1991, 1992 Free Software Foundation, Inc.
|
||
|
|
||
|
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; see the file COPYING. If not, write to
|
||
|
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
|
||
|
You may contact the author by:
|
||
|
e-mail: phil@cs.wwu.edu
|
||
|
us-mail: Philip A. Nelson
|
||
|
Computer Science Department, 9062
|
||
|
Western Washington University
|
||
|
Bellingham, WA 98226-9062
|
||
|
|
||
|
*************************************************************************/
|
||
|
|
||
|
#include "bcdefs.h"
|
||
|
#include "y.tab.h"
|
||
|
#include "global.h"
|
||
|
#include "proto.h"
|
||
|
|
||
|
/* Using flex, we can ask for a smaller input buffer. With lex, this
|
||
|
does nothing! */
|
||
|
|
||
|
#ifdef SMALL_BUF
|
||
|
#undef YY_READ_BUF_SIZE
|
||
|
#define YY_READ_BUF_SIZE 512
|
||
|
#endif
|
||
|
|
||
|
/* We want to define our own yywrap. */
|
||
|
#undef yywrap
|
||
|
_PROTOTYPE(int yywrap, (void));
|
||
|
|
||
|
/* MINIX returns from read with < 0 if SIGINT is encountered.
|
||
|
In flex, we can redefine YY_INPUT to the following. In lex, this
|
||
|
does nothing! */
|
||
|
#include <errno.h>
|
||
|
#undef YY_INPUT
|
||
|
#define YY_INPUT(buf,result,max_size) \
|
||
|
while ( (result = read( fileno(yyin), (char *) buf, max_size )) < 0 ) \
|
||
|
if (errno != EINTR) \
|
||
|
YY_FATAL_ERROR( "read() in flex scanner failed" );
|
||
|
|
||
|
%}
|
||
|
DIGIT [0-9A-F]
|
||
|
LETTER [a-z]
|
||
|
%%
|
||
|
define return(Define);
|
||
|
break return(Break);
|
||
|
quit return(Quit);
|
||
|
length return(Length);
|
||
|
return return(Return);
|
||
|
for return(For);
|
||
|
if return(If);
|
||
|
while return(While);
|
||
|
sqrt return(Sqrt);
|
||
|
scale return(Scale);
|
||
|
ibase return(Ibase);
|
||
|
obase return(Obase);
|
||
|
auto return(Auto);
|
||
|
else return(Else);
|
||
|
read return(Read);
|
||
|
halt return(Halt);
|
||
|
last return(Last);
|
||
|
warranty return(Warranty);
|
||
|
continue return(Continue);
|
||
|
print return(Print);
|
||
|
limits return(Limits);
|
||
|
"+"|"-"|";"|"("|")"|"{"|"}"|"["|"]"|","|"^" { yylval.c_value = yytext[0];
|
||
|
return((int)yytext[0]); }
|
||
|
&& { return(AND); }
|
||
|
\|\| { return(OR); }
|
||
|
"!" { return(NOT); }
|
||
|
"*"|"/"|"%" { yylval.c_value = yytext[0]; return(MUL_OP); }
|
||
|
"="|\+=|-=|\*=|\/=|%=|\^= { yylval.c_value = yytext[0]; return(ASSIGN_OP); }
|
||
|
=\+|=-|=\*|=\/|=%|=\^ {
|
||
|
#ifdef OLD_EQ_OP
|
||
|
char warn_save;
|
||
|
warn_save = warn_not_std;
|
||
|
warn_not_std = TRUE;
|
||
|
warn ("Old fashioned =<op>");
|
||
|
warn_not_std = warn_save;
|
||
|
yylval.c_value = yytext[1];
|
||
|
#else
|
||
|
yylval.c_value = '=';
|
||
|
yyless (1);
|
||
|
#endif
|
||
|
return(ASSIGN_OP);
|
||
|
}
|
||
|
==|\<=|\>=|\!=|"<"|">" { yylval.s_value = strcopyof(yytext); return(REL_OP); }
|
||
|
\+\+|-- { yylval.c_value = yytext[0]; return(INCR_DECR); }
|
||
|
"\n" { line_no++; return(NEWLINE); }
|
||
|
\\\n { line_no++; /* ignore a "quoted" newline */ }
|
||
|
[ \t]+ { /* ignore spaces and tabs */ }
|
||
|
"/*" {
|
||
|
int c;
|
||
|
|
||
|
for (;;)
|
||
|
{
|
||
|
while ( ((c=input()) != '*') && (c != EOF))
|
||
|
/* eat it */
|
||
|
if (c == '\n') line_no++;
|
||
|
if (c == '*')
|
||
|
{
|
||
|
while ( (c=input()) == '*') /* eat it*/;
|
||
|
if (c == '/') break; /* at end of comment */
|
||
|
if (c == '\n') line_no++;
|
||
|
}
|
||
|
if (c == EOF)
|
||
|
{
|
||
|
fprintf (stderr,"EOF encountered in a comment.\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
[a-z][a-z0-9_]* { yylval.s_value = strcopyof(yytext); return(NAME); }
|
||
|
\"[^\"]*\" {
|
||
|
unsigned char *look;
|
||
|
int count = 0;
|
||
|
yylval.s_value = strcopyof(yytext);
|
||
|
for (look = yytext; *look != 0; look++)
|
||
|
{
|
||
|
if (*look == '\n') line_no++;
|
||
|
if (*look == '"') count++;
|
||
|
}
|
||
|
if (count != 2) yyerror ("NUL character in string.");
|
||
|
return(STRING);
|
||
|
}
|
||
|
{DIGIT}({DIGIT}|\\\n)*("."({DIGIT}|\\\n)*)?|"."(\\\n)*{DIGIT}({DIGIT}|\\\n)* {
|
||
|
unsigned char *src, *dst;
|
||
|
int len;
|
||
|
/* remove a trailing decimal point. */
|
||
|
len = strlen(yytext);
|
||
|
if (yytext[len-1] == '.')
|
||
|
yytext[len-1] = 0;
|
||
|
/* remove leading zeros. */
|
||
|
src = yytext;
|
||
|
dst = yytext;
|
||
|
while (*src == '0') src++;
|
||
|
if (*src == 0) src--;
|
||
|
/* Copy strings removing the newlines. */
|
||
|
while (*src != 0)
|
||
|
{
|
||
|
if (*src == '\\')
|
||
|
{
|
||
|
src++; src++;
|
||
|
line_no++;
|
||
|
}
|
||
|
else
|
||
|
*dst++ = *src++;
|
||
|
}
|
||
|
*dst = 0;
|
||
|
yylval.s_value = strcopyof(yytext);
|
||
|
return(NUMBER);
|
||
|
}
|
||
|
. {
|
||
|
if (yytext[0] < ' ')
|
||
|
yyerror ("illegal character: ^%c",yytext[0] + '@');
|
||
|
else
|
||
|
if (yytext[0] > '~')
|
||
|
yyerror ("illegal character: \\%3d", (int) yytext[0]);
|
||
|
else
|
||
|
yyerror ("illegal character: %s",yytext);
|
||
|
}
|
||
|
%%
|
||
|
|
||
|
|
||
|
|
||
|
/* This is the way to get multiple files input into lex. */
|
||
|
|
||
|
int
|
||
|
yywrap()
|
||
|
{
|
||
|
if (!open_new_file ()) return (1); /* EOF on standard in. */
|
||
|
return (0); /* We have more input. */
|
||
|
}
|