| ;
/* NULL */
stmt:
';' | expr ';'
{ $$ = opr(';', 2, NULL, NULL); } { $$ = $1; }
{ $$ = opr(PRINT, 1, $2); }
{ $$ = opr('=', 2, set_index($1), $3); }
| PRINT expr ';' | VARIABLE '=' expr ';'
| WHILE '(' expr ')' stmt { $$ = opr(WHILE, 2, $3, $5); } | IF '(' expr ')' stmt %prec IFX { $$ = opr(IF, 2, $3, $5); } | IF '(' expr ')' stmt ELSE stmt %prec ELSE | '{' stmt_list '}' ;
{ $$ = $1; }
{ $$ = opr(';', 2, $2, $1); }
{ $$ = $2; }
{ $$ = opr(IF, 3, $3, $5, $7); }
stmt_list:
stmt
| stmt_list stmt ;
INTEGER | VARIABLE
expr: %%
{ $$ = set_content($1); } { $$ = set_index($1); }
| expr '+' expr | expr '-' expr | expr '*' expr | expr '/' expr | expr '%' expr | expr '<' expr | expr '>' expr | expr GE expr | expr LE expr | expr NE expr | expr EQ expr | expr AND expr | expr OR expr
{ $$ = opr('+', 2, $1, $3); } { $$ = opr('-', 2, $1, $3); } { $$ = opr('*', 2, $1, $3); } { $$ = opr('/', 2, $1, $3); } { $$ = opr('%', 2, $1, $3); } { $$ = opr('<', 2, $1, $3); } { $$ = opr('>', 2, $1, $3); } { $$ = opr(GE, 2, $1, $3); } { $$ = opr(LE, 2, $1, $3); } { $$ = opr(NE, 2, $1, $3); } { $$ = opr(EQ, 2, $1, $3); } { $$ = opr(AND, 2, $1, $3); } { $$ = opr(OR, 2, $1, $3); } { $$ = opr(NOT, 1, $2); } { $$ = opr(UMINUS, 1, $2); } { $$ = $2; }
| NOT expr | '-' expr %prec UMINUS | '(' expr ')' ;
#define SIZE_OF_NODE ((char *)&p->content - (char *)p)
Node *set_content(int value) {
Node *p;
size_t sizeNode;
/* 分配结点空间 */
sizeNode = SIZE_OF_NODE + sizeof(int); if ((p = malloc(sizeNode)) == NULL) yyerror(\ }
Node *set_index(int value) {
Node *p;
size_t sizeNode;
/* 分配结点空间 */
sizeNode = SIZE_OF_NODE + sizeof(int); if ((p = malloc(sizeNode)) == NULL) /* 复制内容 */
p->type = TYPE_CONTENT; p->content = value; return p;
yyerror(\ /* 复制内容 */ p->type = TYPE_INDEX; p->index = value;
return p; }
Node *opr(int name, int num, ...) {
va_list valist;
Node *p;
size_t sizeNode; int i;
/* 分配结点空间 */
sizeNode = SIZE_OF_NODE + sizeof(OpNode) + (num - 1) * sizeof(Node*); if ((p = malloc(sizeNode)) == NULL)
yyerror(\ /* 复制内容 */
p->type = TYPE_OP; p->op.name = name; p->op.num = num;
va_start(valist, num);
for (i = 0; i < num; i++)
p->op.node[i] = va_arg(valist, Node*); va_end(valist); return p;
}
void freeNode(Node *p) {
int i;
if (!p) return;
if (p->type == TYPE_OP) {
for (i = 0; i < p->op.num; i++) freeNode(p->op.node[i]);
}
free (p); }
void yyerror(char *s) {
fprintf(stdout, \
}
int main(void) { }
yyparse(); return 0;
定义结点如下: union tagYYSTYPE { };
extern YYSTYPE YYNEAR yylval;
在本程序中,还有自定义的头文件node.h如下:
typedef enum { TYPE_CONTENT, TYPE_INDEX, TYPE_OP } NodeEnum;
int iValue; /* 变量值 */ char sIndex; /* 变量数组索引 */ Node *nPtr; /* 结点地址 */
/* 操作符 */ typedef struct { int name; int num;
/* 操作符名称 */ /* 操作元个数 */ /* 操作元地址 可扩展 */
struct NodeTag * node[1]; } OpNode;
typedef struct NodeTag {
NodeEnum type; union { };
int content; int index;
/* 树结点类型 */
/* Union 必须是最后一个成员 */
/* 内容 */ /* 索引 */
/* 操作符对象 */
OpNode op;
} Node;
extern int Var[26];
七、 运行结果及测试程序