You are on page 1of 7

1 import CombinableParsers.

{concat, leftMost, or, rightMost}


2 import OperationsParsers.{constant, kleene, mapped, optional, plus, satisfy, separator}
3 import scala.util.Try
4
5 object Parser {
6 type SuccessParse[+T] = (T, String)
7
8 type ParseFunction[T] = String => SuccessParse[T]
9
10 abstract class Parser[+T]{
11 def parse(elementToParse: String): Try[SuccessParse[T]] = {
12 Try {
13 if(elementToParse.isEmpty) throw new RuntimeException("No se encontro ningun caracter")
14 parseFunction(elementToParse)
15 }
16 }
17
18 def parseFunction(elementToParse: String): SuccessParse[T]
19
20 def <|>[T1 >: T](otherParser: Parser[T1]): Parser[T1] = or(this, otherParser)
21 def <>[U](otherParser: Parser[U]): Parser[(T,U)] = concat(this, otherParser)
22 def ~>[U](otherParser: Parser[U]): Parser[U] = rightMost(this, otherParser)
23 def <~[U](otherParser: Parser[U]): Parser[T] = leftMost(this, otherParser)
24
25 def satisfies(condition: T => Boolean): Parser[T] = satisfy(this, condition)
26 def opt(): Parser[Option[T]] = optional(this)
27 def *(): Parser[List[T]] = kleene(this)
28 def +(): Parser[List[T]] = plus(this)
29
30 def sepBy[U](sepParser: Parser[U]): Parser[List[T]] = separator(this, sepParser)
31 def const[U](value: U): Parser[U] = constant(this, value)
32 def map[U](transform: T => U): Parser[U] = mapped(this, transform)
33
34 }
35 }
Page 1 of 1
1 import BasicParsers.{char, number, string}
2 import Musica._
3 import Parser.Parser
4
5 object MusicParser {
6
7 val silencio: Parser[Silencio] =
8 char('_').const(Silencio(Blanca)) <|>
9 char('-').const(Silencio(Negra)) <|>
10 char('~').const(Silencio(Corchea))
11
12 val alteracion: Parser[Nota => Nota] =
13 char('#').const { (unaNota: Nota) => unaNota.sostenido } <|>
14 char('s').const { (unaNota: Nota) => unaNota.sostenido } <|>
15 char('b').const { (unaNota: Nota) => unaNota.bemol }
16
17 val nota: Parser[Nota] = ((
18 char('C').const(C) <|>
19 char('D').const(D) <|>
20 char('E').const(E) <|>
21 char('F').const(F) <|>
22 char('G').const(G) <|>
23 char('A').const(A) <|>
24 char('B').const(B)
25 ) <> alteracion.opt).map {
26 case (note, None) => note
27 case (note, Some(alteracionFn)) => alteracionFn(note)
28 }
29
30 val tono: Parser[Tono] = (number <> nota).map{ case (octava, nota) => Tono(octava, nota) }
31
32 val figura: Parser[Figura] =
33 string("1/16").const(SemiCorchea) <|>
34 string("1/1").const(Redonda) <|>
35 string("1/2").const(Blanca) <|>
Page 1 of 2
36 string("1/4").const(Negra) <|>
37 string("1/8").const(Corchea)
38
39 val sonido: Parser[Sonido] = (tono <> figura).map { case (unTono, unaFigura) => Sonido(unTono, unaFigura) }
40
41 val calidad: Parser[(Tono, Figura) => Acorde] =
42 char('m').const { (unTono: Tono, unaFigura: Figura) => unTono.nota.acordeMenor(unTono.octava, unaFigura
) } <|>
43 char('M').const { (unTono: Tono, unaFigura: Figura) => unTono.nota.acordeMayor(unTono.octava, unaFigura) }
44
45 val acordeConCalidad: Parser[Acorde] = (tono <> calidad <> figura).map {
46 case ((unTono, acordeFn), unaFigura) => acordeFn(unTono, unaFigura)
47 }
48
49 val acordeConNotas: Parser[Acorde] = ((tono sepBy char('+')) <> figura).map {
50 case ( tonos, unaFigura ) => Acorde(tonos, unaFigura)
51 }
52
53 val acorde: Parser[Acorde] = acordeConCalidad <|> acordeConNotas
54 val tocable: Parser[Tocable] = silencio <|> sonido <|> acorde
55
56 val melodia: Parser[Melodia] = tocable sepBy char(' ')
57
58 }
59

