Lex Yacc (三) 语法树打印
2016-05-23 12:21
363 查看
语法树打印 草木瓜(六) 源代码有百度云存盘
node.h 中有是否打印内容栈的开关treeinput
treeinputif(1>1||2>2)print(1); else if(3>1&&2>2)print(2); else print(3);
和 再识语法树 中的文件放一起
bison -d lexya_e.y
lex lexya_e.l
gcc -g -o graph lex.yy.c lexya_e.tab.c liwei.c
./graph < treeinput
./graph < input 也可以用五中的输入
liwei.c
这个文件需要与《Lex和Yacc应用方法(五).再识语法树》中提到的node.h,lexya_e.l,lexya_e.y一起编译,生成可执行文件。我这里编译的可执行文件名是graph,下文皆使用这个名称。#include <stdio.h> #include <string.h> #include "node.h" #include "lexya_e.tab.h" /* 节点最大文本宽度 */ #define MAX_NODE_TEXT_LEN 10 /* 节点最大子节点个数 */ #define MAX_SUBNODE_COUNT 5 /* 节点宽度 */ #define NODE_WIDTH 4 #define MAX_NODE_COUNT 100 /* 排序后 树结点 */ #define MAX_TREE_WIDTH 20 #define MAX_TREE_DEEP 10 /* 树结点 图信息 */ struct NodePoint { int x; /* 标准坐标X */ int y; /* 标准坐标Y */ char text[MAX_NODE_TEXT_LEN]; /* 显示内容 */ int textoffset1; int textoffset2; int parent; /* 父结点索引 */ int idx; /* 当前结点索引 */ Node * node; /* 实际内存树节点 */ int oppx; /* 相对坐标 */ int oppx_mid;/* 相对坐标中值 */ int childnum; /* 子结点个数 */ int child[MAX_SUBNODE_COUNT]; /* 子结点索引 */ }; struct NodePoint G_TreeNodePoint[MAX_NODE_COUNT]; /* 树结点全局全量 */ int G_iNodeCount; //存储树结点个数 int G_iNodeParent;//存储树的父结点 struct NodePoint * G_pTreeNodeOrder[MAX_TREE_DEEP][MAX_TREE_WIDTH]; /* 树结点按层次的排序数组 */ int G_iTreeNodeOrderCount[MAX_TREE_DEEP]; /* 每层树结点个数 */ int G_iDeepCount; /* 层次深度 */ int G_iMinNodeXValue; /* 树结点最小x值 */ int G_iGraphNum = -1; /* 图个数 */ /* 函数定义 */ void GraphNode(Node *, int, int, int); void GraphNode_Set(int, int, int, char *, Node *); void GraphNode_PrintVars(); void GraphNode_Order(); void GraphNode_Adjust(); void GraphNode_FillPos(); void GraphNode_Print(); struct NodePoint * NodeFind(struct NodePoint *, struct NodePoint *); void NodeAdjust(struct NodePoint *, int tmp); void PrintInfo(int, char *); void InitVars(); int GetOffset(int, int, int); char * itoa(int, char*); /* 供内部调用函数 */ int NodeExecute(Node *p) { G_iNodeCount = -1; G_iNodeParent = -1; G_iMinNodeXValue = 0; InitVars(); GraphNode(p, 0, 0, G_iNodeParent); GraphNode_Order(); GraphNode_PrintVars(); GraphNode_Adjust(); GraphNode_FillPos(); GraphNode_PrintVars(); GraphNode_Print(); return 0; } /* 主递归函数,用于填充全局变量值 */ void GraphNode(Node *p, int xoffset, int yoffset, int parent) { char sWord[MAX_NODE_TEXT_LEN]; char *sNodeText; int i; G_iNodeCount++; if (parent != -1) { G_TreeNodePoint[parent].child[G_TreeNodePoint[parent].childnum] = G_iNodeCount; G_TreeNodePoint[parent].childnum++; } switch (p->type) { case TYPE_CONTENT: sprintf (sWord, "c(%g)", p->content); sNodeText = sWord; GraphNode_Set (xoffset, yoffset, parent, sNodeText, p); break; case TYPE_INDEX: sprintf (sWord, "idx(%s)", G_Var[p->index].mark); sNodeText = sWord; GraphNode_Set (xoffset, yoffset, parent, sNodeText, p); break; case TYPE_OP: switch (p->op.name) { case WHILE: sNodeText = "while"; break; case IF: sNodeText = "if"; break; case FOR: sNodeText = "for"; break; case PRINT: sNodeText = "print"; break; case ';': sNodeText = "[;]"; break; case '=': sNodeText = "[=]"; break; case UMINUS: sNodeText = "[_]"; break; case '+': sNodeText = "[+]"; break; case '-': sNodeText = "[-]"; break; case '*': sNodeText = "[*]"; break; case '/': sNodeText = "[/]"; break; case '<': sNodeText = "[<]"; break; case '>': sNodeText = "[>]"; break; case GE: sNodeText = "[>=]"; break; case LE: sNodeText = "[<=]"; break; case NE: sNodeText = "[!=]"; break; case EQ: sNodeText = "[==]"; break; case AND: sNodeText = "[&&]"; break; case OR: sNodeText = "[||]"; break; case ADD_T: sNodeText = "[++v]"; break; case MUS_T: sNodeText = "[--v]"; break; case ADD_TT: sNodeText = "[v++]"; break; case MUS_TT: sNodeText = "[v--]"; break; } GraphNode_Set (xoffset, yoffset, parent, sNodeText, p); for (i = 0; i < p->op.num; i++) { GraphNode(p->op.node[i], GetOffset(p->op.num, i + 1, 2), yoffset + 1, GetNodeIndex(p)); } break; } } /* 树结点赋值函数 */ void GraphNode_Set(int xoffset, int yoffset, int parent, char * text, Node * p ) { int iBaseValue; if (parent <= -1) iBaseValue = 0; else iBaseValue = G_TreeNodePoint[parent].x; G_TreeNodePoint[G_iNodeCount].x = (iBaseValue + xoffset) ; G_TreeNodePoint[G_iNodeCount].y = yoffset; strcpy(G_TreeNodePoint[G_iNodeCount].text, text); iBaseValue = strlen(text); if (iBaseValue & 1) { G_TreeNodePoint[G_iNodeCount].textoffset1 = strlen(text) / 2 ; G_TreeNodePoint[G_iNodeCount].textoffset2 = strlen(text) - G_TreeNodePoint[G_iNodeCount].textoffset1 ; } else { G_TreeNodePoint[G_iNodeCount].textoffset1 = strlen(text) / 2 - 1; G_TreeNodePoint[G_iNodeCount].textoffset2 = strlen(text) - G_TreeNodePoint[G_iNodeCount].textoffset1 ; } G_TreeNodePoint[G_iNodeCount].parent = parent; G_TreeNodePoint[G_iNodeCount].idx = G_iNodeCount; G_TreeNodePoint[G_iNodeCount].node = p; G_TreeNodePoint[G_iNodeCount].oppx = 0; G_TreeNodePoint[G_iNodeCount].oppx_mid = 0; G_TreeNodePoint[G_iNodeCount].child[0] = 0; G_TreeNodePoint[G_iNodeCount].childnum = 0; /* 记录最小值 */ if (G_TreeNodePoint[G_iNodeCount].x < G_iMinNodeXValue)G_iMinNodeXValue = G_TreeNodePoint[G_iNodeCount].x; } /* 根据树结点层次排序 */ void GraphNode_Order() { int i; int iDeep; G_iDeepCount = -1; for (i = 0; i <= G_iNodeCount; i++) { G_TreeNodePoint[i].x = G_TreeNodePoint[i].x - G_iMinNodeXValue + 1; iDeep = G_TreeNodePoint[i].y; G_iTreeNodeOrderCount[iDeep]++; G_pTreeNodeOrder[iDeep][G_iTreeNodeOrderCount[iDeep]] = &G_TreeNodePoint[i]; if (iDeep > G_iDeepCount)G_iDeepCount = iDeep; } } /* 填充树结点真实坐标,相对坐标 */ void GraphNode_FillPos() { int iInt; int iBlank; int idx; int i, j; for (j = 0; j <= G_iDeepCount; j++) { iBlank = 0; for (i = 0; i <= G_iTreeNodeOrderCount[j]; i++) { idx = G_pTreeNodeOrder[j][i]->idx; if (i != 0) { iInt = (G_TreeNodePoint[idx].x - G_TreeNodePoint[G_pTreeNodeOrder[j][i - 1]->idx].x) * NODE_WIDTH ; iBlank = iInt - G_TreeNodePoint[idx].textoffset1 - G_TreeNodePoint[G_pTreeNodeOrder[j][i - 1]->idx].textoffset2; } else { iInt = (G_TreeNodePoint[idx].x) * NODE_WIDTH ; iBlank = iInt - G_TreeNodePoint[idx].textoffset1; } G_TreeNodePoint[idx].oppx = iInt ; G_TreeNodePoint[idx].oppx_mid = iBlank ; } } } /* 调整树结点位置 */ void GraphNode_Adjust() { int i, j; int tmp; for (i = G_iDeepCount; i >= 0; i--) for (j = 0; j <= G_iTreeNodeOrderCount[i]; j++) if (j != G_iTreeNodeOrderCount[i]) { if (j == 0) { tmp = G_pTreeNodeOrder[i][j]->textoffset1 / NODE_WIDTH ; if (tmp >= 1) NodeAdjust(NodeFind(G_pTreeNodeOrder[i][j], G_pTreeNodeOrder[i][j + 1]), tmp); } tmp = G_pTreeNodeOrder[i][j]->x - G_pTreeNodeOrder[i][j + 1]->x + ( G_pTreeNodeOrder[i][j]->textoffset2 + G_pTreeNodeOrder[i][j + 1]->textoffset1 ) / NODE_WIDTH + 1; if (tmp >= 1) NodeAdjust(NodeFind(G_pTreeNodeOrder[i][j], G_pTreeNodeOrder[i][j + 1]), tmp); } } /* 查找需要调整的子树的根结点 struct NodePoint * NodeFind(struct NodePoint * p) { while(p->parent!=-1 && G_TreeNodePoint[p->parent].child[0]==p->idx) { p=&G_TreeNodePoint[p->parent]; } return p; } */ /* 查找需要调整的子树的根结点 */ struct NodePoint * NodeFind(struct NodePoint * p1, struct NodePoint * p2) { while (p2->parent != -1 && p1->parent != p2->parent) { p1 = &G_TreeNodePoint[p1->parent]; p2 = &G_TreeNodePoint[p2->parent]; } return p2; } /* 递归调整坐标 */ void NodeAdjust(struct NodePoint * p, int tmp) { int i; if (p->childnum == 0) p->x = p->x + tmp; else { p->x = p->x + tmp; for (i = 0; i <= p->childnum - 1; i++) NodeAdjust(&G_TreeNodePoint[p->child[i]], tmp); } } /* 打印内存变量 */ void GraphNode_PrintVars() { printf("\n"); int i, j; for (i = 0; i <= G_iNodeCount; i++) { printf("ID:%2d x:%2d y:%2d txt:%6s ofs:%d/%d rx:%2d b:%2d pa:%2d num:%2d child:", i, G_TreeNodePoint[i].x, G_TreeNodePoint[i].y, G_TreeNodePoint[i].text, G_TreeNodePoint[i].textoffset1, G_TreeNodePoint[i].textoffset2, G_TreeNodePoint[i].oppx, G_TreeNodePoint[i].oppx_mid, G_TreeNodePoint[i].parent, G_TreeNodePoint[i].childnum ); for (j = 0; j <= G_TreeNodePoint[i].childnum - 1; j++) printf("%d ", G_TreeNodePoint[i].child[j]); printf("\n"); } printf("\n"); } /* 打印语法树 */ void GraphNode_Print() { G_iGraphNum++; printf("<Graph %d>\n", G_iGraphNum); int idx; int i, j; for (j = 0; j <= G_iDeepCount; j++) { /* 打印首行结点 [] */ for (i = 0; i <= G_iTreeNodeOrderCount[j]; i++) { idx = G_pTreeNodeOrder[j][i]->idx; PrintInfo( G_TreeNodePoint[idx].oppx_mid , G_TreeNodePoint[idx].text); } printf("\n"); if (j == G_iDeepCount)return; /* 结束 */ /* 打印第二行分隔线 | */ int iHave = 0; for (i = 0; i <= G_iTreeNodeOrderCount[j]; i++) { idx = G_pTreeNodeOrder[j][i]->idx; if (G_pTreeNodeOrder[j][i]->childnum) { if (iHave == 0) PrintInfo( G_TreeNodePoint[idx].oppx , "|"); else PrintInfo( G_TreeNodePoint[idx].oppx - 1 , "|"); iHave = 1; } else PrintInfo( G_TreeNodePoint[idx].oppx , ""); } printf("\n"); /* 打印第三行连接线 ------ */ for (i = 0; i <= G_iTreeNodeOrderCount[j + 1]; i++) { idx = G_pTreeNodeOrder[j + 1][i]->idx; int k; if (i != 0 && G_pTreeNodeOrder[j + 1][i]->parent == G_pTreeNodeOrder[j + 1][i - 1]->parent) { for (k = 0; k <= G_pTreeNodeOrder[j + 1][i]->oppx - 2; k++) printf("-"); printf("|"); } else if (i == 0) { PrintInfo( G_TreeNodePoint[idx].oppx , "|"); } else { PrintInfo( G_TreeNodePoint[idx].oppx - 1 , "|"); } } printf("\n"); /* 打印第四行分割连接线 | */ for (i = 0; i <= G_iTreeNodeOrderCount[j + 1]; i++) { idx = G_pTreeNodeOrder[j + 1][i]->idx; if (i == 0) PrintInfo( G_TreeNodePoint[idx].oppx , "|"); else PrintInfo( G_TreeNodePoint[idx].oppx - 1 , "|"); } printf("\n"); } } /* 获取节点位移 */ int GetOffset(int count, int idx, int base) { if (count & 1) return (idx - (count + 1) / 2) * base; else return idx * base - (count + 1) * base / 2; } /* 根据节点地址获取内存索引 */ int GetNodeIndex(Node * p) { int i; for (i = G_iNodeCount; i >= 0; i--) { if (p == G_TreeNodePoint[i].node)return G_TreeNodePoint[i].idx; } } /* 初始化变量 */ void InitVars() { /* int i,j; for(j=0;j<=MAX_TREE_DEEP-1;j++) for(i=0;i<=MAX_TREE_WIDTH-1;i++) G_pTreeNodeOrder[j][i]=0; */ int i; for (i = 0; i <= MAX_TREE_DEEP - 1; i++) G_iTreeNodeOrderCount[i] = -1; } /* 打印固定信息 */ void PrintInfo(int val, char * str) { char sInt[10]; char sPrint[20]; itoa( val , sInt); strcpy(sPrint, "%"); strcat(sPrint, sInt); strcat(sPrint, "s"); printf(sPrint, ""); printf(str); } /* int 转 char */ char * itoa(int n, char *buffer) { int i = 0, j = 0; int iTemp; /* 临时int */ char cTemp; /* 临时char */ do { iTemp = n % 10; buffer[j++] = iTemp + '0'; n = n / 10; } while (n > 0); for (i = 0; i < j / 2; i++) { cTemp = buffer[i]; buffer[i] = buffer[j - i - 1]; buffer[j - i - 1] = cTemp; } buffer[j] = '\0'; return buffer; }
相关文章推荐
- 学习Spring MVC,关于注解的Spring MVC,关于控制器的Spring MVC,学习Spring,简单Spring MVC实例
- spring aop方法中通过代理工厂注入通知
- HDOJ-2196 Computer
- 微信底部滑动时图标渐变色的实现
- Error:Failed to find: com.facebook.fresco:fresco:0.7.2+
- mongodb一些使用技巧或注意事项记录
- Difference of Maven JAXB plugins
- Retrofit2 更新指南
- 持续部署单页应用的7大技巧
- swift对象存储
- ubuntu14.04安装deepinlinux相关软件
- 自定义ViewGroup——圆形排列LinearLayout
- Problem-H
- Lex Yacc (二) 语法树
- 项目4-日期时间类
- 陶哲轩实分析-第8章-无限集合
- 二分图最大匹配各种题型
- PHP中header用法小结
- 【bzoj4380】[POI2015]Myjnie
- 持续部署单页应用的7大技巧