summaryrefslogblamecommitdiff
path: root/sources/examples/parsers1.scala
blob: 06e8ed0fe003d3a1fcd00a277e0d8446fb37bdf6 (plain) (tree)
1
2
3
4
5
6
7
8
9

                 
                        
 
             
 
                   
 
                                         
 
                                 
 



                                                                            


       


                                                                  
                                                        


       



                                                                  


       


                                                                  




                                              
                                              

   

                                            








                                                     
                                                

 
                                            
 
                        
 

                                        
 

                                     

                             


























                                                                   
 












                                                      
package examples;

abstract class Parsers {

  type input;

  trait Parser[a] {

    type Result = Option[Pair[a, input]];

    def apply(in: input): Result;

    def filter(pred: a => boolean) = new Parser[a] {
      def apply(in: input): Result = Parser.this.apply(in) match {
        case None => None
        case Some(Pair(x, in1)) => if (pred(x)) Some(Pair(x, in1)) else None
      }
    }

    def map[b](f: a => b) = new Parser[b] {
      def apply(in: input): Result = Parser.this.apply(in) match {
        case None => None
	case Some(Pair(x, in1)) => Some(Pair(f(x), in1))
      }
    }

    def flatMap[b](f: a => Parser[b]) = new Parser[b] {
      def apply(in: input): Result = Parser.this.apply(in) match {
        case None => None
	case Some(Pair(x, in1)) => f(x).apply(in1)
      }
    }

    def ||| (def p: Parser[a]) = new Parser[a] {
      def apply(in: input): Result = Parser.this.apply(in) match {
	case None => p(in)
	case s => s
      }
    }

    def &&& [b](def p: Parser[b]): Parser[b] =
      for (val _ <- this; val x <- p) yield x;
  }

  def succeed[a](x: a) = new Parser[a] {
    def apply(in: input) = Some(Pair(x, in))
  }

  def rep[a](p: Parser[a]): Parser[List[a]] =
    rep1(p) ||| succeed(List());

  def rep1[a](p: Parser[a]): Parser[List[a]] =
    for (val x <- p; val xs <- rep(p)) yield x :: xs;

  def opt[a](p: Parser[a]): Parser[Option[a]] =
    (for (val x <- p) yield List(x)) ||| List();
}

abstract class ExprParsers extends Parsers {

  def any: Parser[char];

  def chr(ch: char) =
    for (val c <- any; c == ch) yield c;

  def chr(p: char => boolean) =
    for (val c <- any; p(c)) yield c;

  def ident: Parser[String] =
    for (
      val c: char <- chr(Character.isLetter);
      val cs: List[char] <- rep(chr(Character.isLetterOrDigit))
    ) yield (c :: cs).mkString("", "", "");

  def number: Parser[int] =
    for (
      val d: char <- chr(Character.isDigit);
      val ds: List[char] <- rep(chr(Character.isDigit))
    ) yield ((d - '0') /: ds) ((x, digit) => x * 10 + digit - '0');

  def list: Parser[List[Tree]] =
    for (
      val _ <- chr('(');
      val es <- listElems ||| succeed(List());
      val _ <- chr(')')
    ) yield es;

  def listElems: Parser[List[Any]] =
    for (
      val x <- expr;
      val xs <- chr(',') &&& listElems ||| succeed(List())
    ) yield x :: xs;

  def expr: Parser[Any] =
    list ||| ident ||| number;

}

object Test {
  def main(args: Array[String]) =
    System.out.println(
      if (args.length == 1)
	new ExprParserFamily(args(0)).expr(0) match {
	  case Some(Pair(tree, _)) => tree.toString();
	  case None => "Syntax error"
	}
      else "usage: java examples.Test <expr-string>"
    );
}