Page 2 of 2
1 import Parser.{Parser, SuccessParse}
2
3 object BasicParsers {
4
5 case class anyChar() extends Parser[Char] {
6 override def parseFunction(elementToParse: String): SuccessParse[Char] = {
7 (elementToParse.charAt(0), elementToParse.substring(1))
8 }
9 }
10
11 def char(charToFind: Char): Parser[Char] = anyChar().satisfies(_==charToFind)
12
13 val void: Parser[Unit] = anyChar().const(())
14
15 def matches(regex: String): Parser[Char] = anyChar().satisfies(_.toString.matches(regex))
16
17 val letter: Parser[Char] = matches("[a-zA-Z]")
18
19 val digit: Parser[Char] = matches("[0-9]")
20
21 val number: Parser[Int] = digit.map(_.asDigit)
22
23 val alphaNum: Parser[Char] = letter <|> digit
24
25 case class string(stringToFind: String) extends Parser[String] {
26 override def parseFunction(elementToParse: String) : SuccessParse[String] = {
27 if(!elementToParse.startsWith(stringToFind)) throw new RuntimeException("El elemento no empieza con el
string a buscar")
28 (stringToFind, elementToParse.replaceFirst(stringToFind, ""))
29 }
30 }
31
32 }
33

Page 1 of 1
1 import Parser.{Parser, SuccessParse}
2 import scala.util.{Failure, Success}
3
4 object CombinableParsers {
5 case class or[T](aParser: Parser[T], anotherParser: Parser[T]) extends Parser[T] {
6 override def parseFunction(elementToParse: String): SuccessParse[T] = {
7 val result = aParser.parse(elementToParse) orElse anotherParser.parse(elementToParse)
8 result match {
9 case Success(value) => value
10 case Failure(_) => throw new RuntimeException("El elemento no satisface ningun parser")
11 }
12 }
13 }
14
15 case class concat[T, U](aParser: Parser[T], anotherParser: Parser[U]) extends Parser[(T,U)] {
16 override def parseFunction(elementToParse: String): SuccessParse[(T,U)] = {
17 val result = for {
18 (value1, rest1) <- aParser.parse(elementToParse)
19 (value2, rest2) <- anotherParser.parse(rest1)
20 } yield ((value1, value2), rest2)
21 result.get
22 }
23 }
24
25 def rightMost[T, U](aParser: Parser[T], anotherParser: Parser[U]): Parser[U] = (aParser <> anotherParser).map
{
26 case (_, value2) => value2
27 }
28
29 def leftMost[T, U](aParser: Parser[T], anotherParser: Parser[U]): Parser[T] = (aParser <> anotherParser).map {
30 case (value1, _) => value1
31 }
32
33 }
34
Page 1 of 1
1 import Parser.{Parser, SuccessParse}
2 import scala.util.{Failure, Success}
3
4 object OperationsParsers {
5 case class satisfy[T](parser: Parser[T], condition: T => Boolean) extends Parser[T] {
6 override def parseFunction(elementToParse: String): SuccessParse[T] = {
7 val (value, rest) = parser.parse(elementToParse).get
8 if(!condition(value)) throw new RuntimeException("El elemento parseado no satisface la condicion dada")
9 (value, rest)
10 }
11 }
12
13 case class optional[T](parser: Parser[T]) extends Parser[Option[T]] {
14 override def parseFunction(elementToParse: String): SuccessParse[Option[T]] = {
15 val result = parser.parse(elementToParse)
16 result match {
17 case Success((value, rest)) => (Some(value), rest)
18 case Failure(_) => (None, elementToParse)
19 }
20 }
21 }
22
23 case class kleene[T](parser: Parser[T]) extends Parser[List[T]] {
24
25 private def getParseIterations(elementToParse: String, iterationsValues: List[T]): SuccessParse[List[T]] = {
26 val parsedElement = parser.parse(elementToParse)
27 parsedElement match {
28 case Failure(_) => (iterationsValues, elementToParse)
29 case Success((value, rest)) => getParseIterations(rest, iterationsValues ::: List(value))
30 }
31 }
32
33 override def parseFunction(elementToParse: String): SuccessParse[List[T]] = {
34 getParseIterations(elementToParse, List.empty)
35 }
Page 1 of 2
36 }
37
38 def plus[T](parser: Parser[T]): Parser[List[T]] = parser.*().satisfies(_.nonEmpty)
39
40 def separator[T, U](parser: Parser[T], sepParser: Parser[U]): Parser[List[T]] = ((parser <~ sepParser).+ <>
parser).map {
41 case (valueList, lastValue) => valueList ::: List(lastValue)
42 }
43
44 def constant[T, U](parser: Parser[T], value: U): Parser[U] = parser.map{ _ => value }
45
46 case class mapped[T, U](parser: Parser[T], transform: T => U) extends Parser[U] {
47 override def parseFunction(elementToParse: String): (U, String) = {
48 val (value, rest) = parser.parse(elementToParse).get
49 (transform(value), rest)
50 }
51 }
52
53 }
54

Page 2 of 2

You might also like