我在学解析,野牛和莱克斯。我正在寻找一个清晰完整的教程/示例,它演示了以下所有内容:
来自字符串的抽象语法Tree.
我已经找到了多个示例和教程,但每个示例和教程通常只满足上述几个需求。到目前为止,我最好的教程是John在Oreilly书中的第3-2章-它有AST;不过,所有的C都只满足上面的Re_1。我欢迎推荐一些很好的例子/教程、现实生活中的开源项目。例如,我看到了MySql .yy文件--写得很好,但对于像我这样的初学者来说太大/太复杂了。
发布于 2012-06-14 00:30:27
最后,我结合了几个例子来得到我想要的东西。前两个例子来自约翰莱文的书野牛和挠曲(第二版),ISBN-10: 0596155972。另一个是来自php编译器的网站,不幸的是,在2017-02-28年间,该网站已经不复存在。我把链接放在这里,以防网站被归档: www.phpcompiler.org/articles/reentrantparser.html
谢谢阿德里安,这是一个存档版本(截止到2017-03-02):
http://web.archive.org/web/20120520150851/http://www.phpcompiler.org/articles/reentrantparser.html
发布于 2012-06-14 00:03:05
首先,我想说C++语法对于Lex/Bison来说太复杂了。这里的问题主要是语法冲突。不可能编写没有它们的C++语法。C++标准明确地说明了这一点,并包含了一些关于如何解决这些问题的指导方针。
没有解决语法冲突的通用解决方案。特别是,C++语法冲突的解决需要对已经定义的标识符有详细的了解。这意味着您需要拥有更大一部分的C++前端。仅仅有语法是不够的。
然而,建立AST是可能的。看看一个小的示例程序。
class HashEntry
{
private:
int key;
int value;
public:
HashEntry(int key, int value)
{
this->key = key;
this->value = value;
}
int getKey() { return key; }
int getValue() { return value; }
};
const int TABLE_SIZE = 128;
class HashMap
{
private:
HashEntry **table;
public:
HashMap()
{
table = new HashEntry*[TABLE_SIZE];
for (int i = 0; i < TABLE_SIZE; i++)
table[i] = NULL;
}
int get(int key)
{
int hash = (key % TABLE_SIZE);
while (table[hash] != NULL && table[hash]->getKey() != key)
hash = (hash + 1) % TABLE_SIZE;
if (table[hash] == NULL)
return -1;
else
return table[hash]->getValue();
}
void put(int key, int value)
{
int hash = (key % TABLE_SIZE);
while (table[hash] != NULL && table[hash]->getKey() != key)
hash = (hash + 1) % TABLE_SIZE;
if (table[hash] != NULL)
delete table[hash];
table[hash] = new HashEntry(key, value);
}
~HashMap()
{
for (int i = 0; i < TABLE_SIZE; i++)
if (table[i] != NULL)
delete table[i];
delete[] table;
}
};
这是这个程序的AST:
这棵树被严重放大了。叶子上的黄色圆圈(很小)是终端符号,中间的绿色圆圈是非终端。中间的粉红色圆圈是TranslationUnit。这棵树有2009年节点。
https://stackoverflow.com/questions/10732932
复制相似问题