0

独自のコンパイラを開発していますが、Java 文法のパニック モードでのエラー回復設計に問題があります。

複数の解決策を考えましたが、本当の問題は次のとおりです。

バイソンC ++でそれを行うにはどうすればよいですか?

私はそれをしました:

パッケージ 2

java.lang.* をインポートします。

エラーは最初のセミコロンまで消費する必要があり、これはルールで正しく実行されます

package_rule: パッケージ エラー ';'

しかし、私がこのコードを書いた場合:

パッケージ 2

java.lang.* をインポート

class y { void method() { int m }

}

エラーを報告するために、標準コンパイラのようなパーサーから必要なもの:

パッケージの行に識別子が必要です。ない ';' 輸入指示行でパッケージの 1 つを報告します。「;」がありません int m 行で。

つまり、パッケージエラーの後に、最初のセミコロンまでトークンを消費するか、最後の行でクラスまたはインターフェイスの宣言を見つけて宣言する前に停止する必要があります。次の行の後に見つかったその他のエラーを報告します。

int m // ';' がありません

私の心の中で複数の解決策を教えてください。

4

2 に答える 2

1

さて、あなたの基本的な問題は、構文エラーからの回復をどのように試みるかということです。次のような入力シーケンスがある場合

package x import

そこにセミコロンがあったはずだと仮定したいですか、それともセミコロンの前に他の何かが詰まっていて、セミコロンに到達するまで何かを捨てるべきだと仮定したいですか?

後者はあなたが持っているものです-ルールpackage: PACKAGE error ';'はまさにそれを行います-キーワードを見たPACKAGEが、その後に続くものがルールの残りの部分と一致しない場合はいつでも、 a が表示packageされるまで入力を破棄し';'、そこから続行しようとします。

package: PACKAGE name error前者が必要な場合は、次のようなルールを使用しますPACKAGE。有効なパッケージ名のように見えるがセミコロンがない場合は、そこにセミコロンがあるかのように扱い、続行してください。

上記の両方を実行できるようにすることは非常に困難です。最も近いのは、文法を次のようにすることです。

package: PACKAGE name ';'  /* normal package decl */
       | PACKAGE name      /* missing semicolon -- treat this as a semantic error */
       | PACKAGE error ';' /* no name -- skip up to the next semicolon to recover */

ただし、この種のことは、おそらく解決が難しい文法上の競合を引き起こします。

于 2013-02-04T19:19:57.833 に答える
1

バイソン方式ではなく、C++ OOP 方式でその問題を解決してもよろしいでしょうか。

これらの種類のASTノードが定義されていると考えてください

struct BaseExpression {
    virtual std::string toIdentifier() = 0;
    // other member. remember to declare a virtual destructor
};

struct IntLiteral : BaseExpression {
    std::string toIdentifier() {
        error::toAnIdentifier();
        return "";
    }
};

struct Identifier: BaseExpression {
    std::string ident;

    explicit Identifier(std::string id) : ident(id) {}

    std::string toIdentifer() {
        return ident;
    }
};

このようにルールを定義します

%union {
    BaseExpression* expr_type;
}

%type <expr_type> simple_expr

package_expr: simple_expr
{
    $1->toIdentifer(); // thus integers or float numbers would generate errors
    // do sth with that identifer
}
;

package_expr: package_rule '.' simple_expr
{
    $3->toIdentifer(); // same trick
    // do sth with that identifer
}
;

どこsimple_exprですか

simple_expr: int_literal { return new IntLiteral; }
           | ...
           | identifier { return new Identifier(yytext); }
;
于 2013-02-04T15:57:46.280 に答える