パーサーを指定回数適用するrepNと、最後の"."をoptionalにするだけでわりと簡単に書けました。
import scala.util.parsing.combinator.syntactical._ object Main extends StandardTokenParsers { lexical.delimiters ++= List(".") def parse : Parser[List[String]] = repN(4, numericLit <~ opt(".")) def parseIp(s : String) : List[String] = { parse(new lexical.Scanner(s)) match { case Success(result, _) => return result case Failure(msg, _) => println("failure : " ++ msg) case Error(msg, _) => println("error : " ++ msg) } return List() } def main(args: Array[String]) { val ip : List[String] = parseIp("192.168.0.1") ip foreach println } }
192 168 0 1
整数型のリストとしてほしい場合は、パース時にtoInt。
import scala.util.parsing.combinator.syntactical._ object Main extends StandardTokenParsers { lexical.delimiters ++= List(".") def parse : Parser[List[Int]] = repN(4, numericLit <~ opt(".") ^^ { _.toInt }) def parseIp(s : String) : List[Int] = { parse(new lexical.Scanner(s)) match { case Success(result, _) => return result case Failure(msg, _) => println("failure : " ++ msg) case Error(msg, _) => println("error : " ++ msg) } return List() } def main(args: Array[String]) { val ip : List[Int] = parseIp("192.168.0.1") ip foreach println } }
numericLitは、Parser[Int]が返ってきてほしい。
Parser[Int]が返されるintLit書いてみました。
import scala.util.parsing.combinator.syntactical._ object Main extends StandardTokenParsers { lexical.delimiters ++= List(".") def intLit : Parser[Int] = elem("number", _.isInstanceOf[lexical.NumericLit]) ^^ (_.chars.toInt) def parse : Parser[List[Int]] = repN(4, intLit <~ opt(".")) def parseIp(s : String) : List[Int] = { parse(new lexical.Scanner(s)) match { case Success(result, _) => return result case Failure(msg, _) => println("failure : " ++ msg) case Error(msg, _) => println("error : " ++ msg) } return List() } def main(args: Array[String]) { val ip : List[Int] = parseIp("192.168.0.1") ip foreach println } }
型のパーサーは用意されてるのが不便なので自作したほうがいいかもしれない。