2

Kiama で「コミットされた選択」操作を実装しようとしています (同様の方法で機能する他の機能と共に)。

サブタームの 1 つが正常に書き直せる場合は、タームを書き直したいです (いずれかのブランチを開始すると、コミットされるという考えです)。

現在、私は次のようにすることができます:

import org.kiama.rewriting.Rewriter
import org.junit.Test

case class B(l:L,r:L)
case class L(s:String)
class RewriteExperiment extends Rewriter {
  def r1 = rule {
    case L(l) if l.s == "X" => L("Did stuff")
  }

  def r2 = strategy {
    case B(l,r) => r1(l) match {
      case Some(x:L) => Some(B(x,"Avoided"))
      case _ => None
    }
  }

  implicit def s2l(s:String) : L = L(s)
}

class RewriteTest extends RewriteExperiment {
  @Test
  def testPruning : Unit = {
    println( rewrite(r2)(B("P","b")) )
    println( rewrite(r2)(B("X","b")) )
  }
}

したがって、r2 は、r1 を最初のサブタームに正常に適用できる場合にのみ起動します。

これはあまりキアマっぽい感じがしません。合同を使用する必要があると感じていますが、ドキュメントからどのように機能するかわかりません。

これを行うためのよりエレガントでキアマイ風の方法を提案できる人はいますか?

4

1 に答える 1

3

合同は 1 つの方法ですが、残念ながら Kiama では定型文が必要です。その方向に進みたい場合は、Kiama の lambda2 の例を参照してください。AST.scala はツリー ノード タイプの合同を定義し、ParLazySubst.scala などのファイルはそれらを使用して戦略を定義します。たとえば、 ではApp (s, id)Appは合同であり、 s がノードの最初の子で成功した場合、App (s, id)戦略はAppノードで成功します (idは恒等戦略です)。

child別の方法は、単一の子の一般的な合同のようなものである whichを使用することです。この場合、操作する子をその番号を指定して指定します。(代わりに、それがどの子かわからない場合、または複数の子を操作したい場合はall、 、one、またはを使用できますsome。)

たとえば、以下は、上記で行っていることを行うためのより明確な方法だと思います。

  def r1 =
    rule {
      case L (l) if l.s == "X" => L ("Did stuff")
    }

  def r2 =
    rule {
      case B (l, r) => B (l, "Avoided")
    }

  val r3 = (child (1, r1)) <* r2

次に、r3 を使用します。

子 (...) 戦略は元の入力項で動作することに注意してください。そのため、通常の順序付け (<*) を使用して、r2 をその項にも適用するかどうかを決定できます。r2 は r1 について何も知る必要がないため、このソリューションはより構成可能です。

于 2013-04-08T10:38:06.067 に答える