求助,关于数据结构,Lisp表达式的数据结构!!!!!!

Clonne 2012-12-11 08:18:20
这是Lisp表达式的介绍:
Lisp的表达式是一个原子(atom)或表(list),原子(atom)是一个字母序列,如abc;表是由零个或多个表达式组成的序列,表达式之间用空格分隔开,放入一对括号中,如:
  abc
  ()
  (abc xyz)
  (a b (c) d)

我正在做一个Lisp这种表达式的文本数据类库(不做解释器,仅仅是解析这种表达式存储的文本数据,就像XMl一样)

于是我这样定义数据结构:


// lisp.h
#include <string>
#include <list>
typedef unsigned int uint;

// Lisp原子ADT
class LispAtom
{
public:
std::string m_Value;
};

class LispList;

// Lisp表达式ADT
class LispCode
{
public:
enum CodeType
{
ATOM, // 是一个原子
LIST, // 是一个表
UNDEFINE // 未定义
};

// 获取表达式类型
CodeType Type();
// 获取原子对象
LispAtom &Atom();
// 获取表对象
LispList *List();
// 设置为原子
void SetAtom();
// 设置为表
void SetList();
// 清除数据
void Clear();
public:
LispCode();
~LispCode();
private:
LispAtom m_Atom;
LispList *m_List;
CodeType m_Type;
std::list<LispList *> m_ClassPtrs;
};

// Lisp表ADT
class LispList
{
public:
// 加入表达式
bool Plus(LispCode &code);
// 移除表达式
bool Minus(uint index);
// 获取表达式
LispCode &Get(uint index);
// 表达式总数
uint Count();
// 清除所有数据
void Clear();
public:
LispList();
~LispList();
private:
std::list<LispCode> m_Codes;
};



#include "lisp.h"
bool LispList::Plus(LispCode &code)
{
m_Codes.push_back(code);
return true;
}

bool LispList::Minus(uint index)
{
if (index >= this->Count()) return false;
auto code_it = m_Codes.begin();
while (index > 0)
{
code_it++;
}
m_Codes.erase(code_it);
return true;
}

LispCode &LispList::Get(uint index)
{
assert(index < this->Count());
auto code_it = m_Codes.begin();
while (index > 0)
{
code_it++;
}
return (*code_it);
}

uint LispList::Count()
{
return m_Codes.size();
}

void LispList::Clear()
{
m_Codes.clear();
return;
}

LispList::LispList()
{
}

LispList::~LispList()
{
}

LispCode::CodeType LispCode::Type()
{
return m_Type;
}

LispAtom &LispCode::Atom()
{
assert(ATOM == this->Type());
return m_Atom;
}

LispList *LispCode::List()
{
assert(LIST == this->Type());
if (NULL == m_List) m_List = new LispList();
return m_List;
}

void LispCode::SetAtom()
{
this->Clear();
m_Type = ATOM;
return;
}

void LispCode::SetList()
{
this->Clear();
m_Type = LIST;
return;
}

void LispCode::Clear()
{
m_Type = UNDEFINE;
m_Atom.m_Value.clear();
m_List = NULL;
return;
}

LispCode::LispCode()
{
m_Type = UNDEFINE;
m_List = NULL;
}

LispCode::~LispCode()
{
this->Clear();
}


上面是我对Lisp表达式的定义,但是我怎么也无法成功的生成正确的表达式树。还有一个词法分析器(仅分离出左括号、原子、右括号),这个词法器没问题。
我用一个递归函数生成LispCode表达式树,但是怎么都不行,不是混乱的表达式就是0xfeeefeee、0xcdcdcdcd的LispList类指针。很生气,把那个递归函数删了。

所以特来求助,大家帮忙看看什么问题。是不是这个Lisp表达式数据结构本来就错误?请问如何正确的生成表达式树?


// LispToken.h
enum LispToken
{
LBRACK, // 左大括号
RBRACK, // 右大括号
ATOM // 原子
};



// lispscanner.h
class LispTokenNode
{
public:
LispToken m_Token;
// 仅原子有此值(ID名、字符串、数值、...)
std::string m_Value;
};

class LispScanner
{
public:
// 从字符串解析Lisp词法
bool Parse(const char *str);
// 获取单词节点链表
std::list<LispTokenNode> &NodeList();
// 清除所有节点数据
void Clear();
private:
std::list<LispTokenNode> m_Nodes;
};



// lispscanner.cpp

#include "lispscanner.h"

// 当字符串结束(遇到0)的时候返回False
static bool SkipWhiteChar(char **pp)
{
char *src = *pp;
while (0 != *src)
{
if ((' ' != *src) && ('\t' != *src) && ('\n' != *src) && ('\r' != *src)) break;
src++;
}
*pp = src;
return (0 != *src);
}

bool LispScanner::Parse(const char *str)
{
assert(NULL != str);
char *p = (char *)str;

LispTokenNode node;
while (0 != *p)
{
if (!SkipWhiteChar(&p)) break;
char cur_char = *p++;
// 表开始符号
if ('(' == cur_char)
{
node.m_Value.clear();
node.m_Token = LBRACK;
m_Nodes.push_back(node);
}
// 表结束符号
else if (')' == cur_char)
{
node.m_Value.clear();
node.m_Token = RBRACK;
m_Nodes.push_back(node);
}
// 原子
else
{
std::string atom_value;
while ((')' != cur_char) && (' ' != cur_char) && ('\n' != cur_char) && ('\t' != cur_char) && ('\r' != cur_char))
{
// 不正确的结束
if (0 == cur_char) return false;
atom_value.append(1, cur_char);
cur_char = *p++;
}
node.m_Value = atom_value;
node.m_Token = ATOM;
m_Nodes.push_back(node);
//
if (')' == cur_char) p--;
}
}
return true;
}

std::list<LispTokenNode> &LispScanner::NodeList()
{
return m_Nodes;
}

void LispScanner::Clear()
{
m_Nodes.clear();
return;
}



上面的就是词法分析器,是没问题的。



#include "lisp.h"
#include "lispscanner.h"

// 这个就是生成表达式树的函数
std::list<LispCode> Parse(const std::string &text)
{
LispScanner scanner;
scanner.Parse(text.c_str());
std::list<LispCode> code_list;

LispCode gen_code;
auto node_list = scanner.NodeList();
auto node_it = node_list.begin();
while (node_list.end() != node_it)
{
// GenericCodeTree就是那个递归生成表达式树的函数,不过被我删了
// 问题就是无论如何都无法正确生成表达式树
// 不是缺这个就是指针混乱
// 比如:gen_code下面有一个列表a,这个列表a下面也有一个列表b,这个列表b有一个表达式,指向gen_code...,结果就是无限循环
// if (!GenericCodeTree(node_it, node_list.end(), gen_code)) break;
// code_list.push_back(gen_code);
}
return code_list;
}

// 测试数据:
const char *lisp_text =
"(texts
(1 逃亡启动器)
(2 使用了错误的参数)
(3 登录失败)
(4 游戏启动失败)
(5 用户系统初始化系统)
)";
...全文
95 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