alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Scala example source code file (Rules.scala)

This example Scala source code file (Rules.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Scala source code examples by using tags.

All credit for the original source code belongs to scala-lang.org; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Scala tags/keywords

a, error, failure, in, out, result, rule, s, success, x

The Rules.scala Scala example source code

// -----------------------------------------------------------------------------
//
//  Scalax - The Scala Community Library
//  Copyright (c) 2005-8 The Scalax Project. All rights reserved.
//
//  The primary distribution site is http://scalax.scalaforge.org/
//
//  This software is released under the terms of the Revised BSD License.
//  There is NO WARRANTY.  See the file LICENSE for the full text.
//
// -----------------------------------------------------------------------------

package scala.tools.scalap
package scalax
package rules

import language.postfixOps

trait Name {
  def name: String
  override def toString = name
}

/** A factory for rules.
  *
  * @author Andrew Foggin
  *
  * Inspired by the Scala parser combinator.
  */
trait Rules {

  import scala.language.implicitConversions
  implicit def rule[In, Out, A, X](f: In => Result[Out, A, X]): Rule[In, Out, A, X] = new DefaultRule(f)
  implicit def inRule[In, Out, A, X](rule: Rule[In, Out, A, X]): InRule[In, Out, A, X] = new InRule(rule)
  implicit def seqRule[In, A, X](rule: Rule[In, In, A, X]): SeqRule[In, A, X] = new SeqRule(rule)

  trait FromRule[In] {
    def apply[Out, A, X](f: In => Result[Out, A, X]): Rule[In, Out, A, X]
  }

  def from[In] = new FromRule[In] {
    def apply[Out, A, X](f: In => Result[Out, A, X]) = rule(f)
  }

  def state[s] = new StateRules {
    type S = s
    val factory = Rules.this
  }

  def success[Out, A](out: Out, a: A) = rule { in: Any => Success(out, a) }

  def failure = rule { in: Any => Failure }

  def error[In] = rule { in: In => Error(in) }
  def error[X](err: X) = rule { in: Any => Error(err) }

  def oneOf[In, Out, A, X](rules: Rule[In, Out, A, X] *): Rule[In, Out, A, X] = new Choice[In, Out, A, X] {
    val factory = Rules.this
    val choices = rules.toList
  }

  def ruleWithName[In, Out, A, X](_name: String, f: In => Result[Out, A, X]): Rule[In, Out, A, X] with Name =
    new DefaultRule(f) with Name {
      val name = _name
    }

  class DefaultRule[In, Out, A, X](f: In => Result[Out, A, X]) extends Rule[In, Out, A, X] {
    val factory = Rules.this
    def apply(in: In) = f(in)
  }

 /** Converts a rule into a function that throws an Exception on failure. */
  def expect[In, Out, A, Any](rule: Rule[In, Out, A, Any]): In => A = (in) => rule(in) match {
    case Success(_, a) => a
    case Failure => throw new ScalaSigParserError("Unexpected failure")
    case Error(x) => throw new ScalaSigParserError("Unexpected error: " + x)
  }
}

/** A factory for rules that apply to a particular context.
  *
  * @requires S the context to which rules apply.
  *
  * @author Andrew Foggin
  *
  * Inspired by the Scala parser combinator.
  */
trait StateRules {
  type S
  type Rule[+A, +X] = rules.Rule[S, S, A, X]

  val factory: Rules
  import factory._

  def apply[A, X](f: S => Result[S, A, X]) = rule(f)

  def unit[A](a: => A) = apply { s => Success(s, a) }
  def read[A](f: S => A) = apply { s => Success(s, f(s)) }

  def get = apply { s => Success(s, s) }
  def set(s: => S) = apply { oldS => Success(s, oldS) }

  def update(f: S => S) = apply { s => Success(s, f(s)) }

  def nil = unit(Nil)
  def none = unit(None)

  /** Create a rule that identities if f(in) is true. */
  def cond(f: S => Boolean) = get filter f

  /** Create a rule that succeeds if all of the given rules succeed.
      @param rules the rules to apply in sequence.
  */
  def allOf[A, X](rules: Seq[Rule[A, X]]) = {
    def rep(in: S, rules: List[Rule[A, X]], results: List[A]): Result[S, List[A], X] = {
      rules match {
        case Nil => Success(in, results.reverse)
        case rule::tl => rule(in) match {
          case Failure => Failure
          case Error(x) => Error(x)
          case Success(out, v) => rep(out, tl, v::results)
        }
      }
    }
    in: S => rep(in, rules.toList, Nil)
  }


  /** Create a rule that succeeds with a list of all the provided rules that succeed.
      @param rules the rules to apply in sequence.
  */
  def anyOf[A, X](rules: Seq[Rule[A, X]]) = allOf(rules.map(_ ?)) ^^ { opts => opts.flatMap(x => x) }

  /** Repeatedly apply a rule from initial value until finished condition is met. */
  def repeatUntil[T, X](rule: Rule[T => T, X])(finished: T => Boolean)(initial: T) = apply {
    // more compact using HoF but written this way so it's tail-recursive
    def rep(in: S, t: T): Result[S, T, X] = {
      if (finished(t)) Success(in, t)
      else rule(in) match {
        case Success(out, f) => rep(out, f(t)) // SI-5189 f.asInstanceOf[T => T]
        case Failure => Failure
        case Error(x) => Error(x)
      }
    }
    in => rep(in, initial)
  }


}

trait RulesWithState extends Rules with StateRules {
  val factory = this
}

Other Scala source code examples

Here is a short list of links related to this Scala Rules.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.