文法定義と型チェックをいっぺんにできないか?
次のプログラミング言語のパーサをつくってみよう.
class Foo { int get () { test().get() this.set() } int test() { } }
普通,構文解析にパーサジェネレータを使うが,文法を定義する支援はしてくれても,意味解析はしてくれない.せめて型があっているかどうかくらいチェックしてほしいものだ...と考えたら次のような定義をかんがえついた.
文法定義は次のようにする
文法定義 ?Prologの式* opt ^Prologの式* opt
パーサは,文法定義にマッチする文章をみつけ,しかもそれが「?Prologの式」 を充足させたら,「^Prologの式」 をデータベースに登録する.
ただし,
- 文法定義内で使われた変数は自由変数として参照可能
- ^TypeName は TypeNameクラスの新しいオブジェクトを作る
- ?TypeName は TypeNameクラスのオブジェクトを探索してあてはめる.(普通のPrologでいうと大文字ではじまる変数)
ClassDecl ::= 'class' Name MethodDecl ^DeclBy(^Class , ClassDecl) ^OwnedBy( MethodDecl , ^Class). ^NameOf (^Class, Name) MethodDecl ::= Type Name Args Block ?OwnedBy (MethodDecl, ?Class) ^DeclBy(^Method, MethodDecl) ^OwnedBy(^Method, ?Class) ^BlockOf(^Method, Block) ^NameOf (^Method, Name) ^TypeOf (^Method, Type) // Expr は Expr の要素.つまり Block内で要素Exprをみつけるたびに // OwnedBy(Expr, Block) をデータベースに追加する Block ::= '{' Expr '}' ^OwnedBy( Expr , Block). Expr ::= This | LocalVarDecl | MethodInvocation LocalVarDecl ::= Type Name ?OwnedBy(LocalVarDecl, ?Block), ^DeclBy(^LocalVar, LocalVarDecl), ^TypeOf(^LocalVar, Type), ^NameOf(^LocalVar, Name). ^InScope(^LocalVar, ?Block). This ::= 'this' ?OwnedBy(This, ?Class) ^TypeOf (This, ?Class) // ※ これはただのPrologの式 OwnedBy(?Expr, ?Class) :- OwnedBy(?Expr, ?Block) OwnedBy(?Block, ?Method) OwnedBy(?Method, ?Class). LocalVarRef ::= Name ?OwnedBy(LocalVarRef, ?Block) ?InScope(?LocalVar, ?Block) ?NameOf (?LocalVar , Name) ?TypeOf (?LocalVar, ?T). ^TypeOf (LocalVarRef, ?T). MethodInvocation ::= Name '(' Arg ')' ?OwnedBy(MethodInvocation, ?Class), ?OwnedBy(?Method, ?Class). ?NameOf (?Method, ?Name), ?TypeOf (?Method, ?T) ^TypeOf (MethodInvocation, ?T) MethodInvocation ::= Expr . Name '(' Arg[] ')' ?TypeOf(Expr, ?T), ?OwnedBy(?Method, ?T). ?NameOf (?Method, ?Name), ?TypeOf (?Method, ?RT), ^TypeOf (MethodInvocation, ?RT)