0

私はシェーディングエンジン用のコンパイラを書いていますが、ステートメントの解析部分に到達するまで、すべてが正常に機能していました。

クラスで定義された抽象構文ツリーを使用して、すべての作業を実行しました(タイプチェックと中間コード生成を簡素化するため)。したがって、祖先クラスASTNodeと、、などのすべての子孫クラスがありASTFloatます。ASTExpressionASTIdentifier

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

問題は、アイテムがステートメントのブロックごとに1回だけ初期化される必要があるということですが、それを行う方法がわかりません。使用は私が試したハックですが、それまでの内容が含まれている可能性がif ($$ == null)あるため、機能しません。yylval

バイソンを使用してこの種の状況を処理するための通常の/最良の方法はどれですか?

4

3 に答える 3

1

ステートメントのリストではなく縮退ツリーを生成することで、この問題を解決しました。したがって、関連するクラス オブジェクトは次のとおりです。

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

実際、これは左再帰であり、スタックを乱雑にすることなく、ステートメントをできるだけ早く削減できます。私の言語に関係する他の種類の「シンボルのリスト」についても同じアプローチに従いました..

于 2009-11-05T21:29:04.283 に答える
1

yacc で左再帰規則を好む理由はさまざまですが、その 1 つは、入力のできるだけ早い段階で削減できることです。

いずれにせよ、それを行うときは、次のようなパターンを使用できます。

statements:                { $$ = new ... }
    | statements statement { /* now $1 and $2 do just what you want */ }
    ;
于 2009-11-05T02:05:54.167 に答える
0

次のような拡張文法を試してください。

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

これが役立つかどうかはわかりません。

于 2009-11-01T16:31:08.977 に答える