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

@ -18,7 +18,7 @@ object Calculator {
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)
@ -29,17 +29,21 @@ 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 >> {
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 >> {
@ -47,13 +51,20 @@ object Calculator {
}
def keyword(str: String) = s(str) ~ ws >> { case (s, _) => s }
def ws = s(" ").* >> { case _ => Unit }
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

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");
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 {
parse(exprElem.getValue.toSeq) match {
case (None, _) => Window.alert("Error parsing expression");
case (Some(x), Nil) => {
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) =>
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

@ -2,54 +2,63 @@ 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)
}
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 debug(str: String) = Rule.rule { x =>
var (result, rem) = parse(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 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]) = {
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] = {
rule(chars => first.parse(chars) match {
case (Some(result), rem) => (Some(result), rem)
@ -59,12 +68,14 @@ object Rule {
}
})
}
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]) = {
if (index == str.length())
@ -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] = {
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 {
rule {
case c +: rem if c >= first && c <= last => (Some(c), rem)
case _ => (None, chars)
})
case chars => (None, chars)
}
}
}