353 lines
5.5 KiB
Plaintext
353 lines
5.5 KiB
Plaintext
%{
|
|
/* $Id$ */
|
|
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
# include <ctype.h>
|
|
# include "token.h"
|
|
# include "Lpars.h"
|
|
|
|
# define TAB 8 /* Size of a acsii tab (\t) in spaces */
|
|
# if (TAB&(TAB-1))!=0
|
|
# define TABSTOP(ind) ((ind)+TAB-(ind)%TAB)
|
|
# else
|
|
# define TABSTOP(ind) (((ind)+TAB)&(~(TAB-1)))
|
|
# endif
|
|
|
|
char *Malloc(), *strcpy();
|
|
|
|
struct token token;
|
|
int ind=0; /* Indentation level of current line */
|
|
static int tab=0; /* First indentation found */
|
|
|
|
int included=0; /* Is current file included? */
|
|
int lineno = 1;
|
|
%}
|
|
|
|
%%
|
|
'((\*[^\n])|([^'\n*]))*' {
|
|
if ((token.t_lval=char_constant(yytext+1))== -1L)
|
|
report("%s not a character constant", yytext);
|
|
|
|
return CHAR_CONST;
|
|
}
|
|
'[^'\n]*'? {
|
|
report("missing '.");
|
|
token.t_lval= -1L;
|
|
|
|
return CHAR_CONST;
|
|
}
|
|
\"((\*[^\n])|([^"\n*]))*\" {
|
|
char *string();
|
|
|
|
token.t_sval=string(yytext);
|
|
|
|
return STRING;
|
|
}
|
|
\"[^"\n]*\"? {
|
|
report("missing \".");
|
|
token.t_sval="";
|
|
|
|
return STRING;
|
|
}
|
|
#[ \t]*"line"?[ \t]*[0-9]+[ \t]*\"[^"\n]*\" {
|
|
set_line_file(yytext);
|
|
tab=0;
|
|
}
|
|
#[A-Fa-f0-9]+ {
|
|
long hex_number();
|
|
|
|
token.t_lval=hex_number(yytext+1);
|
|
|
|
return NUMBER;
|
|
}
|
|
[0-9]+ {
|
|
long number();
|
|
|
|
token.t_lval=number(yytext);
|
|
|
|
return NUMBER;
|
|
}
|
|
[A-Za-z][A-Za-z0-9.]* {
|
|
register key;
|
|
|
|
if ((key=keyword(yytext))==IDENTIFIER)
|
|
token.t_sval=strcpy(Malloc(yyleng+1), yytext);
|
|
|
|
return key;
|
|
}
|
|
\n[ \f\t]*/"--" {/* Line with only a comment, don't set tab */
|
|
lineno++;
|
|
}
|
|
|
|
\n[ \f\t]* {
|
|
|
|
lineno++;
|
|
ind=indentation(yytext+1);
|
|
if (tab==0)
|
|
tab=ind;
|
|
else
|
|
if (ind%tab!=0)
|
|
warning("indentation not on a %d space boundary", tab);
|
|
}
|
|
[ \f\t] { /* Nothing */ }
|
|
[-=<>:,;+*/\[\]()?!&] return yytext[0];
|
|
|
|
"\\" return BS;
|
|
":=" return AS;
|
|
"<=" return LE;
|
|
">=" return GE;
|
|
"<>" return NE;
|
|
"<<" return LS;
|
|
">>" return RS;
|
|
"/\\" return BA;
|
|
"\\/" return BO;
|
|
"><" return BX;
|
|
|
|
"--"[^\n]* { /* Comment is skipped */ }
|
|
. {
|
|
warning((' '<=yytext[0] && yytext[0]<0177) ? "%s'%c')" : "%soctal: %o)",
|
|
"bad character seen (", yytext[0]&0377);
|
|
}
|
|
%%
|
|
char *string(s) char *s;
|
|
{
|
|
register c;
|
|
register char *p= s;
|
|
char *str= s;
|
|
|
|
str++; p++;
|
|
while (*str != '"') {
|
|
if ((c=character(&str)) != -1)
|
|
*p++= c;
|
|
else
|
|
return "";
|
|
}
|
|
|
|
*p=0;
|
|
*s=p-(s+1);
|
|
return s;
|
|
}
|
|
|
|
long number(s) register char *s;
|
|
{
|
|
static char max_str[]="2147483647";
|
|
int maxlen=sizeof max_str-1;
|
|
long atol();
|
|
long num;
|
|
|
|
while (*s=='0') { /* skip leading nulls */
|
|
*s++;
|
|
yyleng--;
|
|
}
|
|
|
|
if (*s==0)
|
|
num=0L;
|
|
else {
|
|
if ((yyleng>maxlen) || (yyleng==maxlen && strcmp(s, max_str)>0))
|
|
warning("integer constant overflow.");
|
|
|
|
num=atol(s);
|
|
}
|
|
|
|
return num;
|
|
}
|
|
|
|
long hex_number(s) register char *s;
|
|
{
|
|
long number=0L;
|
|
|
|
while (*s)
|
|
number=(number<<4)+hextoint(*s++);
|
|
|
|
return number;
|
|
}
|
|
|
|
int hextoint(c) register c;
|
|
{
|
|
register val;
|
|
|
|
if (islower(c))
|
|
val=(c-'a')+10;
|
|
else
|
|
if (isupper(c))
|
|
val=(c-'A')+10;
|
|
else
|
|
val=c-'0';
|
|
|
|
return val;
|
|
}
|
|
|
|
int character(S) register char **S;
|
|
{
|
|
register char *s= *S;
|
|
register c, cc;
|
|
|
|
if ((c= *s++)=='*') {
|
|
switch (c= *s++) {
|
|
case 'c':
|
|
cc='\r';
|
|
break;
|
|
case 'n':
|
|
cc='\n';
|
|
break;
|
|
case 't':
|
|
cc='\t';
|
|
break;
|
|
case 's':
|
|
cc=' ';
|
|
break;
|
|
case '#':
|
|
if (isxdigit(c= *s++) && isxdigit(*s)) {
|
|
cc= (hextoint(c)<<4)+hextoint(*s++);
|
|
break;
|
|
} else {
|
|
report("two digit hexadecimal const expected.");
|
|
return -1;
|
|
}
|
|
default:
|
|
cc=c;
|
|
break;
|
|
}
|
|
} else
|
|
cc=c;
|
|
|
|
*S=s;
|
|
return cc;
|
|
}
|
|
|
|
int char_constant(s) char *s;
|
|
{
|
|
register cc;
|
|
|
|
cc=character(&s);
|
|
|
|
return (*s=='\'' && cc!= -1) ? cc : -1;
|
|
}
|
|
|
|
int indentation(s) register char *s;
|
|
{
|
|
register in=0, c;
|
|
|
|
while (c= *s++) {
|
|
if (c=='\t')
|
|
in=TABSTOP(in);
|
|
else
|
|
if (c=='\f')
|
|
in=0;
|
|
else
|
|
in++;
|
|
}
|
|
|
|
return in;
|
|
}
|
|
|
|
int tabulated(oind, ind) register oind, ind;
|
|
{
|
|
if (tab>0 && ind>oind+tab)
|
|
warning("process' indentation too large (changed to %d tab%s)",
|
|
oind/tab+1, oind>=tab ? "s" : "");
|
|
return ind>oind;
|
|
}
|
|
|
|
int rep_tk=0;
|
|
struct token rep_token;
|
|
|
|
void repeat_token(tk)
|
|
{
|
|
rep_tk=tk;
|
|
rep_token=token;
|
|
}
|
|
|
|
scanner()
|
|
{
|
|
register tk;
|
|
|
|
if (rep_tk>0) {
|
|
tk=rep_tk;;
|
|
rep_tk=0;
|
|
token=rep_token;
|
|
return tk;
|
|
} else
|
|
return yylex();
|
|
}
|
|
|
|
char *tokenname(tk, inst) register tk, inst;
|
|
{
|
|
if (tk<0400) {
|
|
static char c[7];
|
|
|
|
if (' '<tk && tk<='~')
|
|
sprint(c, "'%c'", tk);
|
|
else
|
|
sprint(c, "'*#%02x'", tk);
|
|
return c;
|
|
} else {
|
|
switch (tk) {
|
|
char *keyname();
|
|
char fake_id[1+sizeof(int)*3+1];
|
|
static fake_cnt=0;
|
|
default:
|
|
return keyname(tk);
|
|
case IDENTIFIER:
|
|
if (inst) {
|
|
sprint(fake_id, "_%d", ++fake_cnt);
|
|
token.t_sval=strcpy(Malloc(strlen(fake_id)+1),
|
|
fake_id);
|
|
return "IDENTIFIER";
|
|
} else
|
|
return token.t_sval;
|
|
case NUMBER:
|
|
case CHAR_CONST:
|
|
token.t_lval=0L;
|
|
return "NUMBER";
|
|
case STRING:
|
|
if (inst) {
|
|
token.t_sval=Malloc(1);
|
|
token.t_sval[0]=0;
|
|
} else
|
|
free(token.t_sval);
|
|
return "STRING";
|
|
case AS: case LE: case GE: case NE:
|
|
case LS: case RS: case BA: case BO:
|
|
case BX: case BS: {
|
|
static int op[]= {
|
|
AS, LE, GE, NE, LS, RS, BA, BO, BX, BS
|
|
};
|
|
static char *opc[]= {
|
|
":=", "<=", ">=", "<>", "<<", ">>", "/\\",
|
|
"\\/", "><", "\\"
|
|
};
|
|
register i;
|
|
static char qopc[5];
|
|
|
|
for (i=0; op[i]!=tk; i++) ;
|
|
sprint(qopc, "'%s'", opc[i]);
|
|
return qopc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
set_line_file(l) register char *l;
|
|
{
|
|
register char *file;
|
|
|
|
while (*l<'0' || *l>'9') l++;
|
|
|
|
lineno=0;
|
|
while ('0'<=*l && *l<='9')
|
|
lineno=lineno*10+(*l++ - '0');
|
|
|
|
lineno--;
|
|
|
|
while (*l++!='"');
|
|
|
|
file=l;
|
|
while (*l++!='"');
|
|
*--l=0;
|
|
|
|
included=set_file(file);
|
|
}
|