这个是书上的例子,
%{
#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, $2, 0);}
|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这个概念,,,先保存在出力,这在和我之前用
面向对象是一样的效果,但是代码的理解就.....