|
|
最近需要学习lex和yacc,尝试着写了一些文件来编译,开始比较简单的还可以,但是后面复杂了一点点就不行了,我现在作的一个练习是这样的,成对的读入 父-子 节点对描述,把他们连接起来,构成一颗树,但是老是失败,希望大家看看,帮我分析一下原因。先谢谢大家了。
思路是:读入节点对,如2 1 1 9 2 3
则构成的树是以2为根,1 3 为其儿子节点,9为2的儿子的一棵树。
使用 lex tree.l
yacc -d tree.y后,需要手工把y.tab.c 中的define YYSTYPE string 拷贝到y.tab.h中,
编译后总是显示错误:
/tmp/ccEDUIuE.o(.bss+0x0): multiple definition of `treeIndex'
/tmp/ccJnHUxB.o(.bss+0x0): first defined here
/tmp/ccpIcrmv.o(.bss+0x30): multiple definition of `treeIndex'
/tmp/ccJnHUxB.o(.bss+0x0): first defined here
collect2: ld returned 1 exit status
希望大家看看我的问题,帮我解答
下面是我的几个文件:
tree.l lex文件
tree.y yacc文件
tree.h 头文件包含和函数声明,
tree.c 头文件实现
/////////////////////
tree.l:
%{
#include "y.tab.h"
void yyerror(char*);
extern YYSTYPE yylval;
%}
char [a-zA-Z\_]
num [0-9]
%%
{char}[{num}|{char}]+ { yylval = yytext;return NAME; }
[ \n\t]+ /*ignore blanks*/;
%%
int yywrap()
{ return 1; }
/////////////////////
tree.y:
%{
#include "tree.h"
#include "y.tab.h"
#define YYSTYPE string
void yyerror(char*);
int yyparse();
int yylex();
void traverseTree(Tree T);
void deleteTree(Tree T);
void addPair(const string P,const string C);
%}
%token NAME
%%
tree : pairs;
pairs : pairs pair
| pair;
pair : NAME NAME
{
addPair($1,$2);
}
%%
extern FILE* yyin;
int main(int args,char* argv[])
{
if(NULL == (yyin = fopen(argv[1],"rt")))
{
exit(1);
}
yyparse();
for(treeMap::iterator p = treeIndex.begin();p != treeIndex.end(); p++)
{
if(p->second->root) traverseTree(p->second);
}
treeIndex.clear();
return 1;
}
void yyerror(const char* err)
{
cout<<err<<endl;
}
/////////////////////
tree.h:
#ifndef TREE_HEADER
#define TREE_HEADER
#pragma warning(disable:4786)
#include<iostream>
#include<string>
#include<map>
using namespace std;
struct treeNode{
string name;
bool root;
treeNode* son;
treeNode* sibling;
treeNode(const string str,bool r): name(str),son(0),sibling(0),root(r){}
};
typedef treeNode* Tree;
typedef map< string, Tree> treeMap;
treeMap treeIndex;
void traverseTree(Tree T);
void deleteTree(Tree T);
void addPair(const string P,const string C);
#endif
/////////////////////
tree.c
/*
采用儿子/兄弟表示法,构造一颗多杈树
*/
#include "tree.h"
void traverseTree(Tree T)
{
if(!T) return ;
if(T->son)
{
traverseTree(T->son);
}
cout<<T->name<<" ";
if(T->sibling)
{
traverseTree(T->sibling);
}
}
void deleteTree(Tree T)
{
if(!T) return ;
if(T->son)
{
deleteTree(T->son);
}
if(T->sibling)
{
deleteTree(T->sibling);
}
delete T;
}
void addPair(const string P,const string C)
{/*添加一对连接到树中去,其中P代表父亲节点的名字,C代表子节点的名字,
treeIndex的作用是记录每个名字指向的节点。
*/
if(NULL == treeIndex[P])
{
Tree temp = new treeNode(C,1);
treeIndex[C] = temp;
}
if(NULL == treeIndex[C])
{
Tree temp = new treeNode(C,0);
treeIndex[C] = temp;
}
if(treeIndex[C]->root)/*若节点是子树的根,去掉标记*/
{
treeIndex[C]->root = false;
}
if(treeIndex[P]->son)
{
Tree temp = treeIndex[P]->son;
while(temp->sibling)
{
temp = temp->sibling;
}
temp->sibling = treeIndex[C];
return ;
}
else
{
treeIndex[P]->son = treeIndex[C];
}
} |
|