Homework 6

  1. Finish Lecture 10/Lab 9 Step 3 with values, and add definitions as in Homework 5. Your value definition class should be Def without a type parameter, denoting integer-valued definitions. Here is how to parse a value definition:
        def valdef: Parser[Def] = ("val" ~> ident <~ "=") ~ expr <~ ";" ^^ { case s ~ e => Def(s, e) } 
    
    Parse a program that is a sequence of value definitions followed by a single expression. The prog function of your parser should return an instance of
    case class Prog(defs: List[Def], expr: Expr) {
      def eval: Int
    }
    
    The eval function should yield the value of the expression with the given variable bindings.
    Put all classes into an object hw6part1 whose body is
    val parser = new SimpleLanguageParser
    parser.parseAll(parser.prog, new InputStreamReader(System.in)) match {
      case parser.Success(result, next) => println(result.eval)
      case _ => println("Error")
    }
    I will test this program by running
    sbt -no-colors "runMain hw6part1" < part1in1
    sbt -no-colors "runMain hw6part2" < part1in2
    ...
    
    For example, if part1in1 contains
    val x = 12;
    x * x * x + 1
    your program should print
    1729
  2. Write a parser that parses a list of integers (such as (1, 23, -79)) into a Scala list. Also support expressions of the form wholeNumber :: list.
    Put your parser into an object hw6part2 in a file src/main/scala/hw6part2.scala whose body is
    val parser = new ListParser
    parser.parseAll(parser.list, new InputStreamReader(System.in)) match {
      case parser.Success(result, next) => println(result)
      case _ => println("Error")
    }
    I will test this program by running
    sbt -no-colors "runMain hw6part2" < part2in1
    sbt -no-colors "runMain hw6part2" < part2in2
    ...
    
    For example, if part2in1 contains
    1 :: 2 :: (3, 4)
    your program should print
    List(1, 2, 3, 4)
  3. Your task is to come up with a context-free grammar for an XML-like language. Tokens are

    < > = </ /> ident stringLiteral

    The last two are defined in JavaTokenParsers.

    An XML element must be closed, using one of the two alternative forms:

    <ident> ... </ident>

    or

    <ident/>

    The first form may contain any number of child elements.

    An element may contain any number of attributes, of the form

    name1="value1" name2="value2"

    Each name must be an identifier, and each value is a string literal.

    Write a Scala program that implements a combinator parser for this language. An hw6part3 object should read an expression from System.in and produce an instance of

    case class Element(name : String, attrs : List[(String, String)], children : List[Element])

    It's a little tricky to ensure that the start and end tag of an element match. Instead of using ^^, use ^? which allows you to supply a partial function—a match expression where not all cases are present. In my parser, I use a case like this:

    case i ~ a ~ ((c, Some(j))) if i == j => Element(j, a, c)

    Your parser may follow a different strategy, but the point is that you can use a case with an if to force the begin and end tags to match, and cause failure otherwise.

    NB. I have no idea why I had to put parentheses around the pair (c, Some(j)), but it didn't work without them.

    Put your parser into an object hw6part3 in a file src/main/scala/hw6part3.scala whose body is

    val parser = new XMLLikeParser
    parser.parseAll(parser.list, new InputStreamReader(System.in)) match {
      case parser.Success(result, next) => println(result)
      case _ => println("Error")
    }
    I will test this program by running
    sbt -no-colors "runMain hw6part3" < part3in1
    sbt -no-colors "runMain hw6part3" < part3in2
    ...
    
    For example, if part3in1 contains
    <greeting type="hello"><text value="world"/></greeting>
    your program should print
    Element(greeting,List((type,"hello")),List(Element(text,List((value,"world")),List())))