2016-10-20 9 views
0

のような構文定義を持つ:パターンマッチング構文定義

syntax ClassDeclaration = classDecl: "class" Identifier ClassBody ; 
... 
syntax ClassBody = classBody : "{" ClassBodyDeclaration* "}" ; 

syntax ClassBodyDeclaration = ClassMemberDeclaration 
          | InstanceInitializer 
          | StaticInitializer 
          | ConstructorDeclaration 
          ; 

... 

の訪問者を使用するには、私が使用して、クラスのボディに一致するパターンにできる午前:

visit(unit) { 
    case classDecl(name, ClassBody body): { // a block "A" here } 
    ... 
} 

質問:このような状況では、 "A"ブロック内の "body"変数からクラス本体宣言のリストをどのようにパターン化できますか?私は理解しようとしましたが、私は "体"は列挙型ではないと思いました。

syntax ClassBody = classBody : "{" ClassBodyDeclaration* decls "}"; 

あなたは、インスタンスのために、リストにそれらを抽出するためにdeclList = [ d | d <- body.decls ]ようなコードを使用して、各宣言にアクセスするために理解を使用することができます。

答えて

2

最も簡単な方法は次のように、ClassBodyDeclaration*に名前を与えることです。

別の方法として、文法の変更を必要としない、Rascalの具体的な構文一致機能を使用する方法があります。あなたは、次のコードを使用して、体内の宣言を一致させることができます。

list[ClassBodyDeclaration] declList = [ ]; 

if ((ClassBody)`{ <ClassBodyDeclaration* decls> }` := body) { 
    declList = [ d | d <- decls ]; 
} 

最後に、別の応答で述べたように、あなたはラスカルは、本体内のClassBodyDeclarationのすべての出現にマッチする、深い試合を呼ぶものを行うことができます。

declList = [ d | /ClassBodyDeclaration d := body ]; 

何らかの理由で他のクラスの中にネストされたクラスを持つことができない場合は、これは問題ありません。この場合、現在のクラスの一部であるクラス本体宣言だけを取得することはできませんが、ネストしたクラスも同様です。

+0

面白いです。最後のアプローチだけが私のために働く。最初のものは次のような例外につながります:NoSuchField( "decls")、さらにyntax ClassBody = classBody: "{" ClassBodyDeclaration * decls "}"; " –

2

文法を制御できない場合は、深いマッチを使用して理解することもできます(declList = [ cbd | /ClassBodyDeclaration cbd := body])。 bodyに含まれるClassBodyDeclarationにすべて一致します。 :=は一致演算子です。

2

どのようにこのソリューションについて:

visit(unit) { 
    case classDecl(name, classBody(ClassBodyDeclaration* body)): { // a block "A" here } 
    ... 
} 

または:

visit(unit) { 
    case (ClassDecl) `class <Identifier name> { <ClassBodyDeclaration* body> }` : { 
    ... 
    } 
} 
+0

を指定した場合でも、私は抽象構文ベースのアプローチ。ちなみに、 "body"メタ変数からクラス本体の宣言をトラバースするにはどうすればよいですか? –

関連する問題