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

Scala example source code file (SeqRule.scala)

This example Scala source code file (SeqRule.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Scala tags/keywords

a, b, b, error, failure, in, rule, rule, s, success, x, x, x2, x2

The Scala SeqRule.scala 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

/** 
 * A workaround for the difficulties of dealing with
 * a contravariant 'In' parameter type...
 */
class InRule[In, +Out, +A, +X](rule : Rule[In, Out, A, X]) {
  
  def mapRule[Out2, B, Y](f : Result[Out, A, X] => In => Result[Out2, B, Y]) : Rule[In, Out2, B, Y] = rule.factory.rule { 
    in : In => f(rule(in))(in)
  }

  /** Creates a rule that succeeds only if the original rule would fail on the given context. */
  def unary_! : Rule[In, In, Unit, Nothing] = mapRule { 
    case Success(_, _) => in : In => Failure
    case _ => in : In => Success(in, ())
  }

  /** Creates a rule that succeeds if the original rule succeeds, but returns the original input. */
  def & : Rule[In, In, A, X] = mapRule {
    case Success(_, a) => in : In => Success(in, a)
    case Failure => in : In => Failure
    case Error(x) => in : In => Error(x)
  }
}

class SeqRule[S, +A, +X](rule : Rule[S, S, A, X]) {
  import rule.factory._

  def ? = rule mapRule { 
    case Success(out, a) => in : S => Success(out, Some(a))
    case Failure => in : S => Success(in, None)
    case Error(x) => in : S => Error(x)
  }
  
  /** Creates a rule that always succeeds with a Boolean value.  
   *  Value is 'true' if this rule succeeds, 'false' otherwise */
  def -? = ? map { _ isDefined }
        
  def * = from[S] { 
    // tail-recursive function with reverse list accumulator
    def rep(in : S, acc : List[A]) : Result[S, List[A], X] = rule(in) match {
       case Success(out, a) => rep(out, a :: acc)
       case Failure => Success(in, acc.reverse)
       case err : Error[_] => err
    }
    in => rep(in, Nil)
  }
  
  def + = rule ~++ *
    
  def ~>?[B >: A, X2 >: X](f : => Rule[S, S, B => B, X2]) = for (a <- rule; fs <- f?) yield fs.foldLeft[B](a) { (b, f) => f(b) }
  
  def ~>*[B >: A, X2 >: X](f : => Rule[S, S, B => B, X2]) = for (a <- rule; fs <- f*) yield fs.foldLeft[B](a) { (b, f) => f(b) }
    
  def ~*~[B >: A, X2 >: X](join : => Rule[S, S, (B, B) => B, X2]) = {
    this ~>* (for (f <- join; a <- rule) yield f(_ : B, a))
  }
  
  /** Repeats this rule one or more times with a separator (which is discarded) */
  def +/[X2 >: X](sep : => Rule[S, S, Any, X2]) = rule ~++ (sep -~ rule *)

  /** Repeats this rule zero or more times with a separator (which is discarded) */
  def */[X2 >: X](sep : => Rule[S, S, Any, X2]) = +/(sep) | state[S].nil
  
  def *~-[Out, X2 >: X](end : => Rule[S, Out, Any, X2]) = (rule - end *) ~- end
  def +~-[Out, X2 >: X](end : => Rule[S, Out, Any, X2]) = (rule - end +) ~- end

  /** Repeats this rule num times */
  def times(num : Int) : Rule[S, S, Seq[A], X] = from[S] { 
    val result = new collection.mutable.ArraySeq[A](num)
    // more compact using HoF but written this way so it's tail-recursive
    def rep(i : Int, in : S) : Result[S, Seq[A], X] = {
      if (i == num) Success(in, result)
      else rule(in) match {
       case Success(out, a) => {
         result(i) = a
         rep(i + 1, out)
       }
       case Failure => Failure
       case err : Error[_] => err
      }
    }
    in => rep(0, in)
  }
}

Other Scala examples (source code examples)

Here is a short list of links related to this Scala SeqRule.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.