507 lines
9.6 KiB
Text
507 lines
9.6 KiB
Text
/* Parser to read optimization patterns of the form:
|
|
op1 op2 ... test : action
|
|
or
|
|
op1 op2 ... : action
|
|
and build a program to recognize then */
|
|
|
|
%token SFIT, UFIT, ROTATE, PSIZE, WSIZE, DWSIZE, DEFINED, UNDEFINED, SAMESIGN;
|
|
%token SAMEEXT, SAMENAM, OFFSET, LOGAND, LOGOR, BITAND, BITOR, XOR;
|
|
%token MINUS, PLUS, TIMES, DIV, MOD, EQ, NE, LT, LE, GT, GE, NOT, COMP;
|
|
%token LSHIFT, RSHIFT, COMMA, OPCODE, INT, UPLUS, UMINUS, PATARG;
|
|
|
|
%start parser, input;
|
|
|
|
{
|
|
#ifndef NORCSID
|
|
static char rcsidp1[] = "$Header$";
|
|
#endif
|
|
|
|
#include "parser.h"
|
|
|
|
#define MAXPRIO 11
|
|
|
|
struct state *states[MAXSTATES];
|
|
struct action *actions[MAXSTATES];
|
|
struct mnems patterns[MAXSTATES];
|
|
int numpatterns = 0; /* Number of patterns */
|
|
int higheststate = 0; /* Highest state yet allocated */
|
|
struct idf *ops; /* Chained list of all ops */
|
|
int maxpattern = 0;
|
|
int maxreplacement = 0;
|
|
int nerrors = 0;
|
|
|
|
static int lencurrpatt;
|
|
static int lenthisrepl;
|
|
static int currentstate; /* Current state of dfa */
|
|
}
|
|
|
|
input : /* empty */
|
|
| optimization input
|
|
;
|
|
|
|
optimization
|
|
{
|
|
int startline;
|
|
struct exp_node *restrictions;
|
|
struct exp_node *finaltest;
|
|
struct mnem_list *repllist;
|
|
}
|
|
:
|
|
{
|
|
startline=linenum; currentstate=0;
|
|
lencurrpatt=0; lenthisrepl=0;
|
|
}
|
|
patterns(&restrictions)
|
|
{ finaltest = (struct exp_node *)NULL; }
|
|
[
|
|
'?'
|
|
exp(1,&finaltest)
|
|
]?
|
|
':'
|
|
action(&repllist)
|
|
{
|
|
numpatterns++;
|
|
addaction(startline,currentstate,restrictions,
|
|
finaltest,repllist);
|
|
}
|
|
'\n'
|
|
;
|
|
|
|
patterns(struct exp_node **tests;)
|
|
{
|
|
struct mnem_list *list;
|
|
struct exp_node *onetest;
|
|
}
|
|
:
|
|
{
|
|
list = (struct mnem_list *)NULL;
|
|
*tests = (struct exp_node *)NULL;
|
|
}
|
|
[
|
|
OPCODE
|
|
{
|
|
if(++lencurrpatt>maxpattern)
|
|
maxpattern=lencurrpatt;
|
|
list = addelem(list,opval, (struct exp_node *)NULL);
|
|
opval->id_used=1;
|
|
if(lencurrpatt==1)
|
|
opval->id_startpatt=1;
|
|
currentstate=dotransition(currentstate,opval,list,lencurrpatt);
|
|
}
|
|
[
|
|
restriction(opval->id_argfmt,&onetest)
|
|
{
|
|
*tests = combinetests(*tests,onetest);
|
|
}
|
|
]?
|
|
]+
|
|
;
|
|
|
|
restriction(int argtype; struct exp_node **test;)
|
|
{
|
|
struct exp_node *test1,*test2;
|
|
int relop;
|
|
int offsetop;
|
|
}
|
|
:
|
|
[ %if(argtype==CSTOPT)
|
|
[ optrelop(&relop) exp(1,test)
|
|
{
|
|
*test = mknode(relop,mkleaf(PATARG,lencurrpatt),*test);
|
|
}
|
|
| DEFINED
|
|
{
|
|
*test = mkleaf(DEFINED,lencurrpatt);
|
|
}
|
|
| UNDEFINED
|
|
{
|
|
*test = mkleaf(UNDEFINED,lencurrpatt);
|
|
}
|
|
]
|
|
| %if(argtype==EXT)
|
|
patarg(&test1)
|
|
{
|
|
*test=mknode(SAMEEXT,
|
|
mkleaf(PATARG,lencurrpatt),
|
|
test1);
|
|
}
|
|
[
|
|
[ PLUS
|
|
{ offsetop = PLUS; }
|
|
| MINUS
|
|
{ offsetop = MINUS; }
|
|
]
|
|
exp(1,&test2)
|
|
{
|
|
test2 = mknode(offsetop, test1, test2);
|
|
test2 = mknode(EQ, mkleaf(PATARG,lencurrpatt), test2);
|
|
*test = combinetests(
|
|
mknode(SAMENAM,
|
|
mkleaf(PATARG,lencurrpatt),
|
|
test1),
|
|
test2);
|
|
}
|
|
]?
|
|
|
|
|
optrelop(&relop) exp(1,test)
|
|
{
|
|
*test = mknode(relop,mkleaf(PATARG,lencurrpatt),*test);
|
|
}
|
|
]
|
|
;
|
|
|
|
optrelop(int *op;)
|
|
:
|
|
{*op = EQ;}
|
|
[ EQ {*op = EQ;}
|
|
| NE {*op = NE;}
|
|
| LT {*op = LT;}
|
|
| LE {*op = LE;}
|
|
| GT {*op = GT;}
|
|
| GE {*op = GE;}
|
|
]?
|
|
;
|
|
action(struct mnem_list **list;)
|
|
{
|
|
struct exp_node *test, *test2;
|
|
struct idf *keepopval;
|
|
int offsetop;
|
|
}
|
|
:
|
|
{ *list = (struct mnem_list *)NULL; }
|
|
[
|
|
OPCODE
|
|
{
|
|
if(++lenthisrepl>maxreplacement)
|
|
maxreplacement = lenthisrepl;
|
|
test= (struct exp_node *)NULL;
|
|
keepopval = opval;
|
|
}
|
|
[ %if(keepopval->id_argfmt==EXT)
|
|
patarg(&test)
|
|
{
|
|
test2 = test;
|
|
}
|
|
[
|
|
[ PLUS
|
|
{ offsetop = PLUS; }
|
|
| MINUS
|
|
{ offsetop = MINUS; }
|
|
]
|
|
exp(1,&test2)
|
|
{
|
|
test2 = mknode(offsetop,test,test2);
|
|
}
|
|
|
|
]?
|
|
{
|
|
test = mknode(COMMA,test,test2);
|
|
}
|
|
| exp(1,&test)
|
|
]?
|
|
{
|
|
*list = addelem(*list,keepopval,test);
|
|
}
|
|
]*
|
|
;
|
|
|
|
exp(int level; struct exp_node **result;)
|
|
{ struct exp_node *res1, *res2;
|
|
int operator; }
|
|
:
|
|
%if(level <= MAXPRIO)
|
|
exp(MAXPRIO+1,&res1)
|
|
[ %while (priority(LLsymb) >= level)
|
|
binop
|
|
{
|
|
operator=LLsymb;
|
|
}
|
|
exp(priority(operator)+1,&res2)
|
|
{
|
|
res1 = mknode(operator,res1,res2);
|
|
}
|
|
]*
|
|
{
|
|
*result = res1;
|
|
}
|
|
| '(' exp(1,result) ')'
|
|
| unaryop(&operator) exp(priority(operator)+1,&res1)
|
|
{
|
|
*result = mknode(operator,res1,(struct exp_node *)NULL);
|
|
}
|
|
| SAMESIGN '(' exp(1,&res1) COMMA exp(1,&res2) ')'
|
|
{
|
|
*result = mknode(SAMESIGN,res1,res2);
|
|
}
|
|
| SFIT '(' exp(1,&res1) COMMA exp(1,&res2) ')'
|
|
{
|
|
*result = mknode(SFIT,res1,res2);
|
|
}
|
|
| UFIT '(' exp(1,&res1) COMMA exp(1,&res2) ')'
|
|
{
|
|
*result = mknode(UFIT,res1,res2);
|
|
}
|
|
| ROTATE '(' exp(1,&res1) COMMA exp(1,&res2) ')'
|
|
{
|
|
*result = mknode(ROTATE,res1,res2);
|
|
}
|
|
| SAMEEXT '(' patarg(&res1) COMMA patarg(&res2) ')'
|
|
{
|
|
*result = mknode(SAMEEXT,res1,res2);
|
|
}
|
|
| SAMENAM '(' patarg(&res1) COMMA patarg(&res2) ')'
|
|
{
|
|
*result = mknode(SAMENAM,res1,res2);
|
|
}
|
|
| OFFSET '(' patarg(&res1) ')'
|
|
{
|
|
*result = res1;
|
|
}
|
|
| patarg(result)
|
|
| PSIZE
|
|
{
|
|
*result = mkleaf(PSIZE,0);
|
|
}
|
|
| WSIZE
|
|
{
|
|
*result = mkleaf(WSIZE,0);
|
|
}
|
|
| DWSIZE
|
|
{
|
|
*result = mkleaf(DWSIZE,0);
|
|
}
|
|
| INT
|
|
{
|
|
*result = mkleaf(INT,lastintval);
|
|
}
|
|
;
|
|
|
|
patarg(struct exp_node **result;)
|
|
{ int intval; }
|
|
: PATARG argno(&intval)
|
|
{
|
|
*result = mkleaf(PATARG,intval);
|
|
}
|
|
;
|
|
|
|
argno(int *val;)
|
|
: INT
|
|
{
|
|
*val = lastintval;
|
|
if(lastintval<0 || (lastintval>lencurrpatt)) {
|
|
fprintf(stderr ,"Illegal $%d on line %d\n",
|
|
lastintval,linenum);
|
|
nerrors++;
|
|
}
|
|
}
|
|
;
|
|
|
|
unaryop(int *operator;)
|
|
: PLUS { *operator = UPLUS; }
|
|
| MINUS { *operator = UMINUS; }
|
|
| NOT { *operator = NOT; }
|
|
| COMP { *operator = COMP; }
|
|
;
|
|
|
|
binop : LOGAND
|
|
| LOGOR
|
|
| BITAND
|
|
| BITOR
|
|
| XOR
|
|
| MINUS
|
|
| PLUS
|
|
| TIMES
|
|
| DIV
|
|
| MOD
|
|
| EQ
|
|
| NE
|
|
| LT
|
|
| LE
|
|
| GT
|
|
| GE
|
|
| LSHIFT
|
|
| RSHIFT
|
|
;
|
|
|
|
%lexical yylex;
|
|
|
|
{
|
|
addaction(startline, state, restrictions, finaltest, repllist)
|
|
int startline;
|
|
int state;
|
|
struct exp_node *restrictions, *finaltest;
|
|
struct mnem_list *repllist;
|
|
{
|
|
struct action *p, *q;
|
|
p=(struct action *)Malloc(sizeof(struct action));
|
|
p->next = (struct action *)NULL;
|
|
p->linenum = startline;
|
|
p->test = combinetests(restrictions,finaltest);
|
|
p->replacement.m_len = lenthisrepl;
|
|
p->replacement.m_elems = constructlist(repllist,lenthisrepl);
|
|
/* chain new action to END of action chain */
|
|
if((q = actions[state])==(struct action *)NULL)
|
|
actions[state] = p;
|
|
else {
|
|
while(q->next != (struct action *)NULL)
|
|
q = q->next;
|
|
q->next = p;
|
|
}
|
|
}
|
|
|
|
struct mnem_elem **
|
|
constructlist(list,len)
|
|
struct mnem_list *list;
|
|
int len;
|
|
{
|
|
struct mnem_elem **p;
|
|
p = (struct mnem_elem **)
|
|
Malloc((unsigned)(len*sizeof(struct mnem_elem *)));
|
|
while(len--) {
|
|
p[len] = list->elem;
|
|
list = list->next;
|
|
}
|
|
return(p);
|
|
}
|
|
|
|
struct mnem_list *
|
|
addelem(oldlist, mnem, test)
|
|
struct mnem_list *oldlist;
|
|
struct idf *mnem;
|
|
struct exp_node *test;
|
|
{
|
|
struct mnem_list *reslist;
|
|
struct mnem_elem *element;
|
|
element = (struct mnem_elem *)Malloc(sizeof(struct mnem_elem));
|
|
element->op_code = mnem;
|
|
element->arg = test;
|
|
reslist = (struct mnem_list *)Malloc(sizeof(struct mnem_list));
|
|
reslist->elem = element;
|
|
reslist->next = oldlist;
|
|
return(reslist);
|
|
}
|
|
|
|
int
|
|
dotransition(state, mnem, mnem_list, lenlist)
|
|
int state;
|
|
struct idf *mnem;
|
|
struct mnem_list *mnem_list;
|
|
int lenlist;
|
|
{
|
|
struct state *p;
|
|
/* look for existing transition */
|
|
for(p=states[state];
|
|
(p!=((struct state *)NULL)) && ((p->op)!=mnem);
|
|
p = p->next
|
|
);
|
|
if(p==(struct state *)NULL) {
|
|
/* none found so add a new state to dfa */
|
|
p=(struct state *)Malloc(sizeof(struct state));
|
|
p->op=mnem;
|
|
if(++higheststate>MAXSTATES) {
|
|
fprintf(stderr,"Parser: More than %s states\n",MAXSTATES);
|
|
sys_stop(S_EXIT);
|
|
}
|
|
p->goto_state= higheststate;
|
|
p->next=states[currentstate];
|
|
states[currentstate]=p;
|
|
states[higheststate] = (struct state *)NULL;
|
|
actions[higheststate] = (struct action *)NULL;
|
|
patterns[higheststate].m_len = lencurrpatt;
|
|
patterns[higheststate].m_elems =
|
|
constructlist(mnem_list,lenlist);
|
|
return(higheststate);
|
|
}
|
|
else return(p->goto_state); /* already exists */
|
|
}
|
|
|
|
struct exp_node *
|
|
combinetests(test1, test2)
|
|
struct exp_node *test1, *test2;
|
|
{
|
|
if(test1==(struct exp_node *)NULL)
|
|
return(test2);
|
|
else if(test2==(struct exp_node *)NULL)
|
|
return(test1);
|
|
else
|
|
return(mknode(LOGAND,test1,test2));
|
|
}
|
|
|
|
priority(op) int op; {
|
|
switch (op) {
|
|
case LOGOR: return(1);
|
|
case LOGAND: return(2);
|
|
case BITOR: return(3);
|
|
case XOR: return(4);
|
|
case BITAND: return(5);
|
|
case EQ:
|
|
case NE: return(6);
|
|
case LT:
|
|
case LE:
|
|
case GT:
|
|
case GE: return(7);
|
|
case LSHIFT:
|
|
case RSHIFT: return(8);
|
|
case MINUS:
|
|
case PLUS: return(9);
|
|
case TIMES:
|
|
case DIV:
|
|
case MOD: return(10);
|
|
case NOT:
|
|
case COMP:
|
|
case UPLUS:
|
|
case UMINUS: return(11);
|
|
}
|
|
fprintf(stderr,"Internal error: priority: - unrecognized operator\n");
|
|
return(0);
|
|
}
|
|
|
|
struct exp_node *
|
|
mknode(op,left,right)
|
|
int op;
|
|
struct exp_node *left,*right;
|
|
{
|
|
struct exp_node *p;
|
|
p = (struct exp_node *)Malloc(sizeof(struct exp_node));
|
|
p->node_type = op;
|
|
p->exp_left = left;
|
|
p->exp_right = right;
|
|
return(p);
|
|
}
|
|
|
|
struct exp_node *
|
|
mkleaf(op,val)
|
|
int op,val;
|
|
{
|
|
struct exp_node *p;
|
|
p = (struct exp_node *)Malloc(sizeof(struct exp_node));
|
|
p->node_type = op;
|
|
p->leaf_val = val;
|
|
return(p);
|
|
}
|
|
|
|
LLmessage(insertedtok)
|
|
int insertedtok;
|
|
{
|
|
nerrors++;
|
|
fprintf(stderr,"parser: syntax error on line %d: ",linenum);
|
|
if(insertedtok) {
|
|
fprintf(stderr,"Inserted token %d\n",insertedtok);
|
|
back_token();
|
|
}
|
|
else fprintf(stderr,"Deleted token %d\n",LLsymb);
|
|
}
|
|
|
|
main() {
|
|
initlex();
|
|
states[0] = (struct state *)NULL;
|
|
patterns[0].m_len = 0;
|
|
parser();
|
|
if(nerrors) {
|
|
fprintf(stderr,"%d errors detected\n",nerrors);
|
|
sys_stop(S_EXIT);
|
|
}
|
|
outputnopt();
|
|
sys_stop(S_END);
|
|
}
|
|
}
|