我正在写一个编译器的着色引擎,每工作得很好,直到我达到解析一部分的论述。

我使用的抽象语法树与类来完成所有的工作中(为了简化类型检查和中间代码生成)中所定义..所以我有一个祖先类ASTNode和所有降序类,如ASTFloatASTExpressionASTIdentifier等..

.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); }

和它的工作原理相当不错,但后来我想产生一个范围的语句(例如一个身体的如果的声明)中这样说:我已经使用了类ASTStatements其中有一个列表ASTNode*必须由解析器与遇到的每个语句被填充。

因此,办法是与此类似:

statements:
statement { if ($$ == null) $$ = new ASTStatements(); ((ASTStatements*)$$)->addStatement($1); } statements { $$->generateASM(); }
;

的问题是,该项目应每个语句块只初始化一次,但我不知道该怎么做。使用if ($$ == null)被一劈我想,但它不工作,因为yylval可以包含任何到这一点。

这是处理这种使用野牛情况正常/最佳方式是什么?

有帮助吗?

解决方案 3

我通过产生不是语句列表,但退化的树来解决这个问题。所以涉及的类对象是:

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); }

和确实这是左递归的,从而允许在不弄乱堆栈尽快减小语句。我跟任何其他种类的“符号列表”涉及我的语言同样的方法..

其他提示

尝试增强语法如下所示:

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 */ }
    ;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top