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.
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 + 1your program should print
1729
(1, 23, -79)
) into a Scala list. Also support expressions of the form wholeNumber :: list
.
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)
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())))