daily pastebin goal
17%
SHARE
TWEET

Untitled

a guest Mar 23rd, 2019 61 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top