Я пишу компилятор для механизма затенения, и каждый работал нормально, пока не достиг части синтаксического анализа операторов.
Я использовал абстрактное синтаксическое дерево , определенное с классами, для выполнения всей работы (для упрощения проверки типов и генерации промежуточного кода) .. поэтому у меня есть класс-предок ASTNode
и все нисходящие классы, такие как ASTFloat
, ASTExpression
, ASTIdentifier
и т. Д.
В .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?