ack/util/topgen/topgen.g

312 lines
6 KiB
Plaintext

/* $Header$ */
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* t o p g e n . g
*
* Grammar of optimizer description, and some code generation
*/
%token LETTER, DIGIT, OTHER, SPACE;
%token LINE_TERMINATOR, OPERAND_SEPARATOR, INSTRUCTION_SEPARATOR,
PATTERN_SEPARATOR, OPEN_BRACKET, CLOSE_BRACKET;
%lexical LLlex;
%start LLparse, optim_description;
{
# include <stdio.h>
# include "token.h"
# include "symtab.h"
# include "misc.h"
char idbuf[BUFSIZ], buf[BUFSIZ];
int countid; /* # of variables */
int countpat; /* # of patterns */
char * malloc();
char * strcpy();
static int patlen; /* Maximum number of instructions in pattern */
static int maxoperand; /* Maximum number of operands of instruction */
extern FILE *input; /* file descriptor of inputfile */
}
optim_description
{ struct symtab *p; } :
SPACE* parameter_line*
{ p = findident("MAXOP",LOOKING,&deftable);
if (p == 0) maxoperand = 2; /* default */
else maxoperand = p->s_num;
}
separator SPACE* mode_definitions
separator SPACE* patterns
separator
{ register int c;
fprintf(genc, linedir, lineno, inpfile);
while ((c = getc(input)) != EOF) {
putc(c,genc);
}
}
;
parameter_line
{ struct symtab *p;} :
identifier
{ p = findident(idbuf,ENTERING,&deftable);}
SPACE
value
{ p->s_num = atoi(buf);}
/* This action in fact only needed for MAXOP */
LINE_TERMINATOR
SPACE*
{ fprintf(genh,"#define %s %s\n",p->s_name,buf);}
;
value
{ char *p1 = buf;} :
[
[ OPEN_BRACKET
| CLOSE_BRACKET
| OPERAND_SEPARATOR
| PATTERN_SEPARATOR
| INSTRUCTION_SEPARATOR
| SPACE
| LETTER
| DIGIT
| OTHER
| '%'
]
{ *p1++ = dot.t_attrib;}
]*
{ *p1 = '\0';}
;
mode_definitions
{ int lin; } :
{ fputs("tok_chk(varno) {\n\tint r;\n", genc);
fputs("\tchar *VAL;\n\n",genc);
fputs("\tVAL = var[varno].value;\n",genc);
fputs("\tswitch(varno) {\n",genc);
}
[
token_list
constraint(&lin)
{ fprintf(genc,linedir,lin,inpfile);
fprintf(genc,"\t\tr = (%s); break;\n",buf);
}
LINE_TERMINATOR
SPACE*
]*
{ fputs("\tdefault :\n\t\tassert(0);\n",genc);
fputs("\t}\n\treturn r;\n}\n\n",genc);
}
;
token_list :
new_identifier
SPACE*
[
OPERAND_SEPARATOR
SPACE*
new_identifier
SPACE*
]*
;
new_identifier
{ struct symtab *p;} :
identifier
{ p = findident(idbuf,ENTERING,&idtable);
p->s_num = ++countid;
fprintf(genc,"\tcase %d:\n", countid);
}
;
constraint (int *lin;)
{ char *p = buf; } :
OPEN_BRACKET
{ *lin = lineno;}
[
[ LINE_TERMINATOR
| OPERAND_SEPARATOR
| PATTERN_SEPARATOR
| INSTRUCTION_SEPARATOR
| LETTER
| DIGIT
| SPACE
| OTHER
| '%'
]
{ *p++ = dot.t_attrib;}
]*
{ *p = '\0';
if (onlyspace(buf)) strcpy(buf,"TRUE");
}
CLOSE_BRACKET
SPACE*
;
patterns
{ int lin;
char *constr;
int np, nr;
} :
[
{ countpat++;
constr = (char *) 0;
fprintf(genc,"struct instr_descr pat%d[] = {\n",
countpat);
}
instruction_list(&np)
{ if (np > patlen) patlen = np;
fputs("\n};\n\n",genc);
}
[
constraint(&lin)
{ /* Save the constraint, we need it later on */
constr = malloc((unsigned)(strlen(buf)+1));
strcpy(constr,buf);
}
]?
PATTERN_SEPARATOR
{ fprintf(genc,"struct instr_descr rep%d[] = {\n",
countpat);
}
replacement(&nr)
{ fputs("\n};\n\n",genc);}
LINE_TERMINATOR
SPACE*
{ addpattern(constr,lin,np,nr);}
]*
{ printhashtable();
printpatterns();
fprintf(genh,"#define NRVARS %d\n",countid);
fprintf(genh,"#define NRPATTERNS %d\n",countpat);
fprintf(genh,"#define MIN_WINDOW_SIZE %d\n",
patlen+3);
fclose(genh);
}
;
instruction_list(int *n;) :
instruction(1)
{ *n = 1;}
[
INSTRUCTION_SEPARATOR
{ fputs(",\n",genc);}
SPACE*
instruction(0)
{ *n += 1;}
]*
;
instruction(int opt;)
{ int count = 0;} :
opcode(opt)
{ if (strcmp(buf,"ANY") != 0) {
fprintf(genc,"\t{\"%s\", {",buf);
}
else fputs("\t{(char *) 0, {",genc);
count = 0;
}
[
operand(' ')
{ count = 1;}
[
OPERAND_SEPARATOR
{ count++;}
SPACE*
operand(',')
]*
{ if (count > maxoperand) {
error("Too many operands");
}
}
]?
{ while (count++ < maxoperand) {
fprintf(genc,"%c{\"\",-1,\"\"}",count == 1 ? ' ' : ',');
}
putc('}',genc);
putc('}',genc);
}
;
opcode(int opt;)
{ char *p = buf;} :
[
[ LETTER
| DIGIT
| OTHER
]
{ *p++ = dot.t_attrib;}
]+
SPACE+
{ *p = '\0';
if (opt) addtohashtable(buf,countpat);
}
;
operand(int c;)
{ register struct symtab *p = 0;} :
{ fprintf(genc, "%c{\"", c);}
[
identifier
{ if (!p) {
p = findident(idbuf,LOOKING,&idtable);
if (p) fprintf(genc,"\",%d,\"",p->s_num);
else fputs(idbuf,genc);
}
else fputs(idbuf,genc);
}
| DIGIT
{ putc(dot.t_attrib,genc);}
| OTHER
{ putc(dot.t_attrib,genc);}
]+
{ if (p) fputs("\"}",genc);
else fputs("\",0,\"\"}",genc);
}
SPACE*
;
replacement (int *n;)
{register i;} :
SPACE*
{ *n = 0;}
[
instruction(0)
{ *n = 1;}
[
INSTRUCTION_SEPARATOR
{ fputs(",\n", genc);}
SPACE*
instruction(0)
{ *n += 1;}
]*
| /* empty replacement, but there must be a
* structure initializer anyway
*/
{ fputs("\t{\"\", {",genc);
for (i = 0; i < maxoperand; i++) {
fprintf(genc, "%c{\"\",-1,\"\"}",i?',':' ');
}
fputs("}}",genc);
}
]
;
identifier
{ char *p = idbuf; } :
LETTER
{ *p++ = dot.t_attrib;}
[ %while (1)
LETTER { *p++ = dot.t_attrib;}
| DIGIT { *p++ = dot.t_attrib;}
]*
{ *p = '\0';}
;
separator :
'%' '%' SPACE* LINE_TERMINATOR
;