关闭

解释器的代码....

633人阅读 评论(0) 收藏 举报

 

这个是书上的例子,

 

%{
#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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:608754次
    • 积分:9252
    • 等级:
    • 排名:第2093名
    • 原创:296篇
    • 转载:149篇
    • 译文:8篇
    • 评论:34条
    最新评论