Copyright © Cay S. Horstmann 2011 Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.

Parsing 3

Context-Free Grammar

Parse Tree

Grammar Example: List of Numbers

Grammar Example: List of Numbers

Extended BNF

Parser Generators

Combinator Parser

Combinator Parser Result

Lab

???

Step 1

  1. Here is the complete application that was discussed in the lecture:
    package parsing3
    
    import scala.util.parsing.combinator._
    
    class SimpleLanguageParser extends JavaTokenParsers {    
      def expr: Parser[Any] = term ~ opt(("+" | "-") ~ expr)
      def term: Parser[Any] = factor ~ opt(("*" | "/" ) ~ term)
      def factor: Parser[Any] = wholeNumber | "(" ~ expr ~ ")"
    }
    
    object Main {
      def main(args: Array[String]) = {
        val parser = new SimpleLanguageParser
        val result = parser.parse(parser.expr, "3 - 4 * 5")
        println(result)
      }
    }
  2. Run the application. What is the output?
  3. Now change the expression to 3 * 4 - 5. How does the output differ?
  4. How does this indicate that the grammer “knows” that multiplication binds more strongly than addition?
  5. The factor rule recurses back to the expr rule. Give an example input to the parser that demonstrates this feature. What is your input? What is the output?
  6. What happens when you give an illegal input to the parser? What input did you give, and what was the result?

Step 2

  1. Add the following function to the SimpleLanguageParser (and not to Main):
    def eval(x : Any) : Int = x match {
      case a ~ Some("+" ~ b) => eval(a) + eval(b)
      case a ~ Some("-" ~ b) => eval(a) - eval(b)
      case a ~ Some("*" ~ b) => eval(a) * eval(b)
      case a ~ Some("/" ~ b) => eval(a) / eval(b)
      case a ~ None => eval(a)
      case a : String => Integer.parseInt(a)
      case "(" ~ a ~ ")" => eval(a)
    }
  2. In your main program, print the value computed by parser.eval(result.get). What output do you get when the parser input is 3 - 4 * 5? 3 * 4 - 5?

  3. What does the eval function do?
  4. Give an input that shows that the last matching rule is necessary. What is your input? What is the output? What result do you get when you comment out the last matching rule?

Step 3

  1. Now we want to enhance the language and add support for statements such as
    val x = 3 + 4 * y

    In BNF, this would be

    valdef ::= "val" identifier "=" expr

    Add a valdef type to the combinator parser that represents such a definition. (To see how to parse an identifier, go to the scaladoc of JavaTokenParsers and then click on the source link on the top of the file.)

    What is the type that you added?

  2. What do you get when you parse val x = 3 + 4? Hint: Remember to call
    parser.parse(parser.valdef, "val x = 3 + 4")
  3. What happens when you parse val x = 3 + 4 * y? (Hint: Look closely at the output. Where is the y? Why?)
  4. What do you do to fix the problem? (Hint: Handle variable identifiers at the same level as numbers.)
  5. Now what is the parser output?