// $Id: EOPLParsers.scala,v 1.1 2005/10/28 20:46:16 leavens Exp leavens $
package interp;

import tools._;

/** Parsing specific to EOPL languages. */
abstract class EOPLParsers extends TokenParsers {

  /** Starting production for this grammar (program). */
  def program: Parser[Program] = 
    for (val exp: Expression <- expression)
      yield AProgram(exp);

  /** Parsing of expressions. */
  def expression: Parser[Expression] =
    number ||| primitiveApplication ||| identifier;

  def number: Parser[Expression] =
    for (val s: String <- nextToken(); s.matches("[0-9]+"))
      yield LitExp(new java.lang.Long(s).longValue());

  def identifier: Parser[Expression] =
    for (val s: String <- nextToken(); s.matches("[^0-9].*"))
      yield VarExp(new Symbol(s));

  def primitiveApplication: Parser[Expression] =
    for (val rator: Primitive <- primitive;
         val _ <- check("(");
         val rands: List[Expression] <- separatedList(expression, ",");
         val _ <- check(")"))
     yield PrimAppExp(rator, rands);

  /** Parsing of primitives */
  def primitive: Parser[Primitive] =
    addPrim ||| subtractPrim ||| multPrim ||| incrPrim ||| decrPrim;

  def addPrim: Parser[Primitive] =
    for (val t: String <- nextToken(); t equals "+")
      yield AddPrim();

  def subtractPrim: Parser[Primitive] =
    for (val t: String <- nextToken(); t equals "-")
      yield SubtractPrim();

  def multPrim: Parser[Primitive] =
    for (val t: String <- nextToken(); t equals "*")
      yield MultPrim();

  def incrPrim: Parser[Primitive] =
    for (val t: String <- nextToken(); t equals "add1")
      yield IncrPrim();

  def decrPrim: Parser[Primitive] =
    for (val t: String <- nextToken(); t equals "sub1")
      yield DecrPrim();
}

