解释器的代码....

 

这个是书上的例子,

 

%{
#include <stdio.h>
#include <stdlib.h>
#define STRSIZE 
64
#include 
" y.tab.h "
#include 
" intall.h "
extern void lexerror()
;
int strcnt  =   0 ;
char string [ STRSIZE + 1 ]   = { 0 } ;
%}
%start STR1 COMM
%%
<INITIAL>
" + "     {return(ADDOP) ; }
<INITIAL> " - "     {return(SUBOP) ; }
<INITIAL> " * "     {return(MULOP) ; }
<INITIAL> " / "     {return(DIVOP) ; }

<INITIAL>
" = "     {return(ASGNOP) ; }
<INITIAL> " == "     {return(EQOP) ; }
<INITIAL> " > "     {return(GTOP) ; }
<INITIAL> " >= "     {return(GEOP) ; }
<INITIAL> " < "     {return(LSOP) ; }
<INITIAL> " <= "     {return(LEOP) ; }
<INITIAL> " != "     {return(NTOP) ; }

<INITIAL>
" { "     {return(LC) ; }
<INITIAL> " } "     {return(RC) ; }
<INITIAL> " ( "     {return(LP) ; }
<INITIAL> " ) "     {return(RP) ; }
<INITIAL> " ; "     {return(SM) ; }
<INITIAL> " , "     {return(CM) ; }
<INITIAL> "         {
                strcnt = 0;
                BEGIN STR1;
                }
<INITIAL>
" /* "     BEGIN COMM;
<INITIAL>if     {return(IF);}
<INITIAL>else   {return(ELSE);}
<INITIAL>while  {return(WHILE);}
<INITIAL>put    {return(PUT);}
<INITIAL>get    {return(GET);}
<INITIAL>[a-z]    {
                yylval.idno = yytext[0] -'a';
                return(IDENT);
                }
<INITIAL>[0-9]+ {
                yylval.num = atoi((char*)yytext);
                return(NUMBER);
                }
<INITIAL>[ ] ;
<INITIAL>[a-z0-9]+ {lexerror(
" word invalid " );}
<INITIAL>.        {lexerror(
" character invalid " );}
<STR1>
"             {
                if (strcnt>
= STRSIZE)lexerror( " string too long " ) ;
                string [ strcnt ]      =  ' 0 ' ;
                yylval.addr  =  pool(string) ;             
                BEGIN INITIAL ;
                return(STRING) ;
                }
<STR1>/
"         {
                if (strcnt < STRSIZE)
                    string[strcnt++] = '
" ' ;
                }
<STR1>/n        {
                if (strcnt < STRSIZE)
                    string
[ strcnt++ ]   =  ' ' ;                  
                }
<STR1>          {
                lexerror(
" string not closed " ) ;
                string [ strcnt ]   =  ' 0 ' ;
                yylval.addr  =  pool(string) ;
                BEGIN INITIAL ;
                return(STRING) ;
                }
<STR1>.            {
                if (strcnt <STRSIZE)string
[ strcnt++ ]   =  yytext [ 0 ] ;
                }
<COMM>
" */ "         {
                BEGIN INITIAL
;     
                }
<COMM>         
;
<COMM>.             ;
%%
void lexerror(char *s)
{
  extern int yynerrs
,  yylineno ;
  ++yynerrs ;
  fprintf(stderr , " %d:%s " , yylineno , s) ;
}

 

 

这个文件应该多留心 字符串和注释的写法

 

% {
#include 
<stdio.h>
#include 
"intall.h"
#define ID        100
#define NUM       101
#define STR          102
#define NODESIZE  100

int nodecnt = 0;
struct node{
  
int ntype;
  
int nvalue;
  
struct node *left;
  
struct node *right;
}
nodearea[NODESIZE] = {0};
%}

% union {
  
int idno;
  
int num;
  
int addr;
  
int label;
  
struct node *nodep;
}


