2012-02-24 20 views
5

S式のリーダー(後でSchemeインタプリタとコンパイラの両方で使用する)を実装する方法を探していますが、私はASTを書くべきです)。OOPでS式を解析する正しい方法

私はSICPを読んできましたが、これはSchemeの中ではとても簡単ですが、私はOOの方法でC++でインタープリタとコンパイラを実装しようとしています。

私は学習目的でのみこれをやっているので、実際にこれを行うのが最も簡単で簡単な方法ではなく、正しいやり直しができる方法を探しています。

私は、人々がS式と容易に出力コンスセルを解析し、いくつかのSchemeの実装では、このような何かを見てきました

struct Sexpr 
    { 
    }; 

    struct Cons : public Sexpr 
    { 
    Sexpr* left; 
    Sexpr* right; 
    }; 

    struct IntAtom : Sexpr 
    { 
    int value; 
    }; 

とScheme Atomの種類ごとにSexprの1つのサブクラス、もしくは沿って何かをそれらの行。

私は確信していませんが、これは私にとってハックのようです...この作業は読者ではなく通訳者によって行われるべきではありませんか?

私が知りたいのは、これがS式を読み込む最良の(正しい)方法と考えられるのか、それともパーサー以外の通訳者の仕事なのでしょうか?パーサーはコンスセルに頼るのではなく、独自のASTを持つべきですか?

+0

私がこの権利を読んでいれば、質問は解析とはあまり関係ありません。むしろ、私はあなたが尋ねていると思う:s-expressionデータ型の最も適切な表現は何か。同意しますか? – dyoo

+0

@dyooはい、いいえ。はい、そうです、私はs式の最も適切な表現を探しています。そして、いいえ、あなたは間違っています。この質問は、明らかに解析する必要があります。私がsexprの最も適切な表現を探していただけの場合、コンスセルであることは間違いありません。しかし、私は具体的にsexprの最も適切な表現**を探しています**解析のため**。 – ivanmp

+0

cool。良い説明。次に、解析作業を区別することの1つは、ソースの位置情報の必要性です。プレーンコンスセルは元のソースからどこに来たのかを覚えていません。解析中に、ソースを指す可能性のあるエラーメッセージをサポートすることができます。解析するために他に何が必要なのでしょうか? – dyoo

答えて

3

、少なくともどこにバインドされているのか、どこから来たのか、コンパイラのパスとその他の情報が格納されています(「ラケットの構文プロパティ」を参照)。

この追加情報により、ソースへのポインタと衛生的なマクロのエラーメッセージなどが表示されます。

ここでは、単に「より多くの価値を含む」という意味で「より豊か」を意味し、価値に中立的ではないことにご注意ください。

私はTuring Tar Pitに落ちる前に--- と同じ情報を正確に表すこともできます。の表を使用してください。ポインタの比較があると仮定すると、構造体内に値を置くことと構造体を値に関連付けるテーブルを使用することの間には表現力の違いはありません。

3

あなたの構文でやや完全なものにしたい場合は、

sexpr ::= atom | sexpr sexpr 
atom ::= nil | intatom | etc. 

をサポートする必要があります。しかし、それはあなたが遭遇する最もsexprよりも一般的です。 Lisp/Schemeの中で最も簡単で最も一般的な形式のS-exprは、a、b、c、dのそれぞれが原子またはリストである(a b c d)のようなものです。ペア形式では、これは[a [b [c [d nil]]]]であり、これはコンスエントのすべての右側がリストであることを意味します。あなたはきれいなのために行くされている場合は、1つは、おそらく前後に主張することができますが、「正しい」アプローチとは何か、私の意見、あなたがアプローチで提案し、使用上

だから、あなただけ

class sexpr {}; 
class atom : sexpr {}; 
class s_list : forward_list<smart_ptr<sexpr>> {}; 
+0

回答をフォーマットできますか? – ivanmp

+0

試して、申し訳ありません:-) –

+0

問題ありません!それは私が心に留めていたことに沿ったものですが、私は2つの質問があります:1)これは現時点で(コンサセル)を心配して通訳に問題を残すべきではなく、代わりにこのようなASTを使用していますか? 2)私は何か間違っているかもしれないが、Sexprからs_listを継承するべきではないか? – ivanmp

3

を行う可能性がありますの処理のための同じデータ構造は、Lispと "コードがデータ"のマントラについて、特にquoteが実際に何を意味するのかを最もよく教えるものですそれはかなり深遠なものです)。

また、ほとんどのLisps(興味深いことに、Schemeを含まない)が伝統的に動作する方法です。

そうですね、読者にLispデータを生成させる:コンス、シンボル、Lisp番号、文字列など、ユーザーレベルのLispコードが扱うものとまったく同じもの。それは、実装の残りの部分をより簡単でより有益なものにするでしょう。

ラケット(およびいくつかの他のスキームの実装を)は、ラケットに(示すそれらに取り付けられた特性を有することができるように、構文オブジェクトの豊かな表現を使用する:フェンスのスキーム/ラケット側から追従する

+0

あなたの答えをありがとう!私の主な目標は、一般的にはコンパイラやインタープリタのほとんどを学ぶことですが、必ずしもそうではありません。なぜなら、私はこれに対する最も正しいアプローチについて疑問に思います。Schemeを選択したのは、それが(少なくともいくつかのサブセットで)始めるのはかなり簡単な言語だと思ったからです。私はそれを使って作業しました。 :)最後の行はどういう意味ですか? – ivanmp

+0

@ivanmp Lispについて知りたいのであれば、このようにするのはもっと有益なことです。はい、*有益な*は私が探していた言葉です。 :)異なるフェーズの異なるデータ構造に対処する必要がなく、フェーズを他のものに変換することなく単に渡すことができるため、インプリメンテーションもよりシンプルになります( 'quote')。一方で、特にLispではなく一般的なコンパイルについて学んでいるなら、どちらの方法でもうまくいくでしょう。 –

+1

私はこの行を意味していた:_それはまた、偶然、ほとんどのLisps(**興味深いことに、Scheme **を含めない)が伝統的に働く方法でもある。_ – ivanmp

1

どのように行われたかの例は、this c/c++ s-expr parser libraryをご覧ください。

ベース表現があるように見えます:

struct elt { 
    int type; 
    char *val; 
    struct elt *list; 
    struct elt *next; 
}; 

そして、私は彼らのドキュメントから引用:

要素がリストまたは原子のいずれかになりますので、素子構造は、タイプインジケータがありますLISTまたはVALUEのいずれかになります。型インジケータがLISTの場合、構造体メンバ "list"は、この要素によって表されるリストの先頭へのポインタになります。型インジケータがVALUEの場合、構造体メンバ "val"には、要素によって表されるアトムが文字列として格納されます。どちらの場合も、「次の」ポインタは現在のs式の次の要素を指します。

さらに、hereは、興味のある多くの言語のs-exprリーダーの他の実装の全リストです。

関連する問題