Advertisement
Guest User

Untitled

a guest
Mar 23rd, 2019
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.29 KB | None | 0 0
  1. package java2scala.homeworks
  2.  
  3. import java2scala.homeworks.CharAutomata.{And, Const, Or}
  4.  
  5. trait CharAutomata[+A] {
  6.  
  7. /** потребить один символ и перейти в следующее состояние */
  8. def consume(char: Char): CharAutomata[A]
  9.  
  10. /** получить текущий результат, если это конец строки */
  11. def result: Either[String, A]
  12.  
  13. /** потребить строку символ за символом */
  14. def apply(source: String): Either[String, A] = consume(source.head) match {
  15. case e: Error => e.result
  16. case c: Const[A] => c.result
  17. case a: CharAutomata[_] if source.tail.nonEmpty => a(source.tail)
  18. case a: CharAutomata[_] => a.result
  19. }
  20.  
  21. /** создать автомат, который запустит оба автомата
  22. * и если первый вернёт ошибку, вернёт результат второго
  23. */
  24. def or[B](auto: CharAutomata[B]): CharAutomata[Either[A, B]] = new Or(this, auto)
  25.  
  26. /** создать автомат, который запустит оба автомата
  27. * вернёт результаты обоих, если оба вернут успешный результат
  28. * и вернёт ошибку, если вернёт ошибку хотя бы один
  29. */
  30. def and[B](auto: CharAutomata[B]): CharAutomata[(A, B)] = new And(this, auto)
  31. }
  32.  
  33. object CharAutomata {
  34.  
  35. /** создаёт автомат, всегда результирующий с ошибкой
  36. * с заданным текстом message
  37. */
  38. def error(message: String): CharAutomata[Nothing] = new Error(message)
  39.  
  40. /** создаёт автомат, всегда успешно результирующий
  41. * с заданным значением `value`
  42. */
  43. def const[A](value: A): CharAutomata[A] = new Const[A](value)
  44.  
  45. /** создаёт автомат, возвращающий
  46. * первое вхождение строчки `substring`
  47. * или ошибкой
  48. */
  49. def find(substring: String): CharAutomata[Int] = new Find(substring)
  50.  
  51. /** создаёт автомат, определяющий является ли строчка,
  52. * если исключить из неё все символы, кроме `'('` и `')'`
  53. * корректной скобочной последовательностью */
  54. def balance: CharAutomata[Unit] = new ParenBalance
  55.  
  56. /** создаёт автомат, ищущий первое число, из цифр подряд
  57. * и возвращающий результат в качестве BigInt либо 0
  58. */
  59. def parseInt: CharAutomata[BigInt] = new ParseInteger
  60.  
  61. /** класс для реализации метода `error` */
  62. class Error(string: String) extends CharAutomata[Nothing] {
  63. def consume(char: Char): CharAutomata[Nothing] = this
  64.  
  65. def result: Either[String, Nothing] = Left(string)
  66. }
  67.  
  68. /** класс для реализации метода `const` */
  69. class Const[A] private[CharAutomata] (value: A) extends CharAutomata[A] {
  70. def consume(char: Char): CharAutomata[A] = this
  71.  
  72. def result: Either[String, A] = Right(value)
  73. }
  74.  
  75. /** класс для реализации метода `find` */
  76. class Find private[CharAutomata] (substring: String, nextSubstrIndex: Int, readChars: Int) extends CharAutomata[Int] {
  77. def this(substring: String) = this(substring, 0, 0)
  78. def consume(char: Char): CharAutomata[Int] = {
  79. if (substring.isEmpty)
  80. const(0)
  81. else if (char == substring(nextSubstrIndex)) {
  82. if (nextSubstrIndex == substring.length - 1)
  83. const(readChars + 1 - substring.length)
  84. else
  85. new Find(substring, nextSubstrIndex + 1, readChars + 1)
  86. } else
  87. new Find(substring, 0, readChars + 1)
  88. }
  89.  
  90. def result: Either[String, Int] =
  91. if (nextSubstrIndex == substring.length)
  92. Right(readChars - nextSubstrIndex)
  93. else
  94. Left(s"Failed to find substring $substring in input sequence")
  95. }
  96.  
  97. /** класс для реализации метода `balance` */
  98. class ParenBalance private[CharAutomata] (openedStack: Int) extends CharAutomata[Unit] {
  99. def this() = this(0)
  100. def consume(char: Char): CharAutomata[Unit] = char match {
  101. case '(' => new ParenBalance(openedStack + 1)
  102. case ')' if openedStack > 0 => new ParenBalance(openedStack - 1)
  103. case ')' => error("Closing bracket on zero balance occured")
  104. case _ => this
  105. }
  106.  
  107. def result: Either[String, Unit] =
  108. if (openedStack == 0)
  109. Right(())
  110. else
  111. Left(s"Brackets are not balanced in input sequence. Stopped on balance = $openedStack")
  112. }
  113.  
  114. /** класс для реализации метода `parseInt` */
  115. class ParseInteger private[CharAutomata] (accum: BigInt) extends CharAutomata[BigInt] {
  116. def this() = this(0)
  117.  
  118. def consume(char: Char): CharAutomata[BigInt] = {
  119. if (char.isDigit)
  120. new ParseInteger(accum * 10 + char.asDigit)
  121. else if (accum != 0)
  122. const[BigInt](accum)
  123. else
  124. this
  125. }
  126.  
  127. def result: Either[String, BigInt] = Right(accum)
  128. }
  129.  
  130. /** класс для реализации метода `and` */
  131. class And[A, B] private[CharAutomata] (autoA: CharAutomata[A], autoB: CharAutomata[B]) extends CharAutomata[(A, B)] {
  132. def consume(char: Char): CharAutomata[(A, B)] = new And(autoA.consume(char), autoB.consume(char))
  133.  
  134. def result: Either[String, (A, B)] = (autoA.result, autoB.result) match {
  135. case (Right(a), Right(b)) => Right(a, b)
  136. case (Left(a), _) => Left(a)
  137. case (_, Left(b)) => Left(b)
  138. }
  139.  
  140. }
  141.  
  142. /** класс для реализации метода `or` */
  143. class Or[A, B] private[CharAutomata] (autoA: CharAutomata[A], autoB: CharAutomata[B]) extends CharAutomata[Either[A, B]] {
  144. def consume(char: Char): CharAutomata[Either[A, B]] = new Or(autoA.consume(char), autoB.consume(char))
  145.  
  146. def result: Either[String, Either[A, B]] = (autoA.result, autoB.result) match {
  147. case (Right(a), _) => Right(Left(a))
  148. case (Left(_), Right(b)) => Right(Right(b))
  149. case (Left(a), Left(b)) => Left(s"Both automatas failed. 'A': '$a', 'B': '$b'")
  150. }
  151. }
  152. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement