Created
October 13, 2011 15:26
-
-
Save bwmcadams/1284516 to your computer and use it in GitHub Desktop.
AST Parsing Combinator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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