% token  < idno >  IDENT
% token  < num >   NUMBER
% token  < addr >  STRING
% token IF ELSE WHILE GET PUT
% token LP RP
% token LC RC
% token CM SM
% token ASGNOP
% token EQOP GTOP GEOP LSOP LEOP NTOP
% left  ADDOP SUBOP
% left  MULOP DIVOP
% right MINUS
% type   < label >   if .prefix  while .prefix
% type   < nodep >  expr cond
%%
s        :stmt.list
        ;
stmt.list
        :
/*empty*/
        
| stmt.list stmt
        ;
stmt    :IDENT ASGNOP expr SM
            
{
            genexpr($
3);
            clearnode();
            gencode(OP_POP, $
1);
            }

        
| if .prefix stmt
            
{gencode(OP_LBL,$1);}
        
| if .prefix stmt    ELSE 
            
{
            gencode(OP_JMP, $
<label>= newlbl());
            gencode(OP_LBL,$
1);
            }

        stmt
            
{gencode(OP_LBL, $<label>$);}
        
| while .prefix 
            
{
            gencode(OP_JPF, $
<label>4 = newlbl());
            }

        stmt
            
{
            gencode(OP_JMP, $
1);
            gencode(OP_LBL, $
<label>2);
            }

        
| PUT LP put.list RP SM
        
| GET LP IDENT RP SM
            
{gencode(OP_GET,$3);}
        
| LC stmt.list RC
        
| SM
        
| error SM
            
{//可以使用一?机制来?制解析器相信??已?被完全修?了
            yyerrok;
            clearnode();
            }

        
| error RC
            
{
            yyerrok;
            clearnode();
            }

        ;
if .prefix
        :IF LP cond RP
        
{
        genexpr($
3);
        clearnode();
        gencode(OP_JPF,$$ 
= newlbl());
        }

        ;
while .prefix
        :WHILE LP cond RP
        
{
        gencode(OP_LBL,$$ 
= newlbl());
        genexpr($
3);
        clearnode();
        }
 
        ;
put.list
        :id.num.or.str
        
| put.list CM id.num.or.str
        ;
id.num.or.str
        :IDENT
            
{gencode(OP_PUTI, $1);}
        
| NUMBER
            
{gencode(OP_PUTN, $1);}
        
| STRING
            
{gencode(OP_PUTS, $1);}
        ;
cond    :expr EQOP expr
            
{$$ = makeexpr(EQ, $1, $3);}
        
| expr GTOP expr
            
{$$ = makeexpr(GT, $1, $3);}
        
| expr GEOP expr
            
{$$ = makeexpr(GE, $1, $3);}
        
| expr LSOP expr
            
{$$ = makeexpr(LS, $1, $3);}
        
| expr LEOP expr
            
{$$ = makeexpr(LE, $1, $3);}
        
| expr NTOP expr
            
{$$ = makeexpr(NT, $1, $3);}
        ;
expr    :expr ADDOP expr
            
{$$ = makeexpr(ADD, $1, $3);}
        
| expr SUBOP expr
            
{$$ = makeexpr(SUB, $1, $3);}
        
| expr MULOP expr
            
{$$ = makeexpr(MUL, $1, $3);}
        
| expr DIVOP expr
            
{$$ = makeexpr(DIV, $1, $3);}
        
| SUBOP expr    % prec MINUS
            
{$$ = makeexpr(MIN, $20);}
        
| LP expr RP
            
{$$ = $2;}
        
| IDENT
            
{$$ = makenode(ID, $1);}
        
| NUMBER
            
{$$ = makenode(NUM, $1);}
        ;
%%
int  yyerror( char   * str) {
    printf(
"%s ", str);
}


void  clearnode()
{
    nodecnt 
= 0;
}


struct  node  * getnode()
{
    
if (nodecnt > NODESIZE){
        fatal(
"nodearea overflow");    
    }

    
return (&nodearea[nodecnt++]);
}


struct  node  * makenode( int  type ,  int  value)
{
    
struct node *p;
    
    p 
= getnode();
    p
->ntype = type;
    p
->nvalue = value;
    p
->left = NULL;
    p
->right = NULL;
    
return(p);
}


