summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/scalap/scalax/rules/Input.scala
blob: af4ac3946429d5e6064965613673a585b097f065 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// -----------------------------------------------------------------------------
//
//  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.scalax.rules

trait Input[+A] extends Iterable[A] {

  def next : Result[Input[A], A, Nothing]
  def index : Int

  def elements = new Iterator[A] {
    private var input : Input[A] = Input.this
    private var result = input.next

    def hasNext = result != Failure
    def next = {
      val Success(input, value) = result
      this.input = input
      this.result = input.next
      value
    }
  }
}


class ArrayInput[A](val array : Array[A], val index : Int) extends Input[A] {
  def this(array : Array[A]) = this(array, 0)

  lazy val next : Result[ArrayInput[A], A, Nothing] = if (index >= array.length) Failure
      else Success(new ArrayInput[A](array, index + 1), array(index))

  override lazy val toString = elements.mkString("\"", "", "\"")
}


class IterableInput[A](iterator : Iterator[A], val index : Int) extends Input[A] {
  def this(iterable : Iterable[A]) = this(iterable.elements, 0)

  lazy val next : Result[IterableInput[A], A, Nothing] = if (!iterator.hasNext) Failure
      else Success(new IterableInput(iterator, index + 1), iterator.next)

  override lazy val toString = elements.mkString("\"", "", "\"")
}


/** View one type of input as another based on a transformation rule */
class View[A, B](
    transform : Input[A] => Result[Input[A], B, Nothing],
    val input : Input[A],
    val index : Int)
    extends Input[B] {

  def next : Result[Input[B], B, Nothing] = transform(input) match {
    case Success(context, b) => Success(new View(transform, context, index + 1), b)
    case _ => Failure
  }
}