Skip to content

Instantly share code, notes, and snippets.

@53ningen
Created December 23, 2014 13:13
Show Gist options
  • Save 53ningen/135266a4e06004a02d00 to your computer and use it in GitHub Desktop.
Save 53ningen/135266a4e06004a02d00 to your computer and use it in GitHub Desktop.
package com.gochiusa.golang.core
import scala.util.parsing.combinator.JavaTokenParsers
class Parser extends JavaTokenParsers {
val ifKeyword = "心"
val elseKeyword = "ぴょんぴょん"
val varKeyword = "心"
// statement
def statement: Parser[Statement] = ifStmt
// expr
def expr: Parser[Expr] = "("~>expr<~")" | binOpExpr1 | binOpExpr2 | relOpExp | assignExpr | term
def binOpExpr1: Parser[Number] = chainl1(binOpExpr2, ("+"|"-")^^{ op => (left: Number, right: Number) => BinOpExpr(left, op, right)})
def binOpExpr2: Parser[Number] = chainl1(number, ("*"|"/")^^{ op => (left: Number, right: Number) => BinOpExpr(left, op, right)})
def relOpExp: Parser[Bool] = number ~ ("<"|">"|"<="|">="|"==") ~ number ^^ { case left ~ op ~ right => RelOpExpr(left, op, right)}
def ifStmt: Parser[Statement] = ifKeyword~relOpExp~"{"~expr~"}"~elseKeyword~"{"~expr~"}" ^^ { case ifKeyword~cond~"{"~cons~"}"~elseKeyword~"{"~alt~"}" => IfStatement(cond, cons, alt)}
def assignExpr: Parser[Expr] = varKeyword~ident~"="~expr ^^ { case varKeyword~ident~"="~expr => AssignExpr(VariableExpr(ident), expr)}
def term: Parser[Expr] = number | boolean | quotedString | identifier
// primitive
def quotedString: Parser[Expr] = stringLiteral ^^ { str => StringValue(str.substring(1, str.length - 1))}
def number: Parser[Number] = floatingPointNumber ^^ { x => NumberValue(x.toDouble) }
def boolean: Parser[Expr] = ("true"|"false") ^^ { x => BooleanValue(x.toBoolean) }
def identifier: Parser[Number] = ident ^^ { x => VariableExpr(x) }
def parse(s: String) = {
parseAll(expr, s) match {
case Success(x, y) => x match {
case x: Number => println(x.eval(Map()))
case _ => println(x)
}
case x => println("Failure:" + x)
}
}
}
trait AST
abstract class Statement extends AST
case class IfStatement(condition: Bool, consequence: Expr, alternative: Expr) extends Statement
abstract class Expr extends AST
trait Number extends Expr { def eval(env: Map[String, Expr]): Double }
trait Bool extends Expr { def eval(env: Map[String, Expr]): Boolean }
trait Str extends Expr { def eval(env: Map[String, Expr]): String }
case class BinOpExpr(left: Number, op: String, right: Number) extends Expr with Number {
def eval(env: Map[String, Expr]): Double = {
op match {
case "+" => left.eval (env: Map[String, Expr]) + right.eval (env: Map[String, Expr])
case "-" => left.eval (env: Map[String, Expr]) - right.eval (env: Map[String, Expr])
case "*" => left.eval (env: Map[String, Expr]) * right.eval (env: Map[String, Expr])
case "/" => left.eval (env: Map[String, Expr]) / right.eval (env: Map[String, Expr])
}
}
}
case class RelOpExpr(left: Number, op: String, right: Number) extends Expr with Bool {
def eval(env: Map[String, Expr]): Boolean = {
op match {
case ">" => left.eval(env: Map[String, Expr]) > right.eval(env: Map[String, Expr])
case "<" => left.eval(env: Map[String, Expr]) < right.eval(env: Map[String, Expr])
case ">=" => left.eval(env: Map[String, Expr]) >= right.eval(env: Map[String, Expr])
case "<=" => left.eval(env: Map[String, Expr]) <= right.eval(env: Map[String, Expr])
case "==" => left.eval(env: Map[String, Expr]) == right.eval(env: Map[String, Expr])
}
}
}
case class VariableExpr(name: String) extends Expr with Number {
def eval(env: Map[String, Expr]): Double = env.get(name) match {
case v: Some[Number] => v.get.eval(env)
case _ => throw new IllegalStateException
}
}
case class AssignExpr(variable: VariableExpr, expr: Expr) extends Expr {
def eval(env: Map[String, Expr]): Map[String, Expr] = env ++ Map(variable.name -> expr)
}
case class NumberValue(v: Double) extends Expr with Number {
def eval(env: Map[String, Expr]): Double = v
}
case class BooleanValue(v: Boolean) extends Expr with Bool {
def eval(env: Map[String, Expr]): Boolean = v
}
case class StringValue(v: String) extends Expr with Str {
def eval(env: Map[String, Expr]): String = v
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment