Skip to content

Instantly share code, notes, and snippets.

@bwmcadams
Created October 13, 2011 15:26
Show Gist options
  • Save bwmcadams/1284516 to your computer and use it in GitHub Desktop.
Save bwmcadams/1284516 to your computer and use it in GitHub Desktop.
AST Parsing Combinator
import scala.util.parsing.combinator._
trait RunParser {
this: RegexParsers =>
type RootType
def root: Parser[RootType]
def run(in: String): ParseResult[RootType] = parseAll(root, in)
}
case class Variable(name: String)
sealed trait MathExpression {
def sign: String
def left: Variable
def right: Variable
}
case class VariableDef(name: Variable, value: Double)
case class SumExpression (override val sign: String,
override val left: Variable,
override val right: Variable) extends MathExpression
case class ProductExpression (override val sign: String,
override val left: Variable,
override val right: Variable) extends MathExpression
object Statements extends JavaTokenParsers with RunParser {
lazy val sumExpr = (variable ~ ("+" ~ variable | "-" ~ variable )) ^^ {
case left ~ (sign ~ right) => SumExpression(sign, left, right)
}
lazy val prodExpr = (variable ~ ("*" ~ variable | "/" ~ variable )) ^^ {
case left ~ (sign ~ right) => ProductExpression(sign, left, right)
}
lazy val variableDef = variable ~ "=" ~ (decimalNumber | floatingPointNumber) ^^ {
case name ~ _ ~ value => VariableDef(name, value.toDouble)
}
lazy val variable = "$" ~> ident ^^ ((chars: String) => Variable(chars))
lazy val sequence = "(" ~> repsep(variable, ",") <~ ")"
type RootType = List[Any]
def root = repsep(variableDef | sumExpr | prodExpr, ";")
}
val vars = scala.collection.mutable.HashMap.empty[Variable, Double]
for (stmt <- Statements.run("$foo = 5.5; $bar = 100.0; $baz = 3.14; $foo + $bar; $bar * $baz; $bar / $foo; $baz - $foo ").get) {
stmt match {
case VariableDef(name, value: Double) => vars.put(name, value)
case SumExpression("+", left, right) => println("<%s> + <%s> = %s".format(left.name, right.name, vars(left) + vars(right)))
case SumExpression("-", left, right) => println("<%s> - <%s> = %s".format(left.name, right.name, vars(left) - vars(right)))
case ProductExpression("*", left, right) => println("<%s> * <%s> = %s".format(left.name, right.name, vars(left) * vars(right)))
case ProductExpression("/", left, right) => println("<%s> / <%s> = %s".format(left.name, right.name, vars(left) / vars(right)))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment