我正在学习解析,野牛和...法。我正在寻找一个明确的&完整的教程/示例演示了以下所有内容:
我找到了多个示例和教程,但每个示例和教程通常只满足上述要求中的一小部分。到目前为止,我最好的教程是来自John Levine的Oreilly一书中的第3-2章 - 它有AST;所有C虽然只满足上面的Re_1。我欢迎推荐好的示例/教程,现实生活中的开源项目。例如,我看到MySql .yy文件 - 看起来很好,但对于像我这样的初学者来说太大/太复杂。
答案 0 :(得分:4)
最后,我结合了几个例子来得到我想要的东西。前两个例子来自John Levine的关于bison& flex(第2版)的书,ISBN-10:0596155972。另一个来自phpcompiler网站,不幸的是,从2017年经常不再存在。我将链接保留在此处,以防网站存档:www.phpcompiler.org/articles/reentrantparser.html
感谢Adrien,这是一个存档版本(2017-03-02工作):
http://web.archive.org/web/20120520150851/http://www.phpcompiler.org/articles/reentrantparser.html
答案 1 :(得分:1)
首先,我想说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个节点。