From 9f5bdc30b6c0c49ccddd972203d4367ddd07d828 Mon Sep 17 00:00:00 2001 From: Gidon Ernst Date: Tue, 11 May 2021 17:39:04 +0200 Subject: [PATCH] log validation some cool stetps --- build.sc | 10 + falstar-config.sh | 2 + falstar-scala.sh | 9 +- falstar-session.sh | 9 +- falstar.sh | 8 +- falstar/src/falstar/Main.scala | 57 ++- .../falstar/falsification/Falsification.scala | 27 +- .../falstar/falsification/Validation.scala | 82 ++++ falstar/src/falstar/hybrid/Signal.scala | 21 +- falstar/src/falstar/linear/Vector.scala | 14 +- falstar/src/falstar/parser/Parser.scala | 28 +- falstar/src/falstar/parser/Scanner.flex | 2 +- falstar/src/falstar/parser/Scanner.java | 434 +++++++++--------- falstar/src/falstar/parser/package.scala | 13 +- falstar/src/falstar/util/Table.scala | 9 +- falstar/src/falstar/util/package.scala | 2 +- 16 files changed, 437 insertions(+), 290 deletions(-) create mode 100644 build.sc create mode 100644 falstar/src/falstar/falsification/Validation.scala diff --git a/build.sc b/build.sc new file mode 100644 index 0000000..cc3c9cb --- /dev/null +++ b/build.sc @@ -0,0 +1,10 @@ +import mill._ +import mill.scalalib._ + +object falstar extends ScalaModule { + def scalaVersion = "2.12.13" + def mainClass = Some("falstar.Main") + + def ivyDeps = Agg( + ivy"org.apache.commons:commons-csv:1.8") +} \ No newline at end of file diff --git a/falstar-config.sh b/falstar-config.sh index 6ce58d5..5db5c36 100755 --- a/falstar-config.sh +++ b/falstar-config.sh @@ -22,6 +22,8 @@ then # Bring $MATLABROOT into the environment source ~/.falstar/matlab echo "Matlab at: $MATLABROOT" + export LD_LIBRARY_PATH="$MATLABROOT/bin/glnxa64:$MATLABROOT/sys/os/glnxa64" + MATLABJARS="$MATLABROOT/java/jar/mvm.jar:$MATLABROOT/java/jar/javaenginecore.jar:$MATLABROOT/java/jar/matlab.jar:$MATLABROOT/java/jar/engine.jar:$MATLABROOT/java/jar/util.jar:$MATLABROOT/java/jar/capabilities.jar" else echo "Could not determine Matlab installation." fi diff --git a/falstar-scala.sh b/falstar-scala.sh index ab7d783..419ad3c 100755 --- a/falstar-scala.sh +++ b/falstar-scala.sh @@ -1,10 +1,5 @@ #!/bin/sh HERE=`dirname "$0"` - -source ~/.falstar/matlab -export LD_LIBRARY_PATH="$MATLABROOT/bin/glnxa64:$MATLABROOT/sys/os/glnxa64" - -CP="$MATLABROOT/java/jar/mvm.jar:$MATLABROOT/java/jar/javaenginecore.jar:$MATLABROOT/java/jar/matlab.jar:$MATLABROOT/java/jar/engine.jar:$MATLABROOT/java/jar/util.jar:$MATLABROOT/java/jar/capabilities.jar" - -./scala-2.12.13/bin/scala -cp "$CP:$HERE/falstar.jar" $@ +source $HERE/falstar-config.sh +scala -cp "$MATLABJARS:$HERE/falstar.jar" $@ diff --git a/falstar-session.sh b/falstar-session.sh index 8918c1a..d45bd1c 100755 --- a/falstar-session.sh +++ b/falstar-session.sh @@ -1,10 +1,5 @@ #!/bin/sh HERE=`dirname "$0"` - -source ~/.falstar/matlab -export LD_LIBRARY_PATH="$MATLABROOT/bin/glnxa64:$MATLABROOT/sys/os/glnxa64" - -CP="$MATLABROOT/java/jar/mvm.jar:$MATLABROOT/java/jar/javaenginecore.jar:$MATLABROOT/java/jar/matlab.jar:$MATLABROOT/java/jar/engine.jar:$MATLABROOT/java/jar/util.jar:$MATLABROOT/java/jar/capabilities.jar" - -./scala-2.12.13/bin/scala -cp "$CP:$HERE/falstar.jar" falstar.util.Matlab $@ +source $HERE/falstar-config.sh +java -cp "$MATLABJARS:$HERE/falstar.jar" falstar.util.Matlab $@ diff --git a/falstar.sh b/falstar.sh index ab417ed..b0aed8a 100755 --- a/falstar.sh +++ b/falstar.sh @@ -1,11 +1,5 @@ #!/bin/sh HERE=`dirname "$0"` - source $HERE/falstar-config.sh - -export LD_LIBRARY_PATH="$MATLABROOT/bin/glnxa64:$MATLABROOT/sys/os/glnxa64" - -CP="$MATLABROOT/java/jar/mvm.jar:$MATLABROOT/java/jar/javaenginecore.jar:$MATLABROOT/java/jar/matlab.jar:$MATLABROOT/java/jar/engine.jar:$MATLABROOT/java/jar/util.jar:$MATLABROOT/java/jar/capabilities.jar" - -java -cp "$CP:$HERE/falstar.jar" falstar.Main $@ +java -cp "$MATLABJARS:$HERE/falstar.jar" falstar.Main $@ diff --git a/falstar/src/falstar/Main.scala b/falstar/src/falstar/Main.scala index bdceaea..981c75e 100644 --- a/falstar/src/falstar/Main.scala +++ b/falstar/src/falstar/Main.scala @@ -15,12 +15,14 @@ import falstar.parser.Flush import falstar.parser.Quit import falstar.parser.Robustness import falstar.parser.Simulate +import falstar.parser.Validate import falstar.parser.parse import falstar.util.Probability import falstar.util.Row import falstar.util.Scope import falstar.util.Matlab import falstar.util.Table +import falstar.falsification.Validation object Main { object quit extends Breaks @@ -31,6 +33,7 @@ object Main { var graphics = false var dummy = false var append = true + var args: List[String] = Nil } val results = mutable.Map[String, mutable.Buffer[Row]]() @@ -66,6 +69,16 @@ object Main { val scope = new Scope(title, sys, best) } + case Validate(log, report, parser) => + val table = Table.read(log.get) + val rows = Validation.apply(table, parser) + + for (name <- report) { + if (!(results contains name)) + results(name) = mutable.Buffer() + results(name) ++= rows + } + case Simulate(sys, phi, ps, us, t) => val tr = sys.sim(ps, us, t) val rs = mtl.Robustness(phi, tr.us, tr.ys) @@ -110,7 +123,6 @@ object Main { } } - @tailrec def setup(args: List[String]): List[String] = args match { case "-a" :: rest => options.ask = true @@ -125,8 +137,13 @@ object Main { case "-d" :: rest => options.dummy = true setup(rest) - case _ => - args + case "--" :: rest => + options.args = rest + Nil + case Nil => + Nil + case file :: rest => + file :: setup(rest) } def safe(f: => Any) = { @@ -161,36 +178,14 @@ object Main { def main(args: Array[String]) { if (args.isEmpty) { - println("usage: falstar [-agv] [+] file_1 ... file_n") - println(" -a ask for additional input files:") - println(" enter one filename per line followed by a blank line") - println(" a blank line acknowledges, EOF (CTRL+d) aborts") - println(" -d dummy run, parse and validate configuration only") - println(" -g show a graphical diagram for each trial") - println(" -v be verbose") - println(" + no header in csv for next file (data should match previous header)") + println("usage: falstar [-dv] file_1 ... file_n") + println(" -d parse configuration only") + println(" -v be more verbose") } - val rest = setup(args.toList) - - var files = Buffer[String]() - files ++= rest - - quit.breakable { - while (options.ask) { - val line = StdIn.readLine - - if (line == null) - quit.break - else if (line.isEmpty) - options.ask = false - else - files += line - } - - runall(files) - writeall(results) - } + val files = setup(args.toList) + runall(files) + writeall(results) println("bye") diff --git a/falstar/src/falstar/falsification/Falsification.scala b/falstar/src/falstar/falsification/Falsification.scala index 27fbc83..0d54a90 100644 --- a/falstar/src/falstar/falsification/Falsification.scala +++ b/falstar/src/falstar/falsification/Falsification.scala @@ -19,15 +19,17 @@ trait Falsification { case Some(seed) => Probability.seed = seed } - val time = now() + val start = now() val data = (1 to n) map { i => println("trial " + i + "/" + n) - val (res, stat, row) = apply(sys, cfg, phi) + val (res, stat, row) = apply(sys, cfg, phi, notes) ((res, stat), row) } + val end = now() + val (all, rows) = data.unzip val (best, _) = all.minBy(_._1.score) @@ -44,7 +46,8 @@ trait Falsification { val what = Seq( "model" -> sys.name, "formula" -> phi, - "start date" -> time + "start date" -> start, + "end date" -> end ) val how = Seq( @@ -61,7 +64,7 @@ trait Falsification { (best, good map (_._1.tr.us), rows, Row(what ++ notes ++ how ++ params ++ aggregate)) } - def apply(sys: System, cfg: Config, phi: Formula): (Result, Statistics, Row) = { + def apply(sys: System, cfg: Config, phi: Formula, notes: Seq[(String, Any)]): (Result, Statistics, Row) = { val seed = Probability.seed println("property " + phi) @@ -72,7 +75,10 @@ trait Falsification { println(" " + name + ": " + value) } + val start = now() val (res, stats) = search(sys, cfg, phi) + val end = now() + println() println("inputs") @@ -101,14 +107,23 @@ trait Falsification { println(" peak memory " + falstar.util.peakMemBytes / 1000 + " kb") println() + val what = Seq( + "model" -> sys.name, "formula" -> phi, + "start date" -> start, + "end date" -> end + ) + + val how = Seq( + "algorithm" -> this.identification, + ) + val data = Seq( - "model" -> sys.name, "property" -> phi, "algorithm" -> this.identification, "seed" -> seed, "simulations" -> stats.simulations, "time" -> stats.time, "robustness" -> res.score, "falsified" -> { if (res.isFalsified) "yes" else "no" }, "input" -> { if (!us.isEmpty) (us toMatlab T) else "[]" }, "output" -> { if (!ys.isEmpty) (ys toMatlab T) else "[]" }) - val row = Row(data ++ params) + val row = Row(what ++ notes ++ how ++ params ++ data) // expose another seed for the next trial // required for external algorithms (Breach, S-Taliro) diff --git a/falstar/src/falstar/falsification/Validation.scala b/falstar/src/falstar/falsification/Validation.scala new file mode 100644 index 0000000..66d1276 --- /dev/null +++ b/falstar/src/falstar/falsification/Validation.scala @@ -0,0 +1,82 @@ +package falstar.falsification + +import scala.collection.mutable + +import falstar.util.Row +import falstar.util.Table +import falstar.hybrid.Config +import falstar.mtl.Formula +import falstar.mtl.Robustness +import falstar.hybrid.System +import falstar.parser.Parser +import falstar.hybrid.Signal +import falstar.linear.Vector + +object Validation { + def check(ok: Boolean) = { + if(ok) "yes" else "no" + } + + def apply(table: Table, parser: Parser): Seq[Row] = { + for(row <- table.rows) yield { + val res = apply(row, parser) + print(".") + res + } + } + + def apply(row: Row, parser: Parser): Row = { + val data = row.data.toMap.asInstanceOf[Map[String,String]] + + val system = data("system") + val state = parser.state + val (sys, cfg) = state.systems(system) + + val property = data("property") + // need to unpack one layer because it reads a sequence of nodes + val falstar.parser.Node(node) = falstar.parser.read(property) + state.system = sys // such that ports and stuff work + val phi = parser.formula(node) + val T = phi.T + + val res = mutable.Buffer[(String, Any)]() + + res += "system" -> system + res += "property" -> property + res += "formula" -> phi + + if(data contains "input") { + val ps = Vector.parse(data.getOrElse("parameters", "[]")) + val us = Signal.parse(data("input")) + // res += "input" -> input + + val pr = cfg.pn(sys.params) + res += "parameters valid" -> check(pr contains ps) + + val ur = cfg.in(sys.inputs) + res += "inputs valid" -> check(us forall { case (t, x) => ur contains x }) + + val tr = sys.sim(ps, us, T) + val rs = Robustness(phi, tr.us, tr.ys) + + if(data contains "falsified") { + val expected = data("falsified") + res += "falsified correct" -> check(expected == check(rs.score < 0)) + } + + if(data contains "robustness") { + val expected = data("robustness").toDouble + val computed = rs.score + val error = Math.abs(expected - computed) + res += "robustness correct" -> check((expected < 0) == (computed < 0)) + res += "robustness error" -> error + } + + if(data contains "output") { + val ys = Signal.parse(data("output")) + } + } + + Row(res) + } +} \ No newline at end of file diff --git a/falstar/src/falstar/hybrid/Signal.scala b/falstar/src/falstar/hybrid/Signal.scala index d29c229..48dd15f 100644 --- a/falstar/src/falstar/hybrid/Signal.scala +++ b/falstar/src/falstar/hybrid/Signal.scala @@ -5,6 +5,25 @@ import scala.collection.mutable.ArrayBuffer import falstar.linear.Vector object Signal { + def parse(str: String): Signal = { + assert(str startsWith "[") + assert(str endsWith "]") + val inner = str.substring(1, str.length - 1) + + if(inner.isEmpty) { + Signal.empty + } else { + val points = inner.split(";") + + for(point <- points) yield { + val x = point.trim.split("\\s+") + val t = x(0).toDouble + val y = Vector(x.length - 1, i => x(i + 1).toDouble) + (t, y) + } + } + } + def length(t0: Time, dt: Duration, T: Time): Int = { Math.ceil((T - t0) / dt).toInt } @@ -39,7 +58,7 @@ object Signal { val us = Seq.tabulate(controlpoints)(i => x) Signal(steps, i => (t0 + i * dt, us(i * controlpoints / steps))) } - + implicit class SignalOps(xs: Signal) { def t0: Time = { if (xs.isEmpty) 0 diff --git a/falstar/src/falstar/linear/Vector.scala b/falstar/src/falstar/linear/Vector.scala index 4b0f72f..6cbdded 100644 --- a/falstar/src/falstar/linear/Vector.scala +++ b/falstar/src/falstar/linear/Vector.scala @@ -128,7 +128,19 @@ class Vector(val length: Int) extends Traversable[Double] { object Vector { val empty = { - Vector(0) + Vector() + } + + def parse(str: String): Vector = { + assert(str startsWith "[") + assert(str endsWith "]") + val inner = str.substring(1, str.length - 1).trim + if(inner.isEmpty) { + empty + } else { + val data = inner.trim.split("\\s+") + Vector(data.length, i => data(i).toDouble) + } } def apply(length: Int, init: (Int) => Double): Vector = { diff --git a/falstar/src/falstar/parser/Parser.scala b/falstar/src/falstar/parser/Parser.scala index 3e9cecb..10f5332 100644 --- a/falstar/src/falstar/parser/Parser.scala +++ b/falstar/src/falstar/parser/Parser.scala @@ -1,6 +1,7 @@ package falstar.parser import java.io.File +import scala.util.DynamicVariable import falstar.falsification.Adaptive import falstar.falsification.Breach @@ -31,11 +32,13 @@ import falstar.hybrid.MatlabSystem sealed trait Command case object Flush extends Command case object Quit extends Command + case class Falsify(search: Falsification, sys: System, cfg: Config, phi: Formula, seed: Option[Long], repeat: Int, notes: Seq[(String, Any)], log: Option[String], report: Option[String]) extends Command +case class Validate(log: Option[String], report: Option[String], parser: Parser) extends Command case class Simulate(sys: System, phi: Formula, ps: Input, us: Signal, T: Time) extends Command case class Robustness(phi: Formula, us: Signal, ys: Signal, T: Time) extends Command -class Parser(directory: String) { +object Parser { case class State( var search: Falsification, var system: System, @@ -55,10 +58,18 @@ class Parser(directory: String) { object State { def empty = State(null, null, null, Map(), Map(), Map(), Map(), None, 1, None, None, Seq()) } +} + +class Parser(_directory: String) { + outer => + import Parser._ + object directory extends DynamicVariable(_directory) var stack = List(State.empty) def state = stack.head + def copy = new Parser(_directory) { stack = List(outer.state.copy()); } + def expand(node: Syntax, env: Map[String, Syntax]): Syntax = node match { case Identifier(name) if env contains name => env(name) @@ -91,7 +102,7 @@ class Parser(directory: String) { object Path { def unapply(node: Syntax): Option[String] = node match { case Literal(value: String) => - Some(directory + "/" + value) + Some(directory.value + "/" + value) case _ => None } @@ -252,9 +263,12 @@ class Parser(directory: String) { } def top(syntax: Syntax): Seq[Command] = expand(syntax, state.defines) match { - case Node(Keyword("include"), Path(file)) => - val node = read(new File(file)) - parse(node) + case Node(Keyword("include"), Path(name)) => + val file = new File(name) + val node = read(file) + directory.withValue(file.getParent) { + parse(node) + } case Node(Keyword("define"), Identifier(name), body) => state.defines += name -> body @@ -337,6 +351,10 @@ class Parser(directory: String) { case Node(Keyword("falsify"), phis @ _*) => phis map { phi => Falsify(state.search, state.system, state.config, formula(phi), state.seed, state.repeat, state.notes, state.log, state.report) } + case Node(Keyword("validate")) => + val cmd = Validate(state.log, state.report, this.copy) + Seq(cmd) + case Node(Keyword("simulate"), Number(time), phi, params, input @ _*) => Seq(Simulate(state.system, formula(phi), vector(params), signal(input), time)) diff --git a/falstar/src/falstar/parser/Scanner.flex b/falstar/src/falstar/parser/Scanner.flex index 7a41b06..18a87f8 100644 --- a/falstar/src/falstar/parser/Scanner.flex +++ b/falstar/src/falstar/parser/Scanner.flex @@ -33,7 +33,7 @@ AlphaNum = {Alpha}|{Num}|"-" Operators = "<" | ">" | "<=" | ">=" | "+" | "-" | "*" | "/" | abs Connectives = "!" | "=>" | "||" | "&&" | "==" | "!=" | true | false | not | implies | and | or | always | eventually | next | in -Toplevel = include | define-system | define | push | pop | load | latex | set-solver | select-system | set-requirements | set-repeat | set-seed | clear-seed | set-log | flush-log | clear-log | set-report | clear-report | falsify | estimate | simulate | robustness | quit | notes +Toplevel = include | define-system | define | push | pop | load | latex | set-solver | select-system | set-requirements | set-repeat | set-seed | clear-seed | set-log | flush-log | clear-log | set-report | clear-report | falsify | validate | estimate | simulate | robustness | quit | notes Simulink = matlab | simulink | parameters | inputs | outputs | option | constant | piecewise-constant Keyword = "(" | ")" | {Operators} | {Connectives} | {Toplevel} | {Simulink} diff --git a/falstar/src/falstar/parser/Scanner.java b/falstar/src/falstar/parser/Scanner.java index e7da800..5771411 100644 --- a/falstar/src/falstar/parser/Scanner.java +++ b/falstar/src/falstar/parser/Scanner.java @@ -1,6 +1,6 @@ // DO NOT EDIT // Generated by JFlex 1.8.2 http://jflex.de/ -// source: src/main/scala/falstar/parser/Scanner.flex +// source: falstar/src/falstar/parser/Scanner.flex package falstar.parser; @@ -99,12 +99,12 @@ private static int zzUnpackcmap_blocks(String packed, int offset, int [] result) private static final String ZZ_ACTION_PACKED_0 = "\2\0\1\1\2\2\1\3\2\1\2\3\1\4\1\5"+ - "\1\1\20\6\1\1\2\7\1\0\1\10\3\0\13\6"+ - "\1\3\6\6\1\3\12\6\1\4\16\6\1\3\63\6"+ + "\1\1\21\6\1\1\2\7\1\0\1\10\3\0\13\6"+ + "\1\3\6\6\1\3\13\6\1\4\16\6\1\3\65\6"+ "\1\3\60\6"; private static int [] zzUnpackAction() { - int [] result = new int[182]; + int [] result = new int[186]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -132,29 +132,30 @@ private static int zzUnpackAction(String packed, int offset, int [] result) { "\0\0\0\53\0\126\0\126\0\201\0\254\0\327\0\u0102"+ "\0\126\0\u012d\0\u0158\0\126\0\u0183\0\u01ae\0\u01d9\0\u0204"+ "\0\u022f\0\u025a\0\u0285\0\u02b0\0\u02db\0\u0306\0\u0331\0\u035c"+ - "\0\u0387\0\u03b2\0\u03dd\0\u0408\0\u0433\0\u045e\0\126\0\u0489"+ - "\0\327\0\126\0\u04b4\0\u04df\0\u050a\0\u0535\0\u0560\0\u058b"+ + "\0\u0387\0\u03b2\0\u03dd\0\u0408\0\u0433\0\u045e\0\u0489\0\126"+ + "\0\u04b4\0\327\0\126\0\u04df\0\u050a\0\u0535\0\u0560\0\u058b"+ "\0\u05b6\0\u05e1\0\u060c\0\u0637\0\u0662\0\u068d\0\u06b8\0\u06e3"+ - "\0\u070e\0\u0739\0\u0764\0\u078f\0\u07ba\0\u07e5\0\u0810\0\u01ae"+ - "\0\u083b\0\u0866\0\u0891\0\u08bc\0\u08e7\0\u0912\0\u093d\0\u0968"+ - "\0\u0993\0\u09be\0\u050a\0\u09e9\0\u0a14\0\u0a3f\0\u0a6a\0\u0a95"+ + "\0\u070e\0\u0739\0\u0764\0\u078f\0\u07ba\0\u07e5\0\u0810\0\u083b"+ + "\0\u01ae\0\u0866\0\u0891\0\u08bc\0\u08e7\0\u0912\0\u093d\0\u0968"+ + "\0\u0993\0\u09be\0\u09e9\0\u0a14\0\u0535\0\u0a3f\0\u0a6a\0\u0a95"+ "\0\u0ac0\0\u0aeb\0\u0b16\0\u0b41\0\u0b6c\0\u0b97\0\u0bc2\0\u0bed"+ "\0\u0c18\0\u0c43\0\u0c6e\0\u0c99\0\u0cc4\0\u0cef\0\u0d1a\0\u0d45"+ "\0\u0d70\0\u0d9b\0\u0dc6\0\u0df1\0\u0e1c\0\u0e47\0\u0e72\0\u0e9d"+ "\0\u0ec8\0\u0ef3\0\u0f1e\0\u0f49\0\u0f74\0\u0f9f\0\u0fca\0\u0ff5"+ "\0\u1020\0\u104b\0\u1076\0\u10a1\0\u10cc\0\u10f7\0\u1122\0\u114d"+ - "\0\u1178\0\u11a3\0\u11ce\0\u11f9\0\u1224\0\u124f\0\u127a\0\u0c43"+ - "\0\u12a5\0\u12d0\0\u12fb\0\u1326\0\u1351\0\u137c\0\u13a7\0\u13d2"+ + "\0\u1178\0\u11a3\0\u11ce\0\u11f9\0\u1224\0\u124f\0\u127a\0\u12a5"+ + "\0\u12d0\0\u12fb\0\u1326\0\u0c99\0\u1351\0\u137c\0\u13a7\0\u13d2"+ "\0\u13fd\0\u1428\0\u1453\0\u147e\0\u14a9\0\u14d4\0\u14ff\0\u152a"+ - "\0\u1555\0\u1580\0\u15ab\0\u15d6\0\u1601\0\u14d4\0\u162c\0\u1657"+ - "\0\u1682\0\u16ad\0\u16d8\0\u1703\0\u172e\0\u1759\0\u1784\0\u17af"+ + "\0\u1555\0\u1580\0\u15ab\0\u15d6\0\u1601\0\u162c\0\u1657\0\u1682"+ + "\0\u16ad\0\u1580\0\u16d8\0\u1703\0\u172e\0\u1759\0\u1784\0\u17af"+ "\0\u17da\0\u1805\0\u1830\0\u185b\0\u1886\0\u18b1\0\u18dc\0\u1907"+ "\0\u1932\0\u195d\0\u1988\0\u19b3\0\u19de\0\u1a09\0\u1a34\0\u1a5f"+ "\0\u1a8a\0\u1ab5\0\u1ae0\0\u1b0b\0\u1b36\0\u1b61\0\u1b8c\0\u1bb7"+ - "\0\u1be2\0\u1c0d\0\u1c38\0\u1c63\0\u1c8e\0\u1cb9"; + "\0\u1be2\0\u1c0d\0\u1c38\0\u1c63\0\u1c8e\0\u1cb9\0\u1ce4\0\u1d0f"+ + "\0\u1d3a\0\u1d65"; private static int [] zzUnpackRowMap() { - int [] result = new int[182]; + int [] result = new int[186]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -181,215 +182,220 @@ private static int zzUnpackRowMap(String packed, int offset, int [] result) { "\1\11\1\12\1\3\1\13\1\14\1\15\1\6\1\16"+ "\1\3\1\17\1\16\1\20\1\21\1\22\1\23\2\16"+ "\1\24\1\16\1\25\1\26\1\27\1\30\1\31\1\32"+ - "\1\33\1\34\1\35\5\16\1\36\2\4\1\37\2\0"+ - "\1\40\45\4\55\0\1\4\66\0\1\11\34\0\7\41"+ - "\1\42\11\41\1\43\31\41\10\0\1\11\54\0\1\44"+ - "\1\0\1\13\3\0\1\16\1\0\30\16\13\0\1\44"+ - "\1\45\1\13\3\0\1\16\1\0\30\16\17\0\2\11"+ - "\45\0\1\16\1\0\1\16\3\0\1\16\1\0\30\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\1\16"+ - "\1\46\10\16\1\47\1\16\1\50\13\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\12\16\1\51\2\16"+ - "\1\52\12\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\4\16\1\53\23\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\21\16\1\54\2\16\1\55\3\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\1\56"+ - "\11\16\1\57\15\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\13\16\1\60\1\61\13\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\1\62\14\16\1\63"+ + "\1\33\1\34\1\35\1\16\1\36\3\16\1\37\2\4"+ + "\1\40\2\0\1\41\45\4\55\0\1\4\66\0\1\11"+ + "\34\0\7\42\1\43\11\42\1\44\31\42\10\0\1\11"+ + "\54\0\1\45\1\0\1\13\3\0\1\16\1\0\30\16"+ + "\13\0\1\45\1\46\1\13\3\0\1\16\1\0\30\16"+ + "\17\0\2\11\45\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\30\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\1\16\1\47\10\16\1\50\1\16\1\51\13\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\12\16"+ + "\1\52\2\16\1\53\12\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\4\16\1\54\23\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\21\16\1\55\2\16"+ + "\1\56\3\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\1\57\11\16\1\60\15\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\13\16\1\61\1\62\13\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\1\63"+ + "\14\16\1\64\12\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\1\65\27\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\4\16\1\66\10\16\1\67\12\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\16\16"+ + "\1\70\1\16\1\71\2\16\1\72\4\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\1\73\7\16\1\74"+ + "\4\16\1\75\5\16\1\76\4\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\23\16\1\77\4\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\15\16\1\100"+ "\12\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\1\64\27\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\4\16\1\65\10\16\1\66\12\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\16\16\1\67\1\16"+ - "\1\70\2\16\1\71\4\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\1\72\7\16\1\73\4\16\1\74"+ - "\5\16\1\75\4\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\23\16\1\76\4\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\15\16\1\77\12\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\4\16\1\100"+ - "\3\16\1\101\17\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\20\16\1\102\7\16\53\0\1\11\2\0"+ - "\1\37\50\0\2\41\4\0\45\41\12\0\1\44\1\0"+ - "\1\44\3\0\1\16\1\0\30\16\15\0\1\103\50\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\21\16\1\70"+ + "\4\16\1\101\3\16\1\102\17\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\20\16\1\103\7\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\1\104\27\16"+ + "\53\0\1\11\2\0\1\40\50\0\2\42\4\0\45\42"+ + "\12\0\1\45\1\0\1\45\3\0\1\16\1\0\30\16"+ + "\15\0\1\105\50\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\21\16\1\71\6\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\25\16\1\106\2\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\3\16\1\71\24\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\4\16"+ + "\1\107\23\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\14\16\1\110\13\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\5\16\1\111\22\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\22\16\1\112\5\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\4\16"+ + "\1\113\23\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\12\16\1\114\15\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\23\16\1\115\4\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\16\16\1\116\11\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\2\16"+ + "\1\117\13\16\1\120\11\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\22\16\1\121\5\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\1\51\27\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\22\16\1\122"+ + "\5\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\26\16\1\123\1\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\22\16\1\124\5\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\22\16\1\125\5\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\22\16\1\126"+ + "\5\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\20\16\1\127\7\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\4\16\1\130\23\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\16\16\1\71\11\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\21\16\1\131"+ "\6\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\25\16\1\104\2\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\3\16\1\70\24\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\4\16\1\105\23\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\14\16\1\106"+ + "\10\16\1\123\17\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\1\16\1\132\26\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\12\16\1\133\7\16\1\134"+ + "\5\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\13\16\1\135\14\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\23\16\1\136\4\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\12\16\1\137\15\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\1\140\27\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\1\141"+ + "\27\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\21\16\1\142\6\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\10\16\1\143\17\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\10\16\1\144\17\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\14\16\1\145"+ "\13\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\5\16\1\107\22\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\22\16\1\110\5\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\4\16\1\111\23\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\12\16\1\112"+ + "\21\16\1\146\6\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\21\16\1\147\6\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\12\16\1\150\15\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\12\16\1\151"+ "\15\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\23\16\1\113\4\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\16\16\1\114\11\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\2\16\1\115\13\16\1\116"+ - "\11\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\22\16\1\117\5\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\1\50\27\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\22\16\1\120\5\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\26\16\1\121\1\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\22\16"+ - "\1\122\5\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\22\16\1\123\5\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\22\16\1\124\5\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\20\16\1\125\7\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\4\16"+ - "\1\126\23\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\16\16\1\70\11\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\21\16\1\127\6\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\10\16\1\121\17\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\1\16"+ - "\1\130\26\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\12\16\1\131\7\16\1\132\5\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\13\16\1\133\14\16"+ + "\23\16\1\152\4\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\4\16\1\153\23\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\12\16\1\154\15\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\22\16\1\71"+ + "\5\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\4\16\1\47\23\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\10\16\1\155\17\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\16\16\1\120\11\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\1\156\27\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\2\16"+ + "\1\157\25\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\7\16\1\71\20\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\23\16\1\160\4\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\4\16\1\161\23\16"+ + "\13\0\1\162\1\0\1\16\3\0\1\16\1\0\30\16"+ "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\23\16"+ - "\1\134\4\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\1\135\27\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\1\136\27\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\21\16\1\137\6\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\10\16\1\140\17\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\10\16"+ - "\1\141\17\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\14\16\1\142\13\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\21\16\1\143\6\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\21\16\1\144\6\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\12\16"+ - "\1\145\15\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\12\16\1\146\15\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\23\16\1\147\4\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\4\16\1\150\23\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\12\16"+ - "\1\151\15\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\22\16\1\70\5\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\4\16\1\46\23\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\10\16\1\152\17\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\16\16"+ - "\1\116\11\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\1\153\27\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\2\16\1\154\25\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\7\16\1\70\20\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\23\16\1\155"+ + "\1\163\4\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\4\16\1\71\23\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\10\16\1\164\17\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\27\16\1\47\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\20\16\1\165"+ + "\7\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\22\16\1\166\5\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\14\16\1\167\13\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\13\16\1\170\14\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\22\16\1\171"+ + "\5\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\4\16\1\71\3\16\1\172\17\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\7\16\1\173\20\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\10\16\1\174"+ + "\17\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\23\16\1\175\4\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\22\16\1\47\5\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\26\16\1\71\1\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\1\176\27\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\15\16"+ + "\1\177\12\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\13\16\1\200\14\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\4\16\1\201\23\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\21\16\1\202\6\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\2\16"+ + "\1\203\25\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\12\16\1\204\5\16\1\205\1\206\6\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\12\16\1\207"+ + "\15\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\3\16\1\170\24\16\13\0\1\210\1\0\1\16\3\0"+ + "\1\16\1\0\30\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\1\211\27\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\4\16\1\212\23\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\1\213\27\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\23\16\1\214"+ "\4\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\4\16\1\156\23\16\13\0\1\157\1\0\1\16\3\0"+ + "\5\16\1\215\22\16\13\0\1\216\1\0\1\16\3\0"+ "\1\16\1\0\30\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\23\16\1\160\4\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\4\16\1\70\23\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\27\16\1\46"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\20\16"+ - "\1\161\7\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\22\16\1\162\5\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\14\16\1\163\13\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\13\16\1\164\14\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\22\16"+ - "\1\165\5\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\4\16\1\70\3\16\1\166\17\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\7\16\1\167\20\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\10\16"+ - "\1\170\17\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\23\16\1\171\4\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\22\16\1\46\5\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\26\16\1\70\1\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\1\172"+ - "\27\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\15\16\1\173\12\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\13\16\1\174\14\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\4\16\1\175\23\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\21\16\1\176"+ - "\6\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\2\16\1\177\25\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\12\16\1\200\5\16\1\201\1\202\6\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\12\16"+ - "\1\203\15\16\13\0\1\204\1\0\1\16\3\0\1\16"+ - "\1\0\30\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\1\205\27\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\4\16\1\206\23\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\1\207\27\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\23\16\1\210\4\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\5\16"+ - "\1\211\22\16\13\0\1\212\1\0\1\16\3\0\1\16"+ - "\1\0\30\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\3\16\1\134\24\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\1\16\1\70\26\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\14\16\1\70\13\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\4\16"+ - "\1\213\23\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\25\16\1\214\2\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\22\16\1\215\5\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\22\16\1\216\5\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\15\16"+ - "\1\217\12\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\4\16\1\220\23\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\4\16\1\221\10\16\1\222\12\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\1\207"+ - "\7\16\1\223\17\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\12\16\1\200\5\16\1\224\1\225\6\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\14\16"+ - "\1\121\13\16\13\0\1\226\1\0\1\16\3\0\1\16"+ - "\1\0\30\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\22\16\1\134\5\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\1\227\27\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\27\16\1\70\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\12\16\1\200\15\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\22\16"+ - "\1\230\5\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\10\16\1\231\17\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\14\16\1\232\13\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\6\16\1\70\21\16"+ - "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\16\16"+ - "\1\233\1\234\10\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\4\16\1\50\23\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\12\16\1\235\15\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\14\16\1\236"+ + "\1\16\1\0\3\16\1\136\24\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\1\16\1\71\26\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\14\16\1\71"+ "\13\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\4\16\1\237\23\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\4\16\1\221\23\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\21\16\1\240\6\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\12\16\1\241"+ + "\4\16\1\217\23\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\25\16\1\220\2\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\22\16\1\221\5\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\22\16\1\222"+ + "\5\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\15\16\1\223\12\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\4\16\1\224\23\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\4\16\1\225\10\16\1\226"+ + "\12\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\1\213\7\16\1\227\17\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\12\16\1\204\5\16\1\230\1\231"+ + "\6\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\14\16\1\123\13\16\13\0\1\232\1\0\1\16\3\0"+ + "\1\16\1\0\30\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\22\16\1\136\5\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\1\233\27\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\27\16\1\71\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\12\16\1\204"+ "\15\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\4\16\1\242\23\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\21\16\1\243\6\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\4\16\1\244\23\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\4\16\1\245"+ - "\10\16\1\246\12\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\23\16\1\247\4\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\24\16\1\250\3\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\11\16\1\70"+ - "\16\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\16\16\1\251\11\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\27\16\1\252\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\12\16\1\211\15\16\13\0\1\16"+ - "\1\0\1\16\3\0\1\16\1\0\20\16\1\46\7\16"+ + "\22\16\1\234\5\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\10\16\1\235\17\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\14\16\1\236\13\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\6\16\1\71"+ + "\21\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ + "\16\16\1\237\1\240\10\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\4\16\1\51\23\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\12\16\1\241\15\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\14\16"+ + "\1\242\13\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\4\16\1\243\23\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\4\16\1\225\23\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\21\16\1\244\6\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\12\16"+ + "\1\245\15\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\4\16\1\246\23\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\21\16\1\247\6\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\4\16\1\250\23\16"+ "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\4\16"+ - "\1\253\23\16\13\0\1\16\1\0\1\16\3\0\1\16"+ - "\1\0\21\16\1\46\6\16\13\0\1\16\1\0\1\16"+ - "\3\0\1\16\1\0\1\121\27\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\20\16\1\121\7\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\10\16\1\254"+ - "\17\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\4\16\1\255\23\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\15\16\1\246\12\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\21\16\1\256\6\16\13\0"+ - "\1\257\1\0\1\16\3\0\1\16\1\0\30\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\20\16\1\260"+ + "\1\251\10\16\1\252\12\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\23\16\1\253\4\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\24\16\1\254\3\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\11\16"+ + "\1\71\16\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\16\16\1\255\11\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\27\16\1\256\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\12\16\1\215\15\16\13\0"+ + "\1\16\1\0\1\16\3\0\1\16\1\0\20\16\1\47"+ "\7\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\20\16\1\70\7\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\22\16\1\261\5\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\2\16\1\262\25\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\4\16\1\263"+ - "\23\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\4\16\1\264\23\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\15\16\1\52\12\16\13\0\1\16\1\0"+ - "\1\16\3\0\1\16\1\0\13\16\1\265\14\16\13\0"+ - "\1\16\1\0\1\16\3\0\1\16\1\0\13\16\1\70"+ - "\14\16\13\0\1\16\1\0\1\16\3\0\1\16\1\0"+ - "\4\16\1\266\23\16\13\0\1\16\1\0\1\16\3\0"+ - "\1\16\1\0\14\16\1\147\13\16\1\0"; + "\4\16\1\257\23\16\13\0\1\16\1\0\1\16\3\0"+ + "\1\16\1\0\21\16\1\47\6\16\13\0\1\16\1\0"+ + "\1\16\3\0\1\16\1\0\1\123\27\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\20\16\1\123\7\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\10\16"+ + "\1\260\17\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\4\16\1\261\23\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\15\16\1\252\12\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\21\16\1\262\6\16"+ + "\13\0\1\263\1\0\1\16\3\0\1\16\1\0\30\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\20\16"+ + "\1\264\7\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\20\16\1\71\7\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\22\16\1\265\5\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\2\16\1\266\25\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\4\16"+ + "\1\267\23\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\4\16\1\270\23\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\15\16\1\53\12\16\13\0\1\16"+ + "\1\0\1\16\3\0\1\16\1\0\13\16\1\271\14\16"+ + "\13\0\1\16\1\0\1\16\3\0\1\16\1\0\13\16"+ + "\1\71\14\16\13\0\1\16\1\0\1\16\3\0\1\16"+ + "\1\0\4\16\1\272\23\16\13\0\1\16\1\0\1\16"+ + "\3\0\1\16\1\0\14\16\1\152\13\16\1\0"; private static int [] zzUnpackTrans() { - int [] result = new int[7396]; + int [] result = new int[7568]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -432,11 +438,11 @@ private static int zzUnpackTrans(String packed, int offset, int [] result) { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\2\0\2\11\4\1\1\11\2\1\1\11\22\1\1\11"+ - "\1\1\1\0\1\11\3\0\221\1"; + "\2\0\2\11\4\1\1\11\2\1\1\11\23\1\1\11"+ + "\1\1\1\0\1\11\3\0\224\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[182]; + int [] result = new int[186]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; diff --git a/falstar/src/falstar/parser/package.scala b/falstar/src/falstar/parser/package.scala index 5943002..a930b42 100644 --- a/falstar/src/falstar/parser/package.scala +++ b/falstar/src/falstar/parser/package.scala @@ -14,15 +14,11 @@ package object parser { val parent = file.getParent() val syntax = read(file) val parser = new Parser(parent) - val problems = parser.parse(syntax) - - problems + parser.parse(syntax) } def formula(ports: Map[String, Port], phi: String) = { - val tokens = scan(new StringReader(phi)) - val args = readAll(tokens) - val node = Node(args: _*) + val node = read(phi) val parser = new Parser("") parser.formula(ports: Map[String, Port], node: Syntax) } @@ -33,6 +29,11 @@ package object parser { Node(args: _*) } + def read(string: String) = { + val tokens = scan(new StringReader(string)) + val args = readAll(tokens) + Node(args: _*) + } def scan(reader: Reader) = { val scanner = new Scanner(reader) diff --git a/falstar/src/falstar/util/Table.scala b/falstar/src/falstar/util/Table.scala index 694b16b..d95b669 100644 --- a/falstar/src/falstar/util/Table.scala +++ b/falstar/src/falstar/util/Table.scala @@ -10,6 +10,7 @@ import java.io.BufferedReader import org.apache.commons.csv.CSVPrinter import org.apache.commons.csv.CSVParser import org.apache.commons.csv.CSVFormat +import org.apache.commons.csv.QuoteMode case class Row(data: Seq[(String, Any)]) { val (keys, values) = data.unzip @@ -34,8 +35,9 @@ object Table { if (parent != null) parent.mkdirs() + val format = CSVFormat.RFC4180.withQuoteMode(QuoteMode.NON_NUMERIC) val writer = new FileWriter(file, false) - val printer = new CSVPrinter(writer, CSVFormat.RFC4180) + val printer = new CSVPrinter(writer, format) var first: Boolean = true printer.printRecord(columns: _*) @@ -65,8 +67,9 @@ object Table { def read(name: String): Table = { import scala.collection.JavaConverters._ + val format = CSVFormat.DEFAULT val reader = new FileReader(name) - val parser = new CSVParser(reader, CSVFormat.RFC4180) + val parser = new CSVParser(reader, format) val records = parser.iterator.asScala if(records.isEmpty) { @@ -74,7 +77,7 @@ object Table { } else { val header = records.next() val columns = header.iterator.asScala.toList - println(columns) + val rows = for(record <- records) yield { val entries = record.iterator.asScala.toSeq Row(columns zip entries) diff --git a/falstar/src/falstar/util/package.scala b/falstar/src/falstar/util/package.scala index 81fb1f6..fc24bf5 100644 --- a/falstar/src/falstar/util/package.scala +++ b/falstar/src/falstar/util/package.scala @@ -8,7 +8,7 @@ package object util { def now() = { import java.text.SimpleDateFormat import java.util.Date - val df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm") + val df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") df.format(new Date()); }