struct  node  * makeexpr( int  type,  struct  node  * left,  struct  node *  right)
{
    
struct node *p;
    
    p 
= makenode(type ,0);
    p
->left = left;
    p
->right = right;
    
    
return(p);
}

/*式のとリーから中間コードを生成する*/
void  genexpr( struct  node *  p)
{
    
if(p == NULL){
        
return;
    }

    
if(p->left){
        genexpr(p
->left);
    }

    
if(p->right){
        genexpr(p
->right);
    }

    
switch (p->ntype){
    
case ID:
        gencode(OP_PSHI, p
->nvalue);
        
break;
    
case NUM:
        gencode(OP_PSHN, p
->nvalue);
        
break;
    
default:
        gencode(OP_CAL, p
->ntype);
        
break;
    }
    
}

 

接下来是intmain.c

 

#include  < stdio.h >
#include 
< string .h >
#include 
< stdlib.h >
#include 
" intall.h "
extern   int  yynerrs;
extern  FILE *  yyin;
int  dmpFlag  =   0 ;
#ifdef YYDEBUG
  
extern   int  yydebug;  
#endif

int  main( int  ac,  char *  av[])
{
    
if(ac < 2){
        fatal(
"option error");
    }

    
if(!(yyin = fopen(av[1],"r"))){
        fatal(
"open error");
    }

    
if(ac >= 3 && !strcmp(av[2],"-d")){
        dmpFlag 
= 1;        
#ifdef YYDEBUG
    yydebug 
= 1;
#endif
    }

    
if(yyparse() || yynerrs){
        fatal(
"not executed");    
    }

    defref();
    
if (dmpFlag){
        dumpcode();
    }

    execute();
}


void  fatal( char   * s)
{
    fprintf(stderr, 
"%s!!!. ", s);    
    exit(
0);
}

intgen.c

 

#include  < stdio.h >
#include 
< string .h >
#include 
" intall.h "

#define  CODESIZE   1000
#define  POOLSIZE   200
#define  LBLSIZE    100
int  codecnt  =   0 ;
struct  code_t codearea[CODESIZE]  =   {0} ;
int  poolcnt  =   0 ;
char  poolarea[POOLSIZE]  =   {0} ;
int  labelno  =   0 ;
int  lbltable[LBLSIZE]  =   {0} ;

/*中間コードを中間コード領域に出力する*/
void  gencode( int  op,  int  sub)
{
    
if (codecnt >=CODESIZE){
        fatal(
"codearea overflow");
    }

    codearea[codecnt].opcode 
= op;
    codearea[codecnt
++].subcode = sub;
}


