Compiler construction 使用bison解析元素列表

Compiler construction 使用bison解析元素列表,compiler-construction,parsing,yacc,bison,Compiler Construction,Parsing,Yacc,Bison,我正在为着色引擎编写一个编译器,在到达语句解析部分之前,每个引擎都工作得很好 我使用类定义的抽象语法树来完成所有工作(以简化类型检查和中间代码生成)。。因此,我有一个祖先类ASTNode和所有降序类,如ASTFloat,asexpression,astiIdentifier等等 在.y文件中,我能够以常见的方式构建AST: nexp: T_LPAR nexp T_RPAR { $$ = $2; } | nexp OP_PLUS nexp { $$ = new ASTBExpression('+'

我正在为着色引擎编写一个编译器,在到达语句解析部分之前,每个引擎都工作得很好

我使用类定义的抽象语法树来完成所有工作(以简化类型检查和中间代码生成)。。因此,我有一个祖先类
ASTNode
和所有降序类,如
ASTFloat
asexpression
astiIdentifier
等等

.y
文件中,我能够以常见的方式构建AST:

nexp:
T_LPAR nexp T_RPAR { $$ = $2; }
| nexp OP_PLUS nexp { $$ = new ASTBExpression('+', (ASTExpression*)$1, (ASTExpression*)$3); }
| nexp OP_MINUS nexp { $$ = new ASTBExpression('-', (ASTExpression*)$1, (ASTExpression*)$3); }
| nexp OP_TIMES nexp { $$ = new ASTBExpression('*', (ASTExpression*)$1, (ASTExpression*)$3); }
它工作得很好,但我尝试以这种方式生成作用域的语句(例如if语句的主体):我使用了一个类
ASTStatements
,它有一个
ASTNode*
列表,解析器必须用遇到的每个语句填充该列表

因此,该方法与此类似:

statements:
statement { if ($$ == null) $$ = new ASTStatements(); ((ASTStatements*)$$)->addStatement($1); } statements { $$->generateASM(); }
;
问题是每个语句块只需初始化一次项,但我不知道如何初始化。使用
if($$==null)
是我尝试过的一种黑客行为,但它不起作用,因为
yylval
可以包含任何内容


使用Bison处理此类情况的正常/最佳方法是什么?

尝试以下扩充语法:

statements: statement { $$ = new ASTStatements();
                       ((ASTStatements*)$$)->addStatement($1); }      
 | statements statement { ((ASTStatements*)$$)->addStatement($2); }

不确定这是否会有帮助。

有各种各样的原因让您更喜欢yacc的左递归规则,首先,您可以在输入中尽早减少

在任何情况下,当您这样做时,您可以使用如下模式:

statements:                { $$ = new ... }
    | statements statement { /* now $1 and $2 do just what you want */ }
    ;

我不是通过生成语句列表而是通过生成一棵退化树来解决这个问题。因此,所涉及的类对象是:

ASTStatements
{
    ASTStatements *m_next;
    ASTStatement *m_statement;

    ....

    public:
        ASTStatements(ASTStatement *statement) // used for last one
        ASTStatements(ASTStatement *stat, ASTStatements *next) // used with a next one
}
按以下方式使用
.y
中的规则:

statements: /* empty */ { $$ = null; }
| statements statement { if ($1 == null) $$ = new ASTStatements($2); else $$ = new ASTStatements($2, (ASTStatements*)$1); }

事实上,这是左递归的,允许在不扰乱堆栈的情况下尽快减少语句。对于我的语言中涉及的任何其他类型的“符号列表”,我采用了相同的方法。

您有%type语句吗?如果有,等等?当然,我必须解决将ASTStatements*转换为一个包含左侧部分(ASTStatement*)和右侧部分(ASTStatements*)的类的问题。我实际上把列表变成了一棵退化树..我真的很喜欢退化树的想法。