Refactor and reformat scala example

This commit is contained in:
Alexey Andreev 2017-07-01 23:43:01 +03:00
parent 434a3dd207
commit 46ebc2d694
4 changed files with 90 additions and 90 deletions

View File

@ -3,7 +3,7 @@ package org.teavm.samples.scala
import org.teavm.samples.scala.Grammar._
object Calculator {
def eval(expr : Expr) : BigInt = expr match {
def eval(expr: Expr): BigInt = expr match {
case Add(a, b) => eval(a) + eval(b)
case Subtract(a, b) => eval(a) - eval(b)
case Multiply(a, b) => eval(a) * eval(b)
@ -12,16 +12,16 @@ object Calculator {
case Number(v) => v
}
def print(expr : Expr) : String = expr match {
def print(expr: Expr): String = expr match {
case Add(a, b) => "(" + print(a) + " + " + print(b) + ")"
case Subtract(a, b) => "(" + print(a) + " - " + print(b) + ")"
case Multiply(a, b) => "(" + print(a) + " * " + print(b) + ")"
case Divide(a, b) => "(" + print(a) + " / " + print(b) + ")"
case Negate(n) => "-" + print(n)
case Number(v) => v.toString()
case Number(v) => v.toString
}
def parse(str : Seq[Char]) = additive.parse(str)
def parse(str: Seq[Char]) = additive.parse(str)
def additive = multiplicative ~ ((keyword("+") | keyword("-")) ~ multiplicative).* >> {
case (h, t) => t.foldLeft(h) {
@ -29,31 +29,42 @@ object Calculator {
case (left, ("-", right)) => Subtract(left, right)
}
}
def multiplicative = unary ~ ((keyword("*") | keyword("/")) ~ unary).* >> {
case (h, t) => t.foldLeft(h) {
case (left, ("*", right)) => Multiply(left, right)
case (left, ("/", right)) => Divide(left, right)
}
}
def unary : Rule[Expr] = keyword("-").? ~ primitive >> {
def unary: Rule[Expr] = keyword("-").? ~ primitive >> {
case (Some(_), v) => Negate(v)
case (None, v) => v
}
def primitive : Rule[Expr] = Rule.firstOf(number >> Number, group)
def group : Rule[Expr] = keyword("(") ~ additive ~ keyword(")") >> { case ((_, result), _) => result }
def number : Rule[Int] = range('1', '9') ~ range('0', '9').* ~ ws >> {
def primitive: Rule[Expr] = Rule.firstOf(number >> Number, group)
def group: Rule[Expr] = keyword("(") ~ additive ~ keyword(")") >> { case ((_, result), _) => result }
def number: Rule[Int] = range('1', '9') ~ range('0', '9').* ~ ws >> {
case ((h, t), _) => t.foldLeft(h - '0')((n, c) => n * 10 + (c - '0'))
}
def keyword(str : String) = s(str) ~ ws >> { case (s, _) => s }
def ws = s(" ").* >> { case _ => Unit }
def keyword(str: String) = s(str) ~ ws >> { case (s, _) => s }
def ws = s(" ").* >> (_ => Unit)
}
sealed abstract class Expr
case class Number(value : Int) extends Expr
case class Add(left : Expr, right : Expr) extends Expr
case class Subtract(left : Expr, right : Expr) extends Expr
case class Multiply(left : Expr, right : Expr) extends Expr
case class Divide(left : Expr, right : Expr) extends Expr
case class Negate(argument : Expr) extends Expr
case class Number(value: Int) extends Expr
case class Add(left: Expr, right: Expr) extends Expr
case class Subtract(left: Expr, right: Expr) extends Expr
case class Multiply(left: Expr, right: Expr) extends Expr
case class Divide(left: Expr, right: Expr) extends Expr
case class Negate(argument: Expr) extends Expr

View File

@ -1,30 +1,26 @@
package org.teavm.samples.scala
import org.teavm.samples.scala.DOM._
import org.teavm.samples.scala.Calculator.parse
import org.teavm.samples.scala.Calculator.print
import org.teavm.samples.scala.Calculator.eval
import org.teavm.jso.browser.Window
import org.teavm.jso.dom.html._
import org.teavm.jso.dom.events._
import org.teavm.jso.dom.html._
import org.teavm.samples.scala.Calculator.{eval, parse, print}
object Client {
def main(args: Array[String]) {
var doc = HTMLDocument.current
var exprElem = doc.getElementById("expr").asInstanceOf[HTMLInputElement]
var calcElem = doc.getElementById("calculate")
var resultList = doc.getElementById("result-list");
calcElem.listenClick((e : MouseEvent) => {
parse(exprElem.getValue().toSeq) match {
val doc = HTMLDocument.current
val exprElem = doc.getElementById("expr").asInstanceOf[HTMLInputElement]
val calcElem = doc.getElementById("calculate")
val resultList = doc.getElementById("result-list")
calcElem.listenClick((e: MouseEvent) => {
parse(exprElem.getValue.toSeq) match {
case (None, _) => Window.alert("Error parsing expression");
case (Some(x), Nil) => {
resultList.insertBefore(doc.createElement("div", (elem : HTMLElement) => {
elem.withChild("span", (child : HTMLElement) =>
case (Some(x), Nil) =>
resultList.insertBefore(doc.createElement("div", (elem: HTMLElement) => {
elem.withChild("span", (child: HTMLElement) =>
child.withAttr("class", "plan").withText(print(x) + " = "))
elem.withChild("span", (child : HTMLElement) =>
elem.withChild("span", (child: HTMLElement) =>
child.withAttr("class", "result").withText(eval(x).toString))
}), resultList.getFirstChild)
}
case (_, err) => Window.alert("Error parsing expression: " + err);
}
})

View File

@ -1,18 +0,0 @@
package org.teavm.samples.scala
import org.teavm.jso.dom.events._
import java.util.function.Consumer
object DOM {
implicit def toEventListener[T <: Event](f : T => Any) : EventListener[T] = {
new EventListener[T]() {
def handleEvent(e : T) = f(e)
}
}
implicit def toConsumer[T](f : T => Any) : Consumer[T] = {
new Consumer[T]() {
def accept(e : T) = f(e)
}
}
}

View File

@ -1,56 +1,65 @@
package org.teavm.samples.scala
object Grammar {
def rule[T](f : Seq[Char] => (Option[T], Seq[Char])) : Rule[T] = Rule.rule(f)
def s(str : String) : Rule[String] = Rule.expect(str)
def range(first : Char, last : Char) : Rule[Char] = Rule.range(first, last)
def rule[T](f: Seq[Char] => (Option[T], Seq[Char])): Rule[T] = Rule.rule(f)
def s(str: String): Rule[String] = Rule.expect(str)
def range(first: Char, last: Char): Rule[Char] = Rule.range(first, last)
}
trait Rule[T] {
def parse(chars : Seq[Char]) : (Option[T], Seq[Char])
def ~[S](other : Rule[S]) : Rule[(T, S)] = Rule.concat(this, other)
def ~(other : => String) : Rule[(T, String)] = Rule.concat(this, Rule.expect(other))
def |(other : => Rule[T]) : Rule[T] = Rule.firstOf(this, other)
def *() : Rule[List[T]] = Rule.unlimited(this)
def >>[S](f : T => S) : Rule[S] = Rule.andThen(this, f)
def ?() : Rule[Option[T]] = Rule.optional(this)
def parse(chars: Seq[Char]): (Option[T], Seq[Char])
def debug(str : String) = Rule.rule { x =>
var (result, rem) = parse(x)
def ~[S](other: Rule[S]): Rule[(T, S)] = Rule.concat(this, other)
def ~(other: => String): Rule[(T, String)] = Rule.concat(this, Rule.expect(other))
def |(other: => Rule[T]): Rule[T] = Rule.firstOf(this, other)
def *(): Rule[List[T]] = Rule.unlimited(this)
def >>[S](f: T => S): Rule[S] = Rule.andThen(this, f)
def ?(): Rule[Option[T]] = Rule.optional(this)
def debug(str: String) = Rule.rule { x =>
val (result, rem) = parse(x)
println(str + ":" + result + ":" + rem)
(result, rem)
}
}
object Rule {
def rule[T](f : Seq[Char] => (Option[T], Seq[Char])) : Rule[T] = new Rule[T]() {
def parse(chars : Seq[Char]) : (Option[T], Seq[Char]) = f(chars)
}
def concat[S, T](left : Rule[S], right : => Rule[T]) : Rule[(S, T)] = {
def rule[T](f: Seq[Char] => (Option[T], Seq[Char])): Rule[T] = (chars: Seq[Char]) => f(chars)
def concat[S, T](left: Rule[S], right: => Rule[T]): Rule[(S, T)] = {
rule(chars => left.parse(chars) match {
case (Some(leftResult), rem) => right.parse(rem) match {
case (Some(rightResult), rem2) => (Some((leftResult, rightResult)), rem2)
case (None, rem2) => (None, rem)
case (None, _) => (None, rem)
}
case (None, rem) => (None, rem)
})
}
def unlimited[T](inner : Rule[T]) : Rule[List[T]] = {
def iter(chars : Seq[Char]) : (List[T], Seq[Char]) = {
def unlimited[T](inner: Rule[T]): Rule[List[T]] = {
def iter(chars: Seq[Char]): (List[T], Seq[Char]) = {
inner.parse(chars) match {
case (Some(result), rem) => {
case (Some(result), rem) =>
val (tail, rem2) = iter(rem)
(result :: tail, rem2)
}
case (None, rem) => (Nil, rem)
}
}
rule(chars => {
val (result, rem) = iter(chars)
(Some(result), rem)
})
}
def firstOf[T](first : Rule[T], second : => Rule[T]) : Rule[T] = {
def firstOf[T](first: Rule[T], second: => Rule[T]): Rule[T] = {
rule(chars => first.parse(chars) match {
case (Some(result), rem) => (Some(result), rem)
case (None, _) => second.parse(chars) match {
@ -59,14 +68,16 @@ object Rule {
}
})
}
def optional[T](inner : Rule[T]) : Rule[Option[T]] = {
def optional[T](inner: Rule[T]): Rule[Option[T]] = {
rule(chars => inner.parse(chars) match {
case (Some(result), rem) => (Some(Some(result)), rem)
case (None, rem) => (Some(None), chars)
})
}
implicit def expect(str : String) : Rule[String] = {
def iter(chars : Seq[Char], index : Int) : (Boolean, Seq[Char]) = {
implicit def expect(str: String): Rule[String] = {
def iter(chars: Seq[Char], index: Int): (Boolean, Seq[Char]) = {
if (index == str.length())
(true, chars)
else chars match {
@ -75,24 +86,24 @@ object Rule {
case _ => (false, chars)
}
}
rule(chars => {
val (matched, rem) = iter(chars, 0)
(matched match {
case true => Some(str)
case false => None
}, rem)
(if (matched) Some(str) else None, rem)
})
}
def andThen[T, S](inner : Rule[T], f : T => S) : Rule[S] = {
def andThen[T, S](inner: Rule[T], f: T => S): Rule[S] = {
rule(chars => inner.parse(chars) match {
case (Some(result), rem) => (Some(f(result)), rem)
case (None, rem) => (None, rem)
})
}
def range(first : Char, last : Char) : Rule[Char] = {
rule(chars => chars match {
def range(first: Char, last: Char): Rule[Char] = {
rule {
case c +: rem if c >= first && c <= last => (Some(c), rem)
case _ => (None, chars)
})
case chars => (None, chars)
}
}
}