/*文字列プール領域に文字列をプールする*/
int  pool( char *  p)
{
    
int i,j;
    j 
= poolcnt;
    
if ((i = poolcnt + strlen(p) + 1> POOLSIZE){
        fatal(
"poolarea overflow");
    }

    strcpy(
&poolarea[poolcnt],p);
    poolcnt 
= i;
    
return (j);
}


int  newlbl()
{
    
if(labelno >= LBLSIZE){
        fatal(
"label overflow");
    }

    
return (labelno++);
}


void  defref()
{
    
int i;
    
for (i = 0; i < codecnt; ++i){
        
if (codearea[i].opcode == OP_LBL){
            lbltable[codearea[i].subcode] 
= i;
        }

    }

    
for (i = 0;i < codecnt; ++i){
        
if(codearea[i].opcode == OP_JMP || codearea[i].opcode == OP_JPF){
            codearea[i].subcode 
= lbltable[codearea[i].subcode];
        }
    
    }

}

intexec.c,这个才是真正的ACTION...

 

#include  < stdio.h >
#include 
" intall.h "
#define  STKSIZE   100
extern   int  codecnt;
extern   char  poolarea[];
extern   struct  code_t codearea[];
int  sp  =   - 1 ;
int  stack[STKSIZE]  =   {0} ;
int  pc  =   0 ;
int  valarea[ ' z '   -   ' a '   +   1 =   {0} ;
/*
  中間コードを実行する
*/

void  execute()
{
    
int sub;
    
    
while (pc < codecnt){
        sub 
= codearea[pc].subcode;
        
switch (codearea[pc].opcode){
        
case OP_POP:
            valarea[sub] 
= stack[sp--];
            
break;
        
case OP_PSHI:
            
if (++sp >= STKSIZE)fatal("stack overflow!!");
            stack[sp] 
= valarea[sub];
            
break;
        
case OP_PSHN:
            
if (++sp >= STKSIZE)fatal("stack overflow!!");
            stack[sp] 
= sub;
            
break;
        
case OP_JMP:
            pc 
= sub;
            
break;    
        
case OP_JPF:
            
if (stack[sp--== 0){
                pc 
= sub;
            }

            
break;
        
case OP_GET:
            scanf(
"%d"&valarea[sub]);
            
break;    
        
case OP_PUTI:
            printf(
"%d", valarea[sub]);
            
break;
        
case OP_PUTN:
            printf(
"%d",sub);
            
break;
        
case OP_PUTS:
            printf(
"%s"&poolarea[sub]);
            
break;
        
case OP_CAL:
            
switch (sub){
                
case ADD:
                    
--sp;
                    stack[sp] 
= stack[sp] + stack[sp + 1];
                    
break;
                
case SUB:
                    
--sp;
                    stack[sp] 
= stack[sp] - stack[sp + 1];
                    
break;
                
case MUL:
                    
--sp;
                    stack[sp] 
= stack[sp] * stack[sp + 1];
                    
break;
                
case DIV:
                    
--sp;
                    stack[sp] 
= stack[sp] / stack[sp + 1];
                    
break;
                
case MIN:
                    
--sp;
                    stack[sp] 
= -stack[sp];
                    
break;
                
case EQ:
                    
--sp;
                    stack[sp] 
= stack[sp] == stack[sp + 1];
                    
break;
                
case GT:
                    
--sp;
                    stack[sp] 
= stack[sp] > stack[sp + 1];
                    
break;
                
case GE:
                    
--sp;
                    stack[sp] 
= stack[sp] >= stack[sp + 1];
                    
break;
                
case LS:
                    
--sp;
                    stack[sp] 
= stack[sp] < stack[sp + 1];
                    
break;
                
case LE:
                    
--sp;
                    stack[sp] 
= stack[sp] <= stack[sp + 1];
                    
break;
                
case NT:
                    
--sp;
                    stack[sp] 
= stack[sp] != stack[sp + 1];
                    
break;
            }

        }

    
++pc;
    }
    
}

intall.h

 

#ifndef INTALL_H__
#define  INTALL_H__

#define  OP_POP              1    /*give valarea to value */
#define  OP_PSHI             2    /*変数の値をスタックにプッシュする*/
#define  OP_PSHN             3    /*定数の値をスタックにプッシュする*/
#define  OP_CAL              4    /*演算子*/
#define  OP_LBL              5    /*ラベル*/
#define  OP_JMP              6    /*ラベル*/
#define  OP_JPF              7    /*ラベル*/
#define  OP_GET              8    /*scanf*/
#define  OP_PUTI             9    /*変量名IDENT,valareaの値を出力*/
#define  OP_PUTN             10  /*NUM数字定数の値*/
#define  OP_PUTS             11    /*文字列出力*/
/*演算子*/
#define  ADD                 1
#define  SUB                 2
#define  MUL                 3
#define  DIV                 4
#define  MIN                 5
#define  EQ                  6
#define  GT                  7
#define  GE                  8
#define  LS                  9
#define  LE                  10
#define  NT                  11

struct  code_t {
    
int opcode;
    
int subcode;
}
;


void  fatal( char * );
#endif

 

没有什么好说的,我是拿书上的例子在学习,这里应该注意的是中间CODE这个概念,,,先保存在出力,这在和我之前用

面向对象是一样的效果,但是代码的理解就.....

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的横打

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值