Lex和Yacc应用方法(五).再识语法树
草木瓜 20070524
一、序
在《Lex和Yacc应用教程(四).语法树》一文已对语法树有了初步的概念,本文主要目的
是巩固语法树的概念,并做进一步的扩展分析。闲说少说,首先给出完整示例,本例在Redhat Linux 9
下调试通过,可放心使用。
另外系列文章的标题,有的叫“lex和yacc应用方法”,有的叫“lex和yacc应用教程”,
还有的叫“lex和yacc使用教程”等等,概念都是一样的。之所以起这么多名字是便于大家通
过搜索引擎能迅速查到。
<本站文章难免有错误疏漏之处。Lex,Yacc系列文章 http://blog.csdn.net/liwei_cmg/category/207528.aspx>
二、示例全代码
本示例包括四个文件
node.h(头文件),lexya_e.l(lex文件),lexya_e.y(yacc文件),parser.c(外部分析文件)
--------------------------------------
A.头文件 node.h
/* 定义树结点的权举类型 */
typedef enum { TYPE_CONTENT, TYPE_INDEX, TYPE_OP } NodeEnum;
/* 操作符 */
typedef struct {
int name; /* 操作符名称 */
int num; /* 操作元个数 */
struct NodeTag * node[1]; /* 操作元地址 可扩展 */
} OpNode;
typedef struct NodeTag {
NodeEnum type; /* 树结点类型 */
/* Union 必须是最后一个成员 */
union {
float content; /* 内容 */
int index; /* 索引 */
OpNode op; /* 操作符对象 */
};
} Node;
struct VarIndex
{
float val;
char mark[10];
};
struct VarDefine
{
int index;
char * name;
};
#define USER_DEF_NUM 259 /* Yacc编译的保留字开始索引 */
#define MAX_VARS 100 /* 最多变量数 */
#define MAX_DEFS 20 /* 最多保留字数 */
#define MAX_BUFF_COLS 40 /* 分析语句最多行数 */
#define MAX_BUFF_ROWS 40 /* 分析语句每行最多字符数 */
extern struct VarIndex G_Var[MAX_VARS]; /* 存储的变量数组 */
extern struct VarDefine G_Def[MAX_DEFS]; /* 系统保留字变量 */
extern int G_iVarMaxIndex; /* 变量目前总数 */
extern int G_iVarCurIndex; /* 当前操作变量索引 */
extern char G_sBuff[MAX_BUFF_ROWS][MAX_BUFF_COLS]; /* 存储分析语句 */
extern int G_iBuffRowCount; /* 当前语句行数 */
extern int G_iBuffColCount; /* 当前语句列数 */
/* 是否打印调试信息的开关 */
// #define PARSE_DEBUG
--------------------------------------
B.lexya_e.l lex文件
%{
#include <stdlib.h>
#include "node.h"
#include "lexya_e.tab.h"
struct VarDefine G_Def[MAX_DEFS]; /* 存储的变量数组 */
char G_sBuff[MAX_BUFF_ROWS][MAX_BUFF_COLS]; /* 存储分析语句 */
int G_iBuffRowCount=0; /* 当前语句行数 */
int G_iBuffColCount=0; /* 当前语句列数 */
extern void add_var(char *); /* 在内存中添加变量 */
void add_buff(char *); /* 在内存中添加语句 */
void yyerror(char *);
%}
/* 使用代变量表示任意字符 */
any .
%%
#{any}*[/n] {
add_buff(yytext);
G_iBuffColCount=0;
G_iBuffRowCount++;
} /* 单行注释 */
[/n] {
G_iBuffColCount=0;
G_iBuffRowCount++;
} /* 回车 */
"for" {
yylval.index = FOR - USER_DEF_NUM;
G_Def[yylval.index].name="for";
add_buff(yytext);
return FOR;
}
"while" {
yylval.index = WHILE -USER_DEF_NUM;
G_Def[yylval.index].name="while";
add_buff(yytext);
return WHILE;
}
"if" {
yylval.index = IF - USER_DEF_NUM;
G_Def[yylval.index].name="if";
add_buff(yytext);
return IF;
}
"else" {
yylval.index = ELSE - USER_DEF_NUM;
G_Def[yylval.index].name="else";
add_buff(yytext);
return ELSE;
}
"print" {
yylval.index = PRINT -USER_DEF_NUM ;
G_Def[yylval.index].name="print";
add_buff(yytext);
return PRINT;
}
[a-zA-Z][a-zA-Z0-9]* {
add_var(yytext);
yylval.index = G_iVarCurIndex;
add_buff(yytext);
return VARIABLE;
}
[0-9]+ {
yylval.val = atof(yytext);
add_buff(yytext);
return NUMBER;
}
[0-9]*/.[0-9]+ {
yylval.val = atof(yytext);
add_buff(yytext);
return NUMBER;
}
"++" { yylval.index = ADD_T-USER_DEF_NUM; G_Def[yylval.index].name="++"; G_Def[yylval.index+1].name="++"; add_buff(yytext); return ADD_T; }
"--" { yylval.index = MUS_T-USER_DEF_NUM; G_Def[yylval.index].name="--"; G_Def[yylval.index+1].name="++"; add_buff(yytext); return MUS_T; }
">=" { yylval.index = GE - USER_DEF_NUM; G_Def[yylval.index].name=">="; add_buff(yytext); return GE;}
"<=" { yylval.index = LE - USER_DEF_NUM; G_Def[yylval.index].name="<="; add_buff(yytext); return LE;}
"==" { yylval.index = EQ - USER_DEF_NUM;