ack/modules/src/em_opt/parser.g

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);
}
}