~ubuntu-branches/debian/experimental/json4s/experimental

« back to all changes in this revision

Viewing changes to scalap/src/main/scala/org/json4s/scalap/SeqRule.scala

  • Committer: Package Import Robot
  • Author(s): Frédéric Bonnard
  • Date: 2017-05-24 16:23:52 UTC
  • Revision ID: package-import@ubuntu.com-20170524162352-k7k8cj8u88wupw4b
Tags: upstream-3.5.0
Import upstream version 3.5.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -----------------------------------------------------------------------------
 
2
//
 
3
//  Scalax - The Scala Community Library
 
4
//  Copyright (c) 2005-8 The Scalax Project. All rights reserved.
 
5
//
 
6
//  The primary distribution site is http://scalax.scalaforge.org/
 
7
//
 
8
//  This software is released under the terms of the Revised BSD License.
 
9
//  There is NO WARRANTY.  See the file LICENSE for the full text.
 
10
//
 
11
// -----------------------------------------------------------------------------
 
12
 
 
13
package org.json4s.scalap
 
14
 
 
15
import language.postfixOps
 
16
 
 
17
/**
 
18
 * A workaround for the difficulties of dealing with
 
19
 * a contravariant 'In' parameter type...
 
20
 */
 
21
class InRule[In, +Out, +A, +X](rule: Rule[In, Out, A, X]) {
 
22
 
 
23
  def mapRule[Out2, B, Y](f: Result[Out, A, X] => In => Result[Out2, B, Y]): Rule[In, Out2, B, Y] = rule.factory.rule {
 
24
    in: In => f(rule(in))(in)
 
25
  }
 
26
 
 
27
  /** Creates a rule that succeeds only if the original rule would fail on the given context. */
 
28
  def unary_! : Rule[In, In, Unit, Nothing] = mapRule {
 
29
    case Success(_, _) => in: In => Failure
 
30
    case _ => in: In => Success(in, ())
 
31
  }
 
32
 
 
33
  /** Creates a rule that succeeds if the original rule succeeds, but returns the original input. */
 
34
  def & : Rule[In, In, A, X] = mapRule {
 
35
    case Success(_, a) => in: In => Success(in, a)
 
36
    case Failure => in: In => Failure
 
37
    case Error(x) => in: In => Error(x)
 
38
  }
 
39
}
 
40
 
 
41
class SeqRule[S, +A, +X](rule: Rule[S, S, A, X]) {
 
42
  import rule.factory._
 
43
 
 
44
  def ? = rule mapRule {
 
45
    case Success(out, a) => in: S => Success(out, Some(a))
 
46
    case Failure => in: S => Success(in, None)
 
47
    case Error(x) => in: S => Error(x)
 
48
  }
 
49
 
 
50
  /** Creates a rule that always succeeds with a Boolean value.
 
51
   *  Value is 'true' if this rule succeeds, 'false' otherwise */
 
52
  def -? = ? map { _ isDefined }
 
53
 
 
54
  def * = from[S] {
 
55
    // tail-recursive function with reverse list accumulator
 
56
    def rep(in: S, acc: List[A]): Result[S, List[A], X] = rule(in) match {
 
57
       case Success(out, a) => rep(out, a :: acc)
 
58
       case Failure => Success(in, acc.reverse)
 
59
       case err: Error[_] => err
 
60
    }
 
61
    in => rep(in, Nil)
 
62
  }
 
63
 
 
64
  def + = rule ~++ *
 
65
 
 
66
  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) }
 
67
 
 
68
  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) }
 
69
 
 
70
  def ~*~[B >: A, X2 >: X](join: => Rule[S, S, (B, B) => B, X2]) = {
 
71
    this ~>* (for (f <- join; a <- rule) yield f(_: B, a))
 
72
  }
 
73
 
 
74
  /** Repeats this rule one or more times with a separator (which is discarded) */
 
75
  def +/[X2 >: X](sep: => Rule[S, S, Any, X2]) = rule ~++ (sep -~ rule *)
 
76
 
 
77
  /** Repeats this rule zero or more times with a separator (which is discarded) */
 
78
  def */[X2 >: X](sep: => Rule[S, S, Any, X2]) = +/(sep) | state[S].nil
 
79
 
 
80
  def *~-[Out, X2 >: X](end: => Rule[S, Out, Any, X2]) = (rule - end *) ~- end
 
81
  def +~-[Out, X2 >: X](end: => Rule[S, Out, Any, X2]) = (rule - end +) ~- end
 
82
 
 
83
  /** Repeats this rule num times */
 
84
  def times(num: Int): Rule[S, S, Seq[A], X] = from[S] {
 
85
    val result = new scala.collection.mutable.ArraySeq[A](num)
 
86
    // more compact using HoF but written this way so it's tail-recursive
 
87
    def rep(i: Int, in: S): Result[S, Seq[A], X] = {
 
88
      if (i == num) Success(in, result)
 
89
      else rule(in) match {
 
90
       case Success(out, a) => {
 
91
         result(i) = a
 
92
         rep(i + 1, out)
 
93
       }
 
94
       case Failure => Failure
 
95
       case err: Error[_] => err
 
96
      }
 
97
    }
 
98
    in => rep(0, in)
 
99
  }
 
100
}
 
101