Skip to content

Instantly share code, notes, and snippets.

@ymnk
Created October 15, 2008 01:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ymnk/16834 to your computer and use it in GitHub Desktop.
Save ymnk/16834 to your computer and use it in GitHub Desktop.
import scala.util.parsing.combinator.lexical.StdLexical
import scala.util.parsing.combinator.syntactical.StdTokenParsers
/**
* This program will parse the arithmetic expression defined as follows,
* <exp> ::= <term> | <exp> "+" <term> | <exp> "-" <term>
* <term> ::= <factor> | <term> "*" <factor> | <term> "/" <factor>
* <factor> ::= <n> | "(" <exp> ")"
* , where n is a nonterminal symbol for numbers.
*
* This program has expected to be compiled with Calc2.scala[1]
* [1] http://gist.github.com/12517
*/
object Calc2WithParserCombinator extends StdTokenParsers {
type Tokens = StdLexical
val lexical = new Tokens
lexical.delimiters ++= List("(", ")", "+", "-", "*", "/")
/**
* For conveniences(to eliminate the left recursion), we will transform the grammar as follows,
* <exp> ::= <term> { ("+" | "-" ) <term> }
* <term> ::= <factor> { ("*" | "/" ) <factor> }
* <factor> ::= <n> | "(" <exp> ")"
*/
def exp:Parser[Atom] = term * ("+" ^^^ {Add(_, _)} | "-" ^^^ {Sub(_, _)})
def term:Parser[Atom] = factor * ("*" ^^^ {Mul(_, _)} | "/" ^^^ {Div(_, _)})
def factor:Parser[Atom] = numericLit ^^ {n => Var(n.toInt)} |
"(" ~> exp <~ ")"
def main(arg:Array[String])={
val a = phrase(exp)(new lexical.Scanner(arg(0))) match {
case Success(result, _) => result
case f@Failure(msg, _) => throw new Exception(f.toString)
case e@Error(msg, _) => throw new Exception(e.toString)
}
println(a)
import Calc2.{compile, eval}
val code = compile(a)
println(code)
val result = eval(code)
println(result)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment