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