Advertisement
PaleoCrafter

Untitled

Sep 26th, 2014
223
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.36 KB | None | 0 0
  1. import scala.collection.mutable.ListBuffer
  2.  
  3. val openMobile = '['
  4. val closeMobile = ']'
  5. val sideDelimiter = '|'
  6. val elementDelimiter = ','
  7.  
  8. trait Node
  9.  
  10. case class Mobile(children: List[Node]) extends Node
  11.  
  12. case class Leaf(weight: Double) extends Node
  13.  
  14. def parse(mobile: String): Mobile = {
  15.   var i = 0
  16.  
  17.   def parseMobile(subj: String): Mobile = {
  18.     var started = false
  19.     var right = false
  20.     val nodes = ListBuffer.empty[Node]
  21.  
  22.     while (i < subj.length) {
  23.       val c = subj.charAt(i)
  24.  
  25.       c match {
  26.         case `openMobile` =>
  27.           if (!started)
  28.             started = true
  29.           else
  30.             nodes += parseMobile(subj)
  31.         case `closeMobile` =>
  32.           if (!started)
  33.             throw new Exception("Closing mobile without opening it")
  34.           else {
  35.             i += 1
  36.             return Mobile(nodes.toList)
  37.           }
  38.         case `sideDelimiter` =>
  39.           if (!right)
  40.             right = true
  41.           else
  42.             throw new Exception("More than one side delimiter")
  43.         case `elementDelimiter` =>
  44.           if (i + 1 < subj.length) {
  45.             if (subj.charAt(i + 1) == sideDelimiter || subj.charAt(i + 1) == closeMobile)
  46.               throw new Exception("Comma at invalid position")
  47.           }
  48.           else
  49.             throw new Exception("Comma at invalid position")
  50.         case _ =>
  51.           val number = parseNumber(subj)
  52.           nodes += Leaf(if(right) number else -number)
  53.       }
  54.  
  55.       i += 1
  56.     }
  57.  
  58.     Mobile(nodes.toList)
  59.   }
  60.  
  61.   def parseNumber(subj: String): Double = {
  62.     val buffer = StringBuilder.newBuilder
  63.     var reachedDot = false
  64.     while (i < subj.length) {
  65.       subj.charAt(i) match {
  66.         case '.' =>
  67.           if (!reachedDot)
  68.             reachedDot = true
  69.           else
  70.             throw new Exception("More dots than allowed")
  71.         case `elementDelimiter` | `openMobile` | `closeMobile` | `sideDelimiter` if buffer.length > 0 =>
  72.           i -= 1
  73.           return buffer.toDouble
  74.         case c =>
  75.           if (c.isDigit)
  76.             buffer.append(c)
  77.           else
  78.             throw new Exception(s"Invalid character '$c'")
  79.       }
  80.       i += 1
  81.     }
  82.  
  83.     buffer.toDouble
  84.   }
  85.  
  86.   if (mobile.charAt(0) == openMobile)
  87.     parseMobile(mobile.replaceAll("\\s", ""))
  88.   else
  89.     throw new Exception("blargh")
  90. }
  91.  
  92. parse("[1,2|4,[1,2|4,5]]");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement