www.pudn.com > FUN_2V.rar > calc_yacc.y
%{
#include "ucvm_type.h"
#include "calc_yacc.h"
Node * var_id(char *);
Node * con_cs(char *);
Node * con_cc(char );
Node * con_ci(long );
Node * con_cr(Real );
Node * ass_op(long, char *, Node *);
Node * exp_op(long, long , ... );
long cc_builder(Node *);
void cc_cleanup(Node *);
void cc_exp_for(Node *);
%}
%union
{
char c_value;
long i_value;
Real r_value;
char *s_value;
Node *n_point;
}
%token IDENTIFIER
%token CONSTANT_S
%token CONSTANT_C
%token CONSTANT_I
%token CONSTANT_R
%right ASS
%type stmt_item
%type stmt_list
%type ifxx_stmt
%type loop_stmt
%type ctrl_stmt
%type goxx_stmt
%type expr_item
%type expr_list
%token IF
%nonassoc IFX
%nonassoc ELSE
%token DO
%token FOR
%token WHILE
%token BREAK
%token CONTI
%token GOTO
%token LABEL
%token CALL
%token INCB INCA
%token DECB DECA
%right ASSIGN ASSADD ASSSUB ASSMUL ASSDIV ASSBAL ASSAND ASSXOR ASSOOR ASSSHL ASSSHR
%left OOR
%left AND
%left '|'
%left '^'
%left '&'
%left CEQ CNE
%left CGE CLE '>' '<'
%left SHL SHR
%left '+' '-'
%left '*' '/' '%'
%right INC DEC '!' '~' UMI
%%
procedure
: stmt_list { cc_builder($1); cc_cleanup($1); }
;
stmt_list
: { $$ = exp_op(',', 2, 0, 0); }
| stmt_list stmt_item { $$ = exp_op(',', 2, $1, $2); }
;
stmt_item
: ';' { $$ = exp_op(',', 2, 0, 0); }
| expr_item ';' { $$ = exp_op(';', 2, $1, 0); }
| ifxx_stmt { $$ = $1; }
| loop_stmt { $$ = $1; }
| ctrl_stmt { $$ = $1; }
| goxx_stmt { $$ = $1; }
| '{' stmt_list '}' { $$ = $2; }
;
ifxx_stmt
: IF '(' expr_item ')' stmt_item %prec IFX { $$ = exp_op(IFX, 2, $3, $5 ); }
| IF '(' expr_item ')' stmt_item ELSE stmt_item { $$ = exp_op(IFX, 3, $3, $5, $7); }
;
loop_stmt
: DO stmt_item WHILE '(' expr_item ')' ';' { $$ = exp_op(DO , 2, $2, $5); }
| WHILE '(' expr_item ')' stmt_item { $$ = exp_op(WHILE, 2, $3, $5); }
| FOR '(' expr_list ';' expr_item ';' expr_list ')' stmt_item { $$ = exp_op(FOR , 4, $3, $5, $7, $9); }
| FOR '(' expr_list ';' expr_item ';' ')' stmt_item { $$ = exp_op(FOR , 4, $3, $5, 0, $8); }
| FOR '(' expr_list ';' ';' expr_list ')' stmt_item { $$ = exp_op(FOR , 4, $3, 0, $6, $8); }
| FOR '(' expr_list ';' ';' ')' stmt_item { $$ = exp_op(FOR , 4, $3, 0, 0, $7); }
| FOR '(' ';' expr_item ';' expr_list ')' stmt_item { $$ = exp_op(FOR , 4, 0, $4, $6, $8); }
| FOR '(' ';' expr_item ';' ')' stmt_item { $$ = exp_op(FOR , 4, 0, $4, 0, $7); }
| FOR '(' ';' ';' expr_list ')' stmt_item { $$ = exp_op(FOR , 4, 0, 0, $5, $7); }
| FOR '(' ';' ';' ')' stmt_item { $$ = exp_op(FOR , 4, 0, 0, 0, $6); }
;
ctrl_stmt
: BREAK ';' { $$ = exp_op(BREAK, 0); }
| CONTI ';' { $$ = exp_op(CONTI, 0); }
;
goxx_stmt
: GOTO IDENTIFIER ';' { $$ = ass_op( GOTO, $2, 0); }
| IDENTIFIER ':' stmt_item { $$ = ass_op(LABEL, $1, $3); }
;
expr_item
: CONSTANT_R { $$ = con_cr($1); }
| CONSTANT_I { $$ = con_ci($1); }
| CONSTANT_C { $$ = con_cc($1); }
| CONSTANT_S { $$ = con_cs($1); }
| IDENTIFIER { $$ = var_id($1); }
| IDENTIFIER ASS expr_item { $$ = ass_op($2, $1, $3); }
| expr_item OOR expr_item { $$ = exp_op(OOR, 2, $1, $3); }
| expr_item AND expr_item { $$ = exp_op(AND, 2, $1, $3); }
| expr_item '|' expr_item { $$ = exp_op('|', 2, $1, $3); }
| expr_item '^' expr_item { $$ = exp_op('^', 2, $1, $3); }
| expr_item '&' expr_item { $$ = exp_op('&', 2, $1, $3); }
| expr_item CEQ expr_item { $$ = exp_op(CEQ, 2, $1, $3); }
| expr_item CNE expr_item { $$ = exp_op(CNE, 2, $1, $3); }
| expr_item CLE expr_item { $$ = exp_op(CLE, 2, $1, $3); }
| expr_item CGE expr_item { $$ = exp_op(CGE, 2, $1, $3); }
| expr_item '<' expr_item { $$ = exp_op('<', 2, $1, $3); }
| expr_item '>' expr_item { $$ = exp_op('>', 2, $1, $3); }
| expr_item SHL expr_item { $$ = exp_op(SHL, 2, $1, $3); }
| expr_item SHR expr_item { $$ = exp_op(SHR, 2, $1, $3); }
| expr_item '+' expr_item { $$ = exp_op('+', 2, $1, $3); }
| expr_item '-' expr_item { $$ = exp_op('-', 2, $1, $3); }
| expr_item '*' expr_item { $$ = exp_op('*', 2, $1, $3); }
| expr_item '/' expr_item { $$ = exp_op('/', 2, $1, $3); }
| expr_item '%' expr_item { $$ = exp_op('%', 2, $1, $3); }
| '!' expr_item { $$ = exp_op('!', 1, $2); }
| '~' expr_item { $$ = exp_op('~', 1, $2); }
| '-' expr_item %prec UMI { $$ = exp_op(UMI, 1, $2); }
| INC IDENTIFIER { $$ = ass_op(INCB, $2, 0); }
| DEC IDENTIFIER { $$ = ass_op(DECB, $2, 0); }
| IDENTIFIER INC { $$ = ass_op(INCA, $1, 0); }
| IDENTIFIER DEC { $$ = ass_op(DECA, $1, 0); }
| IDENTIFIER '(' ')' { $$ = ass_op(CALL, $1, 0); }
| IDENTIFIER '(' expr_list ')' { $$ = ass_op(CALL, $1, $3); }
| '(' expr_item ')' { $$ = $2; }
;
expr_list
: expr_item { $$ = exp_op(',', 2, 0, $1); }
| expr_list ',' expr_item { $$ = exp_op(',', 2, $1, $3); }
;
%%
Node * var_id(char *vs)
{
Node *p_node;
p_node = (Node *)malloc(sizeof(Node));
p_node->node_data.id.s_label = vs;
p_node->node_type = TYPE_EXPR_ID;
return(p_node);
}
Node * con_cs(char *vs)
{
Node *p_node;
p_node = (Node *)malloc(sizeof(Node));
p_node->node_data.cs.s_value = vs;
p_node->node_type = TYPE_EXPR_CS;
return(p_node);
}
Node * con_cc(char vc)
{
Node *p_node;
p_node = (Node *)malloc(sizeof(Node));
p_node->node_data.cc.c_value = vc;
p_node->node_type = TYPE_EXPR_CC;
return(p_node);
}
Node * con_ci(long vi)
{
Node *p_node;
p_node = (Node *)malloc(sizeof(Node));
p_node->node_data.ci.i_value = vi;
p_node->node_type = TYPE_EXPR_CI;
return(p_node);
}
Node * con_cr(Real vr)
{
Node *p_node;
p_node = (Node *)malloc(sizeof(Node));
p_node->node_data.cr.r_value = vr;
p_node->node_type = TYPE_EXPR_CR;
return(p_node);
}
Node * ass_op(long op, char *va, Node *ex)
{
Node *p_node;
p_node = (Node *)malloc(sizeof(Node));
p_node->node_data.op.oper = op;
p_node->node_data.op.op_n = 2;
p_node->node_data.op.op_s[0] = var_id(va);
p_node->node_data.op.op_s[1] = ex;
p_node->node_type = TYPE_EXPR_OP;
return(p_node);
}
Node * exp_op(long op, long np, ...)
{
Node *p_node;
va_list ap;
int ai;
p_node = (Node *)malloc(sizeof(Node));
va_start(ap, np);
for(ai = 0; ai < np && ai < 4; ai ++)
{
p_node->node_data.op.op_s[ai] =
va_arg(ap, Node *);
}
va_end(ap);
p_node->node_data.op.oper = op;
p_node->node_data.op.op_n = ai;
p_node->node_type = TYPE_EXPR_OP;
return(p_node);
}
void cc_cleanup(Node *p_node)
{
if(NULL != p_node)
{
if(TYPE_EXPR_OP == p_node->node_type)
{
int i;
for(i = 0; i < p_node->node_data.op.op_n; i ++)
{
cc_cleanup(p_node->node_data.op.op_s[i]);
}
}
else
if(TYPE_EXPR_ID == p_node->node_type)
{
if(NULL != p_node->node_data.id.s_label)
free(p_node->node_data.id.s_label);
}
else
if(TYPE_EXPR_CS == p_node->node_type)
{
if(NULL != p_node->node_data.cs.s_value)
free(p_node->node_data.cs.s_value);
}
free(p_node);
}
}
long cc_builder(Node *p_node)
{
if(NULL != p_node)
{
switch(p_node->node_type)
{
case TYPE_EXPR_ID:
fprintf(asout,"push_v %s\n", p_node->node_data.id.s_label);
break;
case TYPE_EXPR_CS:
fprintf(asout,"push_s %s\n", p_node->node_data.cs.s_value);
break;
case TYPE_EXPR_CC:
fprintf(asout,"push_c %c\n", p_node->node_data.cc.c_value);
break;
case TYPE_EXPR_CI:
fprintf(asout,"push_i %d\n", p_node->node_data.ci.i_value);
break;
case TYPE_EXPR_CR:
fprintf(asout,"push_r %e\n", p_node->node_data.cr.r_value);
break;
case TYPE_EXPR_OP:
switch(p_node->node_data.op.oper)
{
case IFX:
if(p_node->node_data.op.op_n > 2)
{
char m_LabStrA[8];
char m_LabStrB[8];
zzlabel(m_LabStrA);
zzlabel(m_LabStrB);
/*if else*/
cc_builder(p_node->node_data.op.op_s[0]);
fprintf(asout, "jmp_ez %s\n", m_LabStrA);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout, "jmp %s\n", m_LabStrB);
fprintf(asout, "label: %s\n", m_LabStrA);
cc_builder(p_node->node_data.op.op_s[2]);
fprintf(asout, "label: %s\n", m_LabStrB);
}
else
{
char m_LabStrA[8];
zzlabel(m_LabStrA);
/*if then*/
cc_builder(p_node->node_data.op.op_s[0]);
fprintf(asout, "jmp_ez %s\n", m_LabStrA);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout, "label: %s\n", m_LabStrA);
}
break;
case DO: /* do ... while(...); */
{
char m_LabStrB[8]; /*break*/
char m_LabStrC[8]; /*conti*/
char *m_OldLabB;
char *m_OldLabC;
zzlabel(m_LabStrB);
zzlabel(m_LabStrC);
m_OldLabB = g_label_break;
m_OldLabC = g_label_conti;
g_label_break = m_LabStrB;
g_label_conti = m_LabStrC;
fprintf(asout, "label: %s\n", m_LabStrC);
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout, "jmp_nz %s\n", m_LabStrC);
fprintf(asout, "label: %s\n", m_LabStrB);
g_label_break = m_OldLabB;
g_label_conti = m_OldLabC;
}
break;
case FOR: /* for(... ; ... ; ...) ... */
{
char m_LabStrA[8];
char m_LabStrB[8];
char m_LabStrC[8];
char *m_OldLabB;
char *m_OldLabC;
zzlabel(m_LabStrA);
zzlabel(m_LabStrB);
zzlabel(m_LabStrC);
m_OldLabB = g_label_break;
m_OldLabC = g_label_conti;
g_label_break = m_LabStrB;
g_label_conti = m_LabStrC;
cc_exp_for(p_node->node_data.op.op_s[0]);
fprintf(asout, "label: %s\n", m_LabStrA);
if(cc_builder(p_node->node_data.op.op_s[1]))
fprintf(asout, "jmp_ez %s\n", m_LabStrB);
cc_builder(p_node->node_data.op.op_s[3]);
fprintf(asout, "label: %s\n", m_LabStrC);
cc_exp_for(p_node->node_data.op.op_s[2]);
fprintf(asout, "jmp %s\n", m_LabStrA);
fprintf(asout, "label: %s\n", m_LabStrB);
g_label_break = m_OldLabB;
g_label_conti = m_OldLabC;
}
break;
case WHILE: /* while(...) ... */
{
char m_LabStrB[8]; /*break*/
char m_LabStrC[8]; /*conti*/
char *m_OldLabB;
char *m_OldLabC;
zzlabel(m_LabStrB);
zzlabel(m_LabStrC);
m_OldLabB = g_label_break;
m_OldLabC = g_label_conti;
g_label_break = m_LabStrB;
g_label_conti = m_LabStrC;
fprintf(asout, "label: %s\n", m_LabStrC);
cc_builder(p_node->node_data.op.op_s[0]);
fprintf(asout, "jmp_ez %s\n", m_LabStrB);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout, "jmp %s\n", m_LabStrC);
fprintf(asout, "label: %s\n", m_LabStrB);
g_label_break = m_OldLabB;
g_label_conti = m_OldLabC;
}
break;
case BREAK:
if(NULL != g_label_break)
fprintf(asout, "jmp %s\n", g_label_break);
break;
case CONTI:
if(NULL != g_label_conti)
fprintf(asout, "jmp %s\n", g_label_conti);
break;
case GOTO:
fprintf(asout,"jmp %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case LABEL:
fprintf(asout,"label: %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
cc_builder(p_node->node_data.op.op_s[1]);
break;
case CALL:
{ int i = cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"push_i %d\n",i);
fprintf(asout,"call_f %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
}
break;
case ',':
{ int i = cc_builder(p_node->node_data.op.op_s[0]);
int j = cc_builder(p_node->node_data.op.op_s[1]);
return(i + j);
}
break;
case ';':
cc_builder(p_node->node_data.op.op_s[0]);
fprintf(asout,"pop_lo\n");
break;
case ASSIGN: /* = */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"assign %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSADD: /* += */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"add_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSSUB: /* -= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"sub_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSMUL: /* *= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"mul_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSDIV: /* /= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"div_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSBAL: /* %= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"rem_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSAND: /* &= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"and_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSXOR: /* ^= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"xor_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSOOR: /* |= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"oor_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSSHL: /* <<= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"shl_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case ASSSHR: /* >>= */
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"shr_as %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case OOR:/*||*/
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"oor_lg\n");
break;
case AND:/*&&*/
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"and_lg\n");
break;
case '|':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"oor_bt\n");
break;
case '^':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"xor_bt\n");
break;
case '&':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"and_bt\n");
break;
case CNE:
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"cmp_ne\n");
break;
case CEQ:
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"cmp_eq\n");
break;
case CLE:/*<=*/
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"cmp_le\n");
break;
case CGE:/*>=*/
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"cmp_ge\n");
break;
case '<':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"cmp_ll\n");
break;
case '>':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"cmp_gg\n");
break;
case SHL:/*<<*/
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"shl_bt\n");
break;
case SHR:/*>>*/
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"shr_bt\n");
break;
case '+':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"add_nb\n");
break;
case '-':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"sub_nb\n");
break;
case '*':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"mul_nb\n");
break;
case '/':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"div_nb\n");
break;
case '%':
cc_builder(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"rem_nb\n");
break;
case '!':
cc_builder(p_node->node_data.op.op_s[0]);
fprintf(asout,"not_lg\n");
break;
case '~':
cc_builder(p_node->node_data.op.op_s[0]);
fprintf(asout,"not_bt\n");
break;
case UMI:
cc_builder(p_node->node_data.op.op_s[0]);
fprintf(asout,"umi_nb\n");
break;
case INCB: /* before, ++ v */
fprintf(asout,"inc_bf %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case DECB: /* before, -- v */
fprintf(asout,"dec_bf %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case INCA: /* after, v ++ */
fprintf(asout,"inc_af %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
case DECA: /* after, v -- */
fprintf(asout,"dec_af %s\n", p_node->
node_data.op.op_s[0]->
node_data.id.s_label);
break;
default:
return(0);
}
break;
default:
return(0);
}
return(1);
}
return(0);
}
void cc_exp_for(Node *p_node)
{
if(NULL != p_node)
{
/*p_node->node_type = TYPE_OP */
/*p_node->node_data.op.oper == ',' */
/*p_node->node_data.op.op_n == 2 */
cc_exp_for(p_node->node_data.op.op_s[0]);
cc_builder(p_node->node_data.op.op_s[1]);
fprintf(asout,"pop_lo\n");
}
}