3

誰かが私に、現時点で正しいセマンティックアクションを実行できるようにするためにさらなる宣言を調べる必要がある状況に対処する方法についてのアドバイス/アイデアを教えてもらえますか?たとえば、誰かが「前方宣言」をサポートしていないプログラミング言語のインタプリタ/コンパイラを作成する場合によく知られています。例を見てみましょう:

foo(123);//<-- our parser targets here. we estimate we have a function 
         //    invocation, but we have no idea about foo declaration/prototype,
         //     so we can't be sure that "foo" takes one integer argument.   


void foo(int i){
//...
}

少なくとも2つのパスが必要であることは明らかです。まず、すべての関数宣言を解析し、関数が取る引数の量、それらの型などの必要なすべての情報を取得します。次に、関数の呼び出しを処理し、上記のように問題を解決できます。このように進む場合は、いくつかのASTトラバースメカニズム/ビジターを使用してこれらすべてのパスを実行する必要があります。この場合、ASTのトラバース/アプライビジターに対処する必要があり、パーサーに直接統合されたフェニックス構造のすべての美しさに「さようなら」と言わなければなりません。

これにどのように対処しますか?

4

3 に答える 3

3

[セマンティクスに関する2番目の回答]この特定の例はたまたま単純です。できることは、まだ宣言されていない関数に対して行われた関数呼び出しと、実際の引数タイプを記録することです。後で関数宣言に遭遇したときは、この新しい関数に(よりよく)一致する先行する関数呼び出しがあるかどうかを確認します。最後の行で関数が欠落している可能性があるため、解析の最後にのみエラーが検出されることは明らかです。しかし、その行の後、まったく一致しなかった関数呼び出しはエラーになります。

さて、問題は、これが単純なセマンティクスで機能することです。より複雑な言語(たとえば、C ++のような関数テンプレートを使用)を見ると、単純なテーブルでそのようなルックアップを実行することはできなくなります。言語構成に構造的に一致する特殊なタブが必要になります。ASTは、解析中の部分的なASTは言うまでもなく、それらにとって最適な構造ではありません。

于 2009-11-05T11:06:24.930 に答える
2

最初のパスの最後にセマンティックチェックを行う代わりに、2つのパスを実行する場合は、アクションによって呼び出されるte関数に、どのパスにあるかを認識させることができます。

[functionCall(name, args)]
[functionDef(name, args, body)]

それらはこのように定義されます(適切な精神構文ではありませんが、要点はわかります)

functionCall(string name, vector<string> args)
{
  if (!first_pass) {
    // check args for validity
    // whatever else you need to do
  }
} 

functionDef(string name, vector<string> args, ... body)
{
  if (first_pass)
    // Add function decleration to symbol table
  else
    // define function
}
于 2009-11-05T12:41:16.350 に答える
1

私はあなたが根拠のない仮定をしていると思います。たとえば、「少なくとも2つのパスが必要であることは明らかです」。いいえ、そうではありません。構文がfoo(123)としてのみ解析できるようなものである場合はfunction-name "(" expression ")"、1回のパスで十分です。

したがって、明確な構文解析のために構文を設計することをお勧めします。単独で解析できない構造は避けてください。たとえば、他の場所での宣言への依存を避けてください。

于 2009-11-05T09:10:59.410 に答える