Copyright © Cay S. Horstmann 2011
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United
States License.
"class
"
"3.14
"
"(
"
expression
term ::= factor * term
term ::= factor
term ::= factor * term ::= factor * factor * term ::= factor * factor * factor
(1) (1, 24, 4) ()
list ::= "(" contents ")"
contents ::= contents ::= number contents ::= number "," contents
(1, 24, )
list ::= "(" contents ")" list ::= "(" ")"
contents ::= number contents ::= number "," contents
contents
yields n
numbers separated by n - 1 commasA | B
(A)*
or {A}
(A)+
(A)?
or [A]
list = "(" ( number ( "," number )* )? ")"
~
|
rep(...)
opt(...)
class SimpleLanguageParser extends JavaTokenParsers { def expr: Parser[Any] = term ~ opt(("+" | "-") ~ expr) def term: Parser[Any] = factor ~ opt(("*" | "/" ) ~ term) def factor: Parser[Any] = wholeNumber | "(" ~ expr ~ ")" }
Parser[Any]
with something more useful
lateropt(P)
returns Option
: Some
of the
result of P
, or None
rep(P)
returns List
of the results of
P
P ~ Q
returns instance of class ~
(similar to a
pair)val parser = new SimpleLanguageParser val result = parser.parse(parser.expr, "3 - 4 * 5")
sets result
to
((3~None)~Some((-~((4~Some((*~(5~None))))~None))))
(x~None)
to x
,
Some(y)
to y
, and ~
to spaces:
(3 (- (4 (* 5))))
ubmit lab work to Sakai.
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) } }
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?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) }
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?
eval
function do? 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?
val x = 3 + 4
? Hint: Remember
to call
parser.parse(parser.valdef, "val x = 3 + 4")
val x = 3 + 4 * y
? (Hint: Look
closely at the output. Where is the y? Why?)