diff --git a/.gitignore b/.gitignore index 88fb07f..e050faa 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ buildall.tmp.* target/ pom.xml .calva/ - +.clj-kondo/ +.lsp/ .nrepl-port diff --git a/docs/cloverage/coverage.css b/docs/cloverage/coverage.css new file mode 100644 index 0000000..2be4e57 --- /dev/null +++ b/docs/cloverage/coverage.css @@ -0,0 +1,40 @@ +.covered { + font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace; + background-color: #558B55; +} + +.not-covered { + font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace; + background-color: red; +} + +.partial { + font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace; + background-color: orange; +} + +.not-tracked { + font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace; +} + +.blank { + font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace; +} + +td { + padding-right: 10px; +} + +td.with-bar { + width: 250px; + text-align: center; +} + +td.with-number { + text-align: right; +} + +td.ns-name { + min-width: 150px; + padding-right: 25px; +} diff --git a/docs/cloverage/index.html b/docs/cloverage/index.html new file mode 100644 index 0000000..90cbc82 --- /dev/null +++ b/docs/cloverage/index.html @@ -0,0 +1,149 @@ + + + + + Coverage Summary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Namespace Forms Forms % Lines Lines %TotalBlankInstrumented
mw-parser.bulk
60
100.00 %
11
100.00 %62711
mw-parser.core
1193
49
96.05 %
207
35
3
98.78 %45141245
mw-parser.declarative
181
13
93.30 %
22
1
1
95.83 %1571024
mw-parser.errors
113
12
90.40 %
19
2
100.00 %68921
mw-parser.flow
74
9
89.16 %
18
3
85.71 %67521
mw-parser.generate
732
187
79.65 %
139
6
30
82.86 %31832175
mw-parser.simplify
72
19
79.12 %
19
1
5
80.00 %84725
mw-parser.utils
73
5
93.59 %
18
2
100.00 %641020
Totals:89.47 %92.25 %
+ + diff --git a/docs/cloverage/mw_parser/bulk.clj.html b/docs/cloverage/mw_parser/bulk.clj.html new file mode 100644 index 0000000..f3b31f2 --- /dev/null +++ b/docs/cloverage/mw_parser/bulk.clj.html @@ -0,0 +1,194 @@ + + + + mw_parser/bulk.clj + + + + 001  (ns ^{:doc "parse multiple rules from a stream, possibly a file." +
+ + 002        :author "Simon Brooke"} +
+ + 003    mw-parser.bulk +
+ + 004    (:use mw-parser.core +
+ + 005          mw-engine.utils +
+ + 006          clojure.java.io +
+ + 007          [clojure.string :only [split trim]]) +
+ + 008    (:import (java.io BufferedReader StringReader))) +
+ + 009   +
+ + 010  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 011  ;;;; +
+ + 012  ;;;; mw-parser: a rule parser for MicroWorld. +
+ + 013  ;;;; +
+ + 014  ;;;; This program is free software; you can redistribute it and/or +
+ + 015  ;;;; modify it under the terms of the GNU General Public License +
+ + 016  ;;;; as published by the Free Software Foundation; either version 2 +
+ + 017  ;;;; of the License, or (at your option) any later version. +
+ + 018  ;;;; +
+ + 019  ;;;; This program is distributed in the hope that it will be useful, +
+ + 020  ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +
+ + 021  ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +
+ + 022  ;;;; GNU General Public License for more details. +
+ + 023  ;;;; +
+ + 024  ;;;; You should have received a copy of the GNU General Public License +
+ + 025  ;;;; along with this program; if not, write to the Free Software +
+ + 026  ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, +
+ + 027  ;;;; USA. +
+ + 028  ;;;; +
+ + 029  ;;;; Copyright (C) 2014 Simon Brooke +
+ + 030  ;;;; +
+ + 031  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 032   +
+ + 033   +
+ + 034  (defn comment? +
+ + 035    "Is this `line` a comment?" +
+ + 036    [line] +
+ + 037    (or (empty? (trim line)) (member? (first line) '(nil \# \;)))) +
+ + 038   +
+ + 039  (defn parse-string +
+ + 040    "Parse rules from successive lines in this `string`, assumed to have multiple +
+ + 041     lines delimited by the new-line character. Return a list of S-expressions." +
+ + 042    [string] +
+ + 043          ;; TODO: tried to do this using with-open, but couldn't make it work. +
+ + 044    (map #(parse-rule (trim %)) (remove comment? (split string #"\n")))) +
+ + 045   +
+ + 046  (defn parse-file +
+ + 047    "Parse rules from successive lines in the file loaded from this `filename`. +
+ + 048     Return a list of S-expressions." +
+ + 049    [filename] +
+ + 050    (parse-string (slurp filename))) +
+ + 051   +
+ + 052  (defn compile-string +
+ + 053    "Compile each non-comment line of this `string` into an executable anonymous +
+ + 054     function, and return the sequence of such functions." +
+ + 055    [string] +
+ + 056    (map #(compile-rule % true) (remove comment? (split string #"\n")))) +
+ + 057   +
+ + 058  (defn compile-file +
+ + 059    "Compile each non-comment line of the file indicated by this `filename` into +
+ + 060     an executable anonymous function, and return the sequence of such functions." +
+ + 061    [filename] +
+ + 062    (compile-string (slurp filename))) +
+ + diff --git a/docs/cloverage/mw_parser/core.clj.html b/docs/cloverage/mw_parser/core.clj.html new file mode 100644 index 0000000..c7f4a54 --- /dev/null +++ b/docs/cloverage/mw_parser/core.clj.html @@ -0,0 +1,1361 @@ + + + + mw_parser/core.clj + + + + 001  (ns ^{:doc "A very simple parser which parses production rules." +
+ + 002        :author "Simon Brooke"} +
+ + 003    mw-parser.core +
+ + 004    (:use mw-engine.utils +
+ + 005          [clojure.string :only [split trim triml]]) +
+ + 006    (:gen-class) +
+ + 007  ) +
+ + 008   +
+ + 009  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 010  ;;;; +
+ + 011  ;;;; mw-parser: a rule parser for MicroWorld. +
+ + 012  ;;;; +
+ + 013  ;;;; This program is free software; you can redistribute it and/or +
+ + 014  ;;;; modify it under the terms of the GNU General Public License +
+ + 015  ;;;; as published by the Free Software Foundation; either version 2 +
+ + 016  ;;;; of the License, or (at your option) any later version. +
+ + 017  ;;;; +
+ + 018  ;;;; This program is distributed in the hope that it will be useful, +
+ + 019  ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +
+ + 020  ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +
+ + 021  ;;;; GNU General Public License for more details. +
+ + 022  ;;;; +
+ + 023  ;;;; You should have received a copy of the GNU General Public License +
+ + 024  ;;;; along with this program; if not, write to the Free Software +
+ + 025  ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, +
+ + 026  ;;;; USA. +
+ + 027  ;;;; +
+ + 028  ;;;; Copyright (C) 2014 Simon Brooke +
+ + 029  ;;;; +
+ + 030  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 031  ;;;; +
+ + 032  ;;;; A very simple parser which parses production rules of the following forms: +
+ + 033  ;;;; +
+ + 034  ;;;; * "if altitude is less than 100 and state is forest then state should be climax and deer should be 3" +
+ + 035  ;;;; * "if altitude is 100 or fertility is 25 then state should be heath and fertility should be 24.3" +
+ + 036  ;;;; * "if altitude is 100 or fertility is 25 then state should be heath" +
+ + 037  ;;;; * "if deer is more than 2 and wolves is 0 and fertility is more than 20 then deer should be deer + 2" +
+ + 038  ;;;; * "if deer is more than 1 and wolves is more than 1 then deer should be deer - wolves" +
+ + 039  ;;;; * "if state is grassland and 4 neighbours have state equal to water then state should be village" +
+ + 040  ;;;; * "if state is forest and fertility is between 55 and 75 then state should be climax" +
+ + 041  ;;;; * "if 6 neighbours have state equal to water then state should be village" +
+ + 042  ;;;; * "if state is in grassland or pasture or heath and 4 neighbours are water then state should be village" +
+ + 043  ;;;; * "if state is forest or state is climax and some neighbours have state equal to fire then 3 in 5 chance that state should be fire" +
+ + 044  ;;;; * "if state is pasture and more than 3 neighbours have state equal to scrub then state should be scrub" +
+ + 045  ;;;; * +
+ + 046  ;;;; +
+ + 047  ;;;; it generates rules in the form expected by `mw-engine.core`, q.v. +
+ + 048  ;;;; +
+ + 049  ;;;; It is, as I say, very simple; it generates a complete rule, or it fails completely, returning nil. +
+ + 050  ;;;; Very occasionally it generates a wrong rule - one which is not a correct translation of the rule +
+ + 051  ;;;; semantics - but that is buggy behaviour, which I'll try to fix over the next few weeks, not a +
+ + 052  ;;;; design fault. +
+ + 053  ;;;; +
+ + 054  ;;;; More significantly it does not generate useful error messages on failure. +
+ + 055  ;;;; +
+ + 056  ;;;; This parser is now obsolete, but is retained in the codebase for now in +
+ + 057  ;;;; case it is of use to anyone. Prefer the declarative.clj parser. +
+ + 058  ;;;; +
+ + 059  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 060   +
+ + 061  (declare parse-conditions) +
+ + 062  (declare parse-not-condition) +
+ + 063  (declare parse-simple-condition) +
+ + 064   +
+ + 065  ;; a regular expression which matches string representation of positive numbers +
+ + 066  (def re-number #"^[0-9.]*$") +
+ + 067   +
+ + 068  ;; error thrown when an attempt is made to set a reserved property +
+ + 069  (def reserved-properties-error +
+ + 070    "The properties 'x' and 'y' of a cell are reserved and should not be set in rule actions") +
+ + 071  ;; error thrown when a rule cannot be parsed +
+ + 072  (def bad-parse-error "I did not understand '%s'") +
+ + 073   +
+ + 074  (defn- keyword-or-numeric +
+ + 075    "If this token appears to represent an explicit number, return that number; +
+ + 076     otherwise, make a keyword of it and return that." +
+ + 077    [token] +
+ + 078    (cond +
+ + 079      (re-matches re-number token) (read-string token) +
+ + 080      (keyword? token) token +
+ + 081      true (keyword token))) +
+ + 082   +
+ + 083  ;; Generally all functions in this file with names beginning 'parse-' take a +
+ + 084  ;; sequence of tokens (and in some cases other optional arguments) and return a +
+ + 085  ;; vector comprising +
+ + 086  ;; +
+ + 087  ;; 1. A code fragment parsed from the front of the sequence of tokens, and +
+ + 088  ;; 2. the remaining tokens which were not consumed in constructing that fragment. +
+ + 089  ;; +
+ + 090  ;; In every case if the function cannot parse the desired construct from the +
+ + 091  ;; front of the sequence of tokens it returns nil. +
+ + 092   +
+ + 093   +
+ + 094  (defn parse-numeric-value +
+ + 095    "Parse a number." +
+ + 096    [[value & remainder]] +
+ + 097    (if (and value (re-matches re-number value)) [(read-string value) remainder])) +
+ + 098   +
+ + 099  (defn parse-property-int +
+ + 100    "Parse a token assumed to be the name of a property of the current cell, +
+ + 101    whose value is assumed to be an integer." +
+ + 102    [[value & remainder]] +
+ + 103    (if value [(list 'get-int 'cell (keyword value)) remainder])) +
+ + 104   +
+ + 105  (defn parse-property-value +
+ + 106    "Parse a token assumed to be the name of a property of the current cell." +
+ + 107    [[value & remainder]] +
+ + 108    (if value [(list (keyword value) 'cell) remainder])) +
+ + 109   +
+ + 110  (defn parse-token-value +
+ + 111    "Parse a token assumed to be a simple token value." +
+ + 112    [[value & remainder]] +
+ + 113    (if value [(keyword value) remainder])) +
+ + 114   +
+ + 115  (defn parse-simple-value +
+ + 116    "Parse a value from the first of these `tokens`. If `expect-int` is true, return +
+ + 117     an integer or something which will evaluate to an integer." +
+ + 118    ([tokens expect-int] +
+ + 119      (or +
+ + 120          (parse-numeric-value tokens) +
+ + 121          (cond expect-int +
+ + 122            (parse-property-int tokens) +
+ + 123            true (parse-token-value tokens)))) +
+ + 124    ([tokens] +
+ + 125      (parse-simple-value tokens false))) +
+ + 126   +
+ + 127  (defn gen-token-value +
+ + 128    "Parse a single value from this single token and return just the generated +
+ + 129     code, not a pair." +
+ + 130    [token expect-int] +
+ + 131    (first (parse-simple-value (list token) expect-int))) +
+ + 132   +
+ + 133  (defn parse-disjunct-value +
+ + 134    "Parse a list of values from among these `tokens`. If `expect-int` is true, return +
+ + 135     integers or things which will evaluate to integers." +
+ + 136    [[OR token & tokens] expect-int] +
+ + 137    (cond (member? OR '("or" "in")) +
+ + 138      (let [value (first (parse-simple-value (list token) expect-int)) +
+ + 139            seek-others (= (first tokens) "or")] +
+ + 140        (cond seek-others +
+ + 141          (let [[others remainder] (parse-disjunct-value tokens expect-int)] +
+ + 142            [(cons value others) remainder]) +
+ + 143          true +
+ + 144          [(list value) tokens])))) +
+ + 145   +
+ + 146  (defn parse-value +
+ + 147    "Parse a value from among these `tokens`. If `expect-int` is true, return +
+ + 148     an integer or something which will evaluate to an integer." +
+ + 149    ([tokens expect-int] +
+ + 150      (or +
+ + 151        (parse-disjunct-value tokens expect-int) +
+ + 152        (parse-simple-value tokens expect-int))) +
+ + 153    ([tokens] +
+ + 154      (parse-value tokens false))) +
+ + 155   +
+ + 156  (defn parse-member-condition +
+ + 157    "Parses a condition of the form '[property] in [value] or [value]...'" +
+ + 158    [[property IS IN & rest]] +
+ + 159    (if (and (member? IS '("is" "are")) (= IN "in")) +
+ + 160      (let [[l remainder] (parse-disjunct-value (cons "in" rest) false)] +
+ + 161        [(list 'member? (list (keyword property) 'cell) (list 'quote l)) remainder]))) +
+ + 162   +
+ + 163  (defn- parse-less-condition +
+ + 164    "Parse '[property] less than [value]'." +
+ + 165    [[property IS LESS THAN & rest]] +
+ + 166    (cond (and (member? IS '("is" "are")) (member? LESS '("less" "fewer")) (= THAN "than")) +
+ + 167      (let [[value remainder] (parse-value rest true)] +
+ + 168          [(list '< (list 'get-int 'cell (keyword property)) value) remainder]))) +
+ + 169   +
+ + 170  (defn- parse-more-condition +
+ + 171    "Parse '[property] more than [value]'." +
+ + 172    [[property IS MORE THAN & rest]] +
+ + 173    (cond (and (member? IS '("is" "are")) (member? MORE '("more" "greater")) (= THAN "than")) +
+ + 174      (let [[value remainder] (parse-value rest true)] +
+ + 175          [(list '> (list 'get-int 'cell (keyword property)) value) remainder]))) +
+ + 176   +
+ + 177  (defn- parse-between-condition +
+ + 178    [[p IS BETWEEN v1 AND v2 & rest]] +
+ + 179    (cond (and (member? IS '("is" "are")) (= BETWEEN "between") (= AND "and") (not (nil? v2))) +
+ + 180      (let [property (first (parse-simple-value (list p) true)) +
+ + 181            value1 (first (parse-simple-value (list v1) true)) +
+ + 182            value2 (first (parse-simple-value (list v2) true))] +
+ + 183        [(list 'or +
+ + 184              (list '< value1 property value2) +
+ + 185              (list '> value1 property value2)) rest]))) +
+ + 186   +
+ + 187  (defn- parse-is-condition +
+ + 188    "Parse clauses of the form 'x is y', 'x is in y or z...', +
+ + 189     'x is between y and z', 'x is more than y' or 'x is less than y'. +
+ + 190     It is necessary to disambiguate whether value is a numeric or keyword." +
+ + 191    [[property IS value & rest]] +
+ + 192    (cond +
+ + 193      (member? IS '("is" "are")) +
+ + 194      (let [tokens (cons property (cons value rest))] +
+ + 195        (cond +
+ + 196          (re-matches re-number value) [(list '= (list 'get-int 'cell (keyword property)) (read-string value)) rest] +
+ + 197          value [(list '= (list (keyword property) 'cell) (keyword value)) rest])))) +
+ + 198   +
+ + 199  (defn- parse-not-condition +
+ + 200    "Parse the negation of a simple condition." +
+ + 201    [[property IS NOT & rest]] +
+ + 202    (cond (and (member? IS '("is" "are")) (= NOT "not")) +
+ + 203      (let [partial (parse-simple-condition (cons property (cons "is" rest)))] +
+ + 204        (cond partial +
+ + 205          (let [[condition remainder] partial] +
+ + 206            [(list 'not condition) remainder]))))) +
+ + 207   +
+ + 208  (defn- gen-neighbours-condition +
+ + 209    ([comp1 quantity property value remainder comp2 distance] +
+ + 210      [(list comp1 +
+ + 211           (list 'count +
+ + 212                 (list 'get-neighbours-with-property-value 'world +
+ + 213                       '(cell :x) '(cell :y) distance +
+ + 214                       (keyword property) (keyword-or-numeric value) comp2)) +
+ + 215           quantity) +
+ + 216             remainder]) +
+ + 217    ([comp1 quantity property value remainder comp2] +
+ + 218      (gen-neighbours-condition comp1 quantity property value remainder comp2 1))) +
+ + 219   +
+ + 220  (defn parse-comparator-neighbours-condition +
+ + 221    "Parse conditions of the form '...more than 6 neighbours are [condition]'" +
+ + 222    [[MORE THAN n NEIGHBOURS WITHIN distance have-or-are & rest]] +
+ + 223    (let [quantity (first (parse-numeric-value (list n))) +
+ + 224          comparator (cond (= MORE "more") '> +
+ + 225                       (member? MORE '("fewer" "less")) '<)] +
+ + 226      (cond +
+ + 227        (not= WITHIN "within") +
+ + 228        (parse-comparator-neighbours-condition +
+ + 229          (flatten +
+ + 230            ;; two tokens were mis-parsed as 'within distance' that weren't +
+ + 231            ;; actually 'within' and a distance. Splice in 'within 1' and try +
+ + 232            ;; again. +
+ + 233            (list MORE THAN n NEIGHBOURS "within" "1" WITHIN distance have-or-are rest))) +
+ + 234        (and quantity +
+ + 235             comparator +
+ + 236             (= THAN "than") +
+ + 237             (= NEIGHBOURS "neighbours")) +
+ + 238        (cond +
+ + 239          (= have-or-are "are") +
+ + 240          (let [[value & remainder] rest +
+ + 241                dist (gen-token-value distance true)] +
+ + 242            (gen-neighbours-condition comparator quantity :state value remainder = dist)) +
+ + 243          (= have-or-are "have") +
+ + 244          (let [[property comp1 comp2 value & remainder] rest +
+ + 245                dist (gen-token-value distance true)] +
+ + 246            (cond (and (= comp1 "equal") (= comp2 "to")) +
+ + 247              (gen-neighbours-condition comparator quantity property +
+ + 248                                        value remainder = dist) +
+ + 249              (and (= comp1 "more") (= comp2 "than")) +
+ + 250              (gen-neighbours-condition comparator quantity property +
+ + 251                                        value remainder > dist) +
+ + 252              (and (= comp1 "less") (= comp2 "than")) +
+ + 253              (gen-neighbours-condition comparator quantity property +
+ + 254                                        value remainder < dist) +
+ + 255              )))))) +
+ + 256   +
+ + 257  (defn parse-some-neighbours-condition +
+ + 258    [[SOME NEIGHBOURS & rest]] +
+ + 259    (cond +
+ + 260      (and (= SOME "some") (= NEIGHBOURS "neighbours")) +
+ + 261      (parse-comparator-neighbours-condition (concat '("more" "than" "0" "neighbours") rest)))) +
+ + 262   +
+ + 263  (defn parse-simple-neighbours-condition +
+ + 264    "Parse conditions of the form '...6 neighbours are [condition]'" +
+ + 265    [[n NEIGHBOURS WITHIN distance have-or-are & rest]] +
+ + 266    (let [quantity (first (parse-numeric-value (list n)))] +
+ + 267      (cond +
+ + 268        (and quantity (= NEIGHBOURS "neighbours")) +
+ + 269        (cond +
+ + 270          (not= WITHIN "within") +
+ + 271          (parse-simple-neighbours-condition +
+ + 272            (flatten +
+ + 273              ;; two tokens were mis-parsed as 'within distance' that weren't +
+ + 274              ;; actually 'within' and a distance. Splice in 'within 1' and try +
+ + 275              ;; again. +
+ + 276              (list n NEIGHBOURS "within" "1" WITHIN distance have-or-are rest))) +
+ + 277          (= have-or-are "are") +
+ + 278          (let [[value & remainder] rest +
+ + 279                dist (gen-token-value distance true)] +
+ + 280            (gen-neighbours-condition '= quantity :state value remainder = dist)) +
+ + 281          (= have-or-are "have") +
+ + 282          (let [[property comp1 comp2 value & remainder] rest +
+ + 283                dist (gen-token-value distance true)] +
+ + 284            (cond (and (= comp1 "equal") (= comp2 "to")) +
+ + 285              (gen-neighbours-condition '= quantity property value remainder = +
+ + 286                                        dist) +
+ + 287              (and (= comp1 "more") (= comp2 "than")) +
+ + 288              (gen-neighbours-condition '= quantity property value remainder > +
+ + 289                                        dist) +
+ + 290              (and (= comp1 "less") (= comp2 "than")) +
+ + 291              (gen-neighbours-condition '= quantity property value remainder < +
+ + 292                                        dist) +
+ + 293              )))))) +
+ + 294   +
+ + 295  (defn parse-neighbours-condition +
+ + 296    "Parse conditions referring to neighbours" +
+ + 297    [tokens] +
+ + 298    (or +
+ + 299      (parse-simple-neighbours-condition tokens) +
+ + 300      (parse-comparator-neighbours-condition tokens) +
+ + 301      (parse-some-neighbours-condition tokens) +
+ + 302      )) +
+ + 303   +
+ + 304  (defn parse-simple-condition +
+ + 305    "Parse conditions of the form '[property] [comparison] [value]'." +
+ + 306    [tokens] +
+ + 307    (or +
+ + 308      (parse-neighbours-condition tokens) +
+ + 309      (parse-member-condition tokens) +
+ + 310      (parse-not-condition tokens) +
+ + 311      (parse-less-condition tokens) +
+ + 312      (parse-more-condition tokens) +
+ + 313      (parse-between-condition tokens) +
+ + 314      (parse-is-condition tokens))) +
+ + 315   +
+ + 316  (defn- parse-disjunction-condition +
+ + 317    "Parse '... or [condition]' from `tokens`, where `left` is the already parsed first disjunct." +
+ + 318    [left tokens] +
+ + 319    (let [partial (parse-conditions tokens)] +
+ + 320      (if partial +
+ + 321        (let [[right remainder] partial] +
+ + 322          [(list 'or left right) remainder])))) +
+ + 323   +
+ + 324  (defn- parse-conjunction-condition +
+ + 325    "Parse '... and [condition]' from `tokens`, where `left` is the already parsed first conjunct." +
+ + 326    [left tokens] +
+ + 327    (let [partial (parse-conditions tokens)] +
+ + 328      (if partial +
+ + 329        (let [[right remainder] partial] +
+ + 330          [(list 'and left right) remainder])))) +
+ + 331   +
+ + 332  (defn- parse-conditions +
+ + 333    "Parse conditions from `tokens`, where conditions may be linked by either 'and' or 'or'." +
+ + 334    [tokens] +
+ + 335    (let [partial (parse-simple-condition tokens)] +
+ + 336      (if partial +
+ + 337        (let [[left [next & remainder]] partial] +
+ + 338          (cond +
+ + 339            (= next "and") (parse-conjunction-condition left remainder) +
+ + 340            (= next "or") (parse-disjunction-condition left remainder) +
+ + 341            true partial))))) +
+ + 342   +
+ + 343  (defn- parse-left-hand-side +
+ + 344   "Parse the left hand side ('if...') of a production rule." +
+ + 345   [[IF & tokens]] +
+ + 346   (if +
+ + 347     (= IF "if") +
+ + 348     (parse-conditions tokens))) +
+ + 349   +
+ + 350  (defn- parse-arithmetic-action +
+ + 351    "Parse actions of the form '[property] should be [property] [arithmetic-operator] [value]', +
+ + 352     e.g. 'fertility should be fertility + 1', or 'deer should be deer - wolves'." +
+ + 353    [previous [prop1 SHOULD BE prop2 operator value & rest]] +
+ + 354    (cond +
+ + 355      (member? prop1 '("x" "y")) +
+ + 356      (throw +
+ + 357        (Exception. reserved-properties-error)) +
+ + 358      (and (= SHOULD "should") +
+ + 359             (= BE "be") +
+ + 360             (member? operator '("+" "-" "*" "/"))) +
+ + 361      [(list 'merge (or previous 'cell) +
+ + 362             {(keyword prop1) (list 'int +
+ + 363                                    (list (symbol operator) (list 'get-int 'cell (keyword prop2)) +
+ + 364                                          (cond +
+ + 365                                            (re-matches re-number value) (read-string value) +
+ + 366                                            true (list 'get-int 'cell (keyword value)))))}) rest])) +
+ + 367   +
+ + 368  (defn- parse-set-action +
+ + 369    "Parse actions of the form '[property] should be [value].'" +
+ + 370    [previous [property SHOULD BE value & rest]] +
+ + 371    (cond +
+ + 372      (member? property '("x" "y")) +
+ + 373      (throw +
+ + 374        (Exception. reserved-properties-error)) +
+ + 375      (and (= SHOULD "should") (= BE "be")) +
+ + 376      [(list 'merge (or previous 'cell) +
+ + 377             {(keyword property) (cond (re-matches re-number value) (read-string value) true (keyword value))}) rest])) +
+ + 378   +
+ + 379  (defn- parse-simple-action [previous tokens] +
+ + 380    (or (parse-arithmetic-action previous tokens) +
+ + 381        (parse-set-action previous tokens))) +
+ + 382   +
+ + 383  (defn- parse-actions +
+ + 384    "Parse actions from tokens." +
+ + 385    [previous tokens] +
+ + 386    (let [[left remainder] (parse-simple-action previous tokens)] +
+ + 387      (cond left +
+ + 388            (cond (= (first remainder) "and") +
+ + 389                  (parse-actions left (rest remainder)) +
+ + 390                  true (list left))))) +
+ + 391   +
+ + 392  (defn- parse-probability +
+ + 393    "Parse a probability of an action from this collection of tokens" +
+ + 394    [previous [n CHANCE IN m & tokens]] +
+ + 395    (cond +
+ + 396      (and (= CHANCE "chance")(= IN "in")) +
+ + 397      (let [[action remainder] (parse-actions previous tokens)] +
+ + 398        (cond action +
+ + 399          [(list 'cond +
+ + 400                (list '< +
+ + 401                      (list 'rand +
+ + 402                            (first (parse-simple-value (list m) true))) +
+ + 403                      (first (parse-simple-value (list n) true))) +
+ + 404                action) remainder])))) +
+ + 405   +
+ + 406  (defn- parse-right-hand-side +
+ + 407    "Parse the right hand side ('then...') of a production rule." +
+ + 408    [[THEN & tokens]] +
+ + 409    (if (= THEN "then") +
+ + 410      (or +
+ + 411        (parse-probability nil tokens) +
+ + 412        (parse-actions nil tokens)))) +
+ + 413   +
+ + 414  (defn parse-rule +
+ + 415    "Parse a complete rule from this `line`, expected to be either a string or a +
+ + 416     sequence of string tokens. Return the rule in the form of an S-expression. +
+ + 417   +
+ + 418     Throws an exception if parsing fails." +
+ + 419    [line] +
+ + 420    (cond +
+ + 421     (string? line) +
+ + 422     (let [rule (parse-rule (split (triml line) #"\s+"))] +
+ + 423       (cond rule rule +
+ + 424         true (throw (Exception. (format bad-parse-error line))))) +
+ + 425     true +
+ + 426     (let [[left remainder] (parse-left-hand-side line) +
+ + 427                [right junk] (parse-right-hand-side remainder)] +
+ + 428       (cond +
+ + 429         ;; there should be a valide left hand side and a valid right hand side +
+ + 430         ;; there shouldn't be anything left over (junk should be empty) +
+ + 431         (and left right (empty? junk)) +
+ + 432         (list 'fn ['cell 'world] (list 'if left right)))))) +
+ + 433   +
+ + 434  (defn compile-rule +
+ + 435    "Parse this `rule-text`, a string conforming to the grammar of MicroWorld rules, +
+ + 436     into Clojure source, and then compile it into an anonymous +
+ + 437     function object, getting round the problem of binding mw-engine.utils in +
+ + 438     the compiling environment. If `return-tuple?` is present and true, return +
+ + 439     a list comprising the anonymous function compiled, and the function from +
+ + 440     which it was compiled. +
+ + 441   +
+ + 442     Throws an exception if parsing fails." +
+ + 443    ([rule-text return-tuple?] +
+ + 444      (do +
+ + 445        (use 'mw-engine.utils) +
+ + 446        (let [afn (eval (parse-rule rule-text))] +
+ + 447          (cond +
+ + 448            (and afn return-tuple?)(list afn (trim rule-text)) +
+ + 449            true afn)))) +
+ + 450    ([rule-text] +
+ + 451      (compile-rule rule-text false))) +
+ + diff --git a/docs/cloverage/mw_parser/declarative.clj.html b/docs/cloverage/mw_parser/declarative.clj.html new file mode 100644 index 0000000..939e864 --- /dev/null +++ b/docs/cloverage/mw_parser/declarative.clj.html @@ -0,0 +1,479 @@ + + + + mw_parser/declarative.clj + + + + 001  (ns ^{:doc "A very simple parser which parses production rules." +
+ + 002        :author "Simon Brooke"} +
+ + 003   mw-parser.declarative +
+ + 004    (:require [instaparse.core :refer [parser]] +
+ + 005              [clojure.string :refer [join trim]] +
+ + 006              [mw-parser.errors :refer [throw-parse-exception]] +
+ + 007              [mw-parser.generate :refer [generate]] +
+ + 008              [mw-parser.simplify :refer [simplify-rule]] +
+ + 009              [mw-parser.utils :refer [rule?]] +
+ + 010              [trptr.java-wrapper.locale :refer [get-default]]) +
+ + 011    (:import [java.util Locale])) +
+ + 012   +
+ + 013  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 014  ;;;; +
+ + 015  ;;;; mw-parser: a rule parser for MicroWorld. +
+ + 016  ;;;; +
+ + 017  ;;;; This program is free software; you can redistribute it and/or +
+ + 018  ;;;; modify it under the terms of the GNU General Public License +
+ + 019  ;;;; as published by the Free Software Foundation; either version 2 +
+ + 020  ;;;; of the License, or (at your option) any later version. +
+ + 021  ;;;; +
+ + 022  ;;;; This program is distributed in the hope that it will be useful, +
+ + 023  ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +
+ + 024  ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +
+ + 025  ;;;; GNU General Public License for more details. +
+ + 026  ;;;; +
+ + 027  ;;;; You should have received a copy of the GNU General Public License +
+ + 028  ;;;; along with this program; if not, write to the Free Software +
+ + 029  ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, +
+ + 030  ;;;; USA. +
+ + 031  ;;;; +
+ + 032  ;;;; Copyright (C) 2014 Simon Brooke +
+ + 033  ;;;; +
+ + 034  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 035   +
+ + 036  (def rule-grammar +
+ + 037    "Basic rule language grammar. +
+ + 038      +
+ + 039    in order to simplify translation into other natural languages, all +
+ + 040    TOKENS within the parser should be unambiguou." +
+ + 041    (join "\n" ["RULE := IF SPACE CONDITIONS SPACE THEN SPACE ACTIONS;" +
+ + 042                "ACTIONS := ACTION | ACTION SPACE AND SPACE ACTIONS" +
+ + 043                "ACTION := SIMPLE-ACTION | PROBABLE-ACTION;" +
+ + 044                "PROBABLE-ACTION := VALUE SPACE CHANCE-IN SPACE VALUE SPACE SIMPLE-ACTION;" +
+ + 045                "SIMPLE-ACTION := SYMBOL SPACE BECOMES SPACE EXPRESSION;"])) +
+ + 046   +
+ + 047  (def common-grammar +
+ + 048    "Grammar rules used both in the rule grammar and in the flow grammar" +
+ + 049    (join "\n" ["COMPARATIVE := MORE | LESS;" +
+ + 050                "COMPARATIVE-QUALIFIER := IS SPACE COMPARATIVE SPACE THAN | COMPARATIVE SPACE THAN;" +
+ + 051                "CONDITION := WITHIN-CONDITION | NEIGHBOURS-CONDITION | PROPERTY-CONDITION;" +
+ + 052                "CONDITIONS := DISJUNCT-CONDITION | CONJUNCT-CONDITION | CONDITION ;" +
+ + 053                "CONJUNCT-CONDITION := CONDITION SPACE AND SPACE CONDITIONS;" +
+ + 054                "DISJUNCT-CONDITION := CONDITION SPACE OR SPACE CONDITIONS;" +
+ + 055                "DISJUNCT-EXPRESSION := IN SPACE DISJUNCT-VALUE;" +
+ + 056                "DISJUNCT-VALUE := VALUE | VALUE SPACE OR SPACE DISJUNCT-VALUE;" +
+ + 057                "EQUIVALENCE := IS SPACE EQUAL | EQUAL | IS ;" +
+ + 058                "EXPRESSION := SIMPLE-EXPRESSION | RANGE-EXPRESSION | NUMERIC-EXPRESSION | DISJUNCT-EXPRESSION | VALUE;" +
+ + 059                "NEGATED-QUALIFIER := QUALIFIER SPACE NOT | NOT SPACE QUALIFIER;" +
+ + 060                "NEIGHBOURS-CONDITION := QUANTIFIER SPACE NEIGHBOURS SPACE IS SPACE PROPERTY-CONDITION | QUALIFIER SPACE NEIGHBOURS-CONDITION;" +
+ + 061                "NUMBER := #'[0-9]+' | #'[0-9]+.[0-9]+';" +
+ + 062                "NUMERIC-EXPRESSION := VALUE | VALUE SPACE OPERATOR SPACE NUMERIC-EXPRESSION;" +
+ + 063                "OPERATOR := '+' | '-' | '*' | '/';" +
+ + 064                "PROPERTY := SYMBOL;" +
+ + 065                "PROPERTY-CONDITION := PROPERTY SPACE QUALIFIER SPACE EXPRESSION | VALUE;" +
+ + 066                "PROPERTY-CONDITION-OR-EXPRESSION := PROPERTY-CONDITION | EXPRESSION;" +
+ + 067                "QUALIFIER := COMPARATIVE-QUALIFIER | NEGATED-QUALIFIER | EQUIVALENCE | IS SPACE QUALIFIER;" +
+ + 068                "QUANTIFIER := NUMBER | SOME | NONE | ALL | COMPARATIVE SPACE THAN SPACE NUMBER;" +
+ + 069                "RANGE-EXPRESSION := BETWEEN SPACE NUMERIC-EXPRESSION SPACE AND SPACE NUMERIC-EXPRESSION;" +
+ + 070                "SIMPLE-EXPRESSION := QUALIFIER SPACE EXPRESSION | VALUE;" +
+ + 071                "SPACE := #'\\s+';" +
+ + 072                "VALUE := SYMBOL | NUMBER;" +
+ + 073                "VALUE := SYMBOL | NUMBER;" +
+ + 074                "WITHIN-CONDITION := QUANTIFIER SPACE NEIGHBOURS SPACE WITHIN SPACE NUMBER SPACE IS SPACE PROPERTY-CONDITION-OR-EXPRESSION;" +
+ + 075                ])) +
+ + 076   +
+ + 077  (def keywords-en +
+ + 078    "English language keyword literals used in rules - both in production +
+ + 079     rules (this namespace) and in flow rules (see mw-parser.flow). +
+ + 080         +
+ + 081        It's a long term aim that the rule language should be easy to  +
+ + 082        internationalise; this isn't a full solution but it's a step towards +
+ + 083        a solution." +
+ + 084    (join "\n" ["ALL := 'all'"  +
+ + 085                "AND := 'and';"  +
+ + 086                "BECOMES := 'should be' | 'becomes';"  +
+ + 087                "BETWEEN := 'between';"  +
+ + 088                "CHANCE-IN := 'chance in';"  +
+ + 089                "EACH := 'each' | 'every' | 'all';" +
+ + 090                "EQUAL := 'equal to';"  +
+ + 091                "FIRST := 'first';" +
+ + 092                "FLOW := 'flow' | 'move';"  +
+ + 093                "FROM := 'from';" +
+ + 094                "IF := 'if';"  +
+ + 095                "IN := 'in';"  +
+ + 096                "IS := 'is' | 'are' | 'have' | 'has';"  +
+ + 097                "LEAST := 'least';" +
+ + 098                "LESS := 'less' | 'fewer';"  +
+ + 099                "MORE := 'more' | 'greater';"  +
+ + 100                "MOST := 'most';" +
+ + 101                "NEIGHBOURS := 'neighbour' | 'neighbor' | 'neighbours' | 'neighbors';"  +
+ + 102                "NONE := 'no';"  +
+ + 103                "NOT := 'not';"  +
+ + 104                "OR := 'or';"  +
+ + 105                "SOME := 'some';"  +
+ + 106                ;; SYMBOL is in the per-language file so that languages that use +
+ + 107                ;; (e.g.) Cyrillic characters can change the definition. +
+ + 108                "SYMBOL := #'[a-z]+';"  +
+ + 109                "THAN := 'than';"  +
+ + 110                "THEN := 'then';"  +
+ + 111                "TO := 'to';" +
+ + 112                "WITH := 'with' | 'where' | 'having';" +
+ + 113                "WITHIN := 'within';"])) +
+ + 114   +
+ + 115  (defn keywords-for-locale +
+ + 116    "For now, just return `keywords-en`; plan is to have resource files of  +
+ + 117     keywords for different languages in a resource directory, but that isn't +
+ + 118     done yet. It's probably not going to work easily for languages that use +
+ + 119     non-latin alphabets, anyway." +
+ + 120    ([] +
+ + 121     (keywords-for-locale (get-default))) +
+ + 122    ([^Locale _locale] +
+ + 123     keywords-en)) +
+ + 124   +
+ + 125  (defmacro build-parser  +
+ + 126    "Compose this grammar fragment `g` with the common grammar fragments to  +
+ + 127     make a complete grammar, and return a parser for that complete grammar." +
+ + 128    [g] +
+ + 129    `(parser (join "\n" [~g common-grammar (keywords-for-locale)]))) +
+ + 130   +
+ + 131  (def parse-rule +
+ + 132    "Parse the argument, assumed to be a string in the correct syntax, and return a parse tree." +
+ + 133    (build-parser rule-grammar)) +
+ + 134   +
+ + 135  (defn compile-rule +
+ + 136    "Parse this `rule-text`, a string conforming to the grammar of MicroWorld rules, +
+ + 137    into Clojure source, and then compile it into an anonymous +
+ + 138    function object, getting round the problem of binding mw-engine.utils in +
+ + 139    the compiling environment. If `return-tuple?` is present and true, return +
+ + 140    a list comprising the anonymous function compiled, and the function from +
+ + 141    which it was compiled. +
+ + 142   +
+ + 143    Throws an exception if parsing fails." +
+ + 144    ([rule-text return-tuple?] +
+ + 145     (assert (string? rule-text)) +
+ + 146     (let [rule (trim rule-text) +
+ + 147           tree (simplify-rule (parse-rule rule)) +
+ + 148           afn (if (rule? tree) (eval (generate tree)) +
+ + 149                 ;; else +
+ + 150                   (throw-parse-exception tree))] +
+ + 151       (if return-tuple? +
+ + 152         (list afn rule) +
+ + 153         ;; else +
+ + 154         afn))) +
+ + 155    ([rule-text] +
+ + 156     (compile-rule rule-text false))) +
+ + 157   +
+ + diff --git a/docs/cloverage/mw_parser/errors.clj.html b/docs/cloverage/mw_parser/errors.clj.html new file mode 100644 index 0000000..1a0877a --- /dev/null +++ b/docs/cloverage/mw_parser/errors.clj.html @@ -0,0 +1,212 @@ + + + + mw_parser/errors.clj + + + + 001  (ns ^{:doc "Display parse errors in a format which makes it easy for the user +
+ + 002        to see where the error occurred." +
+ + 003        :author "Simon Brooke"} +
+ + 004    mw-parser.errors) +
+ + 005   +
+ + 006  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 007  ;; +
+ + 008  ;; This program is free software; you can redistribute it and/or +
+ + 009  ;; modify it under the terms of the GNU General Public License +
+ + 010  ;; as published by the Free Software Foundation; either version 2 +
+ + 011  ;; of the License, or (at your option) any later version. +
+ + 012  ;; +
+ + 013  ;; This program is distributed in the hope that it will be useful, +
+ + 014  ;; but WITHOUT ANY WARRANTY; without even the implied warranty of +
+ + 015  ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +
+ + 016  ;; GNU General Public License for more details. +
+ + 017  ;; +
+ + 018  ;; You should have received a copy of the GNU General Public License +
+ + 019  ;; along with this program; if not, write to the Free Software +
+ + 020  ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, +
+ + 021  ;; USA. +
+ + 022  ;; +
+ + 023  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 024   +
+ + 025   +
+ + 026  ;; error thrown when an attempt is made to set a reserved property +
+ + 027  (def reserved-properties-error +
+ + 028    "The properties 'x' and 'y' of a cell are reserved and should not be set in rule actions") +
+ + 029  ;; error thrown when a rule cannot be parsed. Slots are for +
+ + 030  ;; (1) rule text +
+ + 031  ;; (2) cursor showing where in the rule text the error occurred +
+ + 032  ;; (3) the reason for the error +
+ + 033  (def bad-parse-error "I did not understand:\n  '%s'\n  %s\n  %s") +
+ + 034   +
+ + 035   +
+ + 036  (defn- explain-parse-error-reason +
+ + 037    "Attempt to explain the reason for the parse error." +
+ + 038    [reason] +
+ + 039    (str "Expecting one of (" (apply str (map #(str (:expecting %) " ") reason)) ")")) +
+ + 040   +
+ + 041   +
+ + 042  (defn- parser-error-to-map +
+ + 043    [parser-error] +
+ + 044    (let [m (reduce (fn [map item](merge map {(first item)(second item)})) {} parser-error) +
+ + 045          reason (map +
+ + 046                   #(reduce (fn [map item] (merge {(first item) (second item)} map)) {} %) +
+ + 047                   (:reason m))] +
+ + 048      (merge m {:reason reason}))) +
+ + 049   +
+ + 050   +
+ + 051  (defn throw-parse-exception +
+ + 052    "Construct a helpful error message from this `parser-error`, and throw an exception with that message." +
+ + 053    [parser-error] +
+ + 054    (assert (coll? parser-error) "Expected a paser error structure?") +
+ + 055    (let +
+ + 056      [ +
+ + 057        ;; the error structure is a list, such that each element is a list of two items, and +
+ + 058        ;; the first element in each sublist is a keyword. Easier to work with it as a map +
+ + 059       error-map (parser-error-to-map parser-error) +
+ + 060       text (:text error-map) +
+ + 061       reason (explain-parse-error-reason (:reason error-map)) +
+ + 062        ;; rules have only one line, by definition; we're interested in the column +
+ + 063       column (if (:column error-map)(:column error-map) 0) +
+ + 064        ;; create a cursor to point to that column +
+ + 065       cursor (apply str (reverse (conj (repeat column " ") "^"))) +
+ + 066       message (format bad-parse-error text cursor reason) +
+ + 067       ] +
+ + 068    (throw (Exception. message)))) +
+ + diff --git a/docs/cloverage/mw_parser/flow.clj.html b/docs/cloverage/mw_parser/flow.clj.html new file mode 100644 index 0000000..eafe82b --- /dev/null +++ b/docs/cloverage/mw_parser/flow.clj.html @@ -0,0 +1,209 @@ + + + + mw_parser/flow.clj + + + + 001  (ns ^{:doc "A very simple parser which parses flow rules." +
+ + 002        :author "Simon Brooke"} +
+ + 003   mw-parser.flow +
+ + 004    (:require [clojure.string :refer [join]] +
+ + 005              [mw-parser.declarative :refer [build-parser]] +
+ + 006              [mw-parser.simplify :refer [simplify-second-of-two]])) +
+ + 007   +
+ + 008  (def flow-grammar +
+ + 009    "Grammar for flow rules. +
+ + 010               +
+ + 011     My initial conception of this would be that production rules  +
+ + 012     (if-then rules) and flow rules (flow-from-to rules) would be  +
+ + 013     entirely separate, presented to the parser as separate text  +
+ + 014     files, and parsed and compiled by different chains of functions. +
+ + 015               +
+ + 016     This appears not to be necessary. Flow rules are easy to parse +
+ + 017     with the same parser as production rules -- a lot of the grammar  +
+ + 018     is intentionally common -- and the rules are easily discriminated +
+ + 019     at the compilation ('generate') stage. +
+ + 020      +
+ + 021     The basic rule I want to be able to compile at this stage is the 'mutual +
+ + 022     aid' rule: +
+ + 023   +
+ + 024     `flow 1 food from house having food > 1 to house with least food within 2` +
+ + 025     " +
+ + 026    (join "\n" ["FLOW-RULE := FLOW SPACE QUANTITY SPACE PROPERTY SPACE FROM SPACE SOURCE SPACE TO-HOW SPACE DESTINATION;" +
+ + 027                "PERCENTAGE := NUMBER #'%';" +
+ + 028                "QUANTITY := PERCENTAGE | NUMBER | EXPRESSION | SOME;" +
+ + 029                "SOURCE := STATE | STATE SPACE WITH SPACE CONDITIONS;" +
+ + 030                "DESTINATION := STATE | STATE SPACE WITH SPACE FLOW-CONDITIONS | STATE SPACE WITHIN SPACE VALUE SPACE WITH SPACE FLOW-CONDITIONS;" +
+ + 031                "DETERMINER := MOST | LEAST;" +
+ + 032                "DETERMINER-CONDITION := DETERMINER SPACE PROPERTY | DETERMINER SPACE PROPERTY;" +
+ + 033                "FLOW-CONDITIONS := DETERMINER-CONDITION | CONDITIONS" +
+ + 034                "STATE := SYMBOL;" +
+ + 035                "TO-HOW := TO | TO-EACH | TO-FIRST;" +
+ + 036                "TO-EACH := TO SPACE EACH | TO SPACE ALL;" +
+ + 037                "TO-FIRST := TO SPACE FIRST"])) +
+ + 038   +
+ + 039  (def parse-flow +
+ + 040    "Parse the argument, assumed to be a string in the correct syntax, and return a parse tree." +
+ + 041    (build-parser flow-grammar)) +
+ + 042   +
+ + 043  (defn simplify-flow +
+ + 044    [tree] +
+ + 045    (if (coll? tree) +
+ + 046      (case (first tree) +
+ + 047        :CONDITION (simplify-second-of-two tree) +
+ + 048        :CONDITIONS (simplify-second-of-two tree) +
+ + 049        :DETERMINER (simplify-second-of-two tree) +
+ + 050  ;;      :DETERMINER-CONDITION (simplify-determiner-condition tree) +
+ + 051        :EXPRESSION (simplify-second-of-two tree) +
+ + 052        :FLOW nil +
+ + 053  ;;      :FLOW-CONDITIONS (simplify-second-of-two tree) +
+ + 054        :PROPERTY (simplify-second-of-two tree) +
+ + 055        :PROPERTY-CONDITION-OR-EXPRESSION (simplify-second-of-two tree) +
+ + 056        :SPACE nil +
+ + 057        :QUANTITY (simplify-second-of-two tree) +
+ + 058        :STATE (list :PROPERTY-CONDITION +
+ + 059                     (list :SYMBOL "state") +
+ + 060                     '(:QUALIFIER +
+ + 061                       (:EQUIVALENCE +
+ + 062                        (:IS "is"))) +
+ + 063                     (list :EXPRESSION +
+ + 064                           (list :VALUE (second tree)))) +
+ + 065        (remove nil? (map simplify-flow tree))) +
+ + 066      tree)) +
+ + 067   +
+ + diff --git a/docs/cloverage/mw_parser/generate.clj.html b/docs/cloverage/mw_parser/generate.clj.html new file mode 100644 index 0000000..f901a2f --- /dev/null +++ b/docs/cloverage/mw_parser/generate.clj.html @@ -0,0 +1,962 @@ + + + + mw_parser/generate.clj + + + + 001  (ns ^{:doc "Generate Clojure source from simplified parse trees." +
+ + 002        :author "Simon Brooke"} +
+ + 003   mw-parser.generate +
+ + 004    (:require [mw-parser.utils :refer [assert-type TODO]] +
+ + 005              [mw-parser.errors :as pe])) +
+ + 006   +
+ + 007  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 008  ;; +
+ + 009  ;; This program is free software; you can redistribute it and/or +
+ + 010  ;; modify it under the terms of the GNU General Public License +
+ + 011  ;; as published by the Free Software Foundation; either version 2 +
+ + 012  ;; of the License, or (at your option) any later version. +
+ + 013  ;; +
+ + 014  ;; This program is distributed in the hope that it will be useful, +
+ + 015  ;; but WITHOUT ANY WARRANTY; without even the implied warranty of +
+ + 016  ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +
+ + 017  ;; GNU General Public License for more details. +
+ + 018  ;; +
+ + 019  ;; You should have received a copy of the GNU General Public License +
+ + 020  ;; along with this program; if not, write to the Free Software +
+ + 021  ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, +
+ + 022  ;; USA. +
+ + 023  ;; +
+ + 024  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 025   +
+ + 026   +
+ + 027  (declare generate generate-action) +
+ + 028   +
+ + 029   +
+ + 030  (defn generate-rule +
+ + 031    "From this `tree`, assumed to be a syntactically correct rule specification, +
+ + 032    generate and return the appropriate rule as a function of two arguments." +
+ + 033    [tree] +
+ + 034    (assert-type tree :RULE) +
+ + 035    (list 'fn ['cell 'world] (list 'if (generate (nth tree 2)) (generate (nth tree 3))))) +
+ + 036   +
+ + 037   +
+ + 038  (defn generate-conditions +
+ + 039    "From this `tree`, assumed to be a syntactically correct conditions clause, +
+ + 040    generate and return the appropriate clojure fragment." +
+ + 041    [tree] +
+ + 042    (assert-type tree :CONDITIONS) +
+ + 043    (generate (second tree))) +
+ + 044   +
+ + 045   +
+ + 046  (defn generate-condition +
+ + 047    "From this `tree`, assumed to be a syntactically correct condition clause, +
+ + 048    generate and return the appropriate clojure fragment." +
+ + 049    [tree] +
+ + 050    (assert-type tree :CONDITION) +
+ + 051    (generate (second tree))) +
+ + 052   +
+ + 053   +
+ + 054  (defn generate-conjunct-condition +
+ + 055    "From this `tree`, assumed to be a syntactically conjunct correct condition clause, +
+ + 056    generate and return the appropriate clojure fragment." +
+ + 057    [tree] +
+ + 058    (assert-type tree :CONJUNCT-CONDITION) +
+ + 059    (cons 'and (map generate (rest tree)))) +
+ + 060   +
+ + 061   +
+ + 062  (defn generate-disjunct-condition +
+ + 063    "From this `tree`, assumed to be a syntactically correct disjunct condition clause, +
+ + 064    generate and return the appropriate clojure fragment." +
+ + 065    [tree] +
+ + 066    (assert-type tree :DISJUNCT-CONDITION) +
+ + 067    (cons 'or (map generate (rest tree)))) +
+ + 068   +
+ + 069   +
+ + 070  (defn generate-ranged-property-condition +
+ + 071    "From this `tree`, assumed to be a syntactically property condition clause for +
+ + 072    this `property` where the `expression` is a numeric range, generate and return +
+ + 073    the appropriate clojure fragment." +
+ + 074    [tree property expression] +
+ + 075    (assert-type tree :PROPERTY-CONDITION) +
+ + 076    (assert-type (nth tree 3) :RANGE-EXPRESSION) +
+ + 077    (let [l1 (generate (nth expression 2)) +
+ + 078          l2 (generate (nth expression 4)) +
+ + 079          pv (list property 'cell)] +
+ + 080      (list 'let ['lower (list 'min l1 l2) +
+ + 081                  'upper (list 'max l1 l2)] +
+ + 082            (list 'and (list '>= pv 'lower) (list '<= pv 'upper))))) +
+ + 083   +
+ + 084   +
+ + 085  (defn generate-disjunct-property-condition +
+ + 086    "From this `tree`, assumed to be a syntactically property condition clause +
+ + 087    where the expression is a a disjunction, generate and return +
+ + 088    the appropriate clojure fragment. +
+ + 089    TODO: this is definitely still wrong!" +
+ + 090    ([tree] +
+ + 091     (let [property (generate (second tree)) +
+ + 092           qualifier (generate (nth tree 2)) +
+ + 093           expression (generate (nth tree 3))] +
+ + 094       (generate-disjunct-property-condition tree property qualifier expression))) +
+ + 095    ([_tree property qualifier expression] +
+ + 096     (let [e (list 'some (list 'fn ['i] '(= i value)) (list 'quote expression))] +
+ + 097       (list 'let ['value (list property 'cell)] +
+ + 098             (if (= qualifier '=) e +
+ + 099                 (list 'not e)))))) +
+ + 100   +
+ + 101   +
+ + 102  (defn generate-property-condition +
+ + 103    "From this `tree`, assumed to be a syntactically property condition clause, +
+ + 104    generate and return the appropriate clojure fragment." +
+ + 105    ([tree] +
+ + 106     (assert-type tree :PROPERTY-CONDITION) +
+ + 107     (if +
+ + 108      (and (= (count tree) 2) (= (first (second tree)) :SYMBOL)) +
+ + 109       ;; it's a shorthand for 'state equal to symbol'. This should probably have +
+ + 110       ;; been handled in simplify... +
+ + 111       (generate-property-condition +
+ + 112        (list +
+ + 113         :PROPERTY-CONDITION +
+ + 114         '(:SYMBOL "state") +
+ + 115         '(:QUALIFIER (:EQUIVALENCE (:EQUAL "equal to"))) +
+ + 116         (second tree))) +
+ + 117       ;; otherwise... +
+ + 118       (generate-property-condition tree (first (nth tree 3))))) +
+ + 119    ([tree expression-type] +
+ + 120     (assert-type tree :PROPERTY-CONDITION) +
+ + 121     (let [property (generate (second tree)) +
+ + 122           qualifier (generate (nth tree 2)) +
+ + 123           e (generate (nth tree 3)) +
+ + 124           expression (cond +
+ + 125                        (and (not (= qualifier '=)) (keyword? e)) (list 'or (list e 'cell) e) +
+ + 126                        (and (not (= qualifier 'not=)) (keyword? e)) (list 'or (list e 'cell) e) +
+ + 127                        :else e)] +
+ + 128       (case expression-type +
+ + 129         :DISJUNCT-EXPRESSION (generate-disjunct-property-condition tree property qualifier expression) +
+ + 130         :RANGE-EXPRESSION (generate-ranged-property-condition tree property expression) +
+ + 131         (list qualifier (list property 'cell) expression))))) +
+ + 132   +
+ + 133  (defn generate-qualifier +
+ + 134    "From this `tree`, assumed to be a syntactically correct qualifier, +
+ + 135    generate and return the appropriate clojure fragment." +
+ + 136    [tree] +
+ + 137    (if +
+ + 138     (= (count tree) 2) +
+ + 139      (generate (second tree)) +
+ + 140      ;; else +
+ + 141      (generate (nth tree 2)))) +
+ + 142   +
+ + 143  (defn generate-simple-action +
+ + 144    "From this `tree`, assumed to be a syntactically correct simple action, +
+ + 145    generate and return the appropriate clojure fragment." +
+ + 146    ([tree] +
+ + 147     (assert-type tree :SIMPLE-ACTION) +
+ + 148     (generate-simple-action tree [])) +
+ + 149    ([tree others] +
+ + 150     (assert-type tree :SIMPLE-ACTION) +
+ + 151     (let [property (generate (second tree)) +
+ + 152           expression (generate (nth tree 3))] +
+ + 153       (if (or (= property :x) (= property :y)) +
+ + 154         (throw (Exception. pe/reserved-properties-error)) +
+ + 155         (list 'merge +
+ + 156               (if (empty? others) 'cell +
+ + 157                 ;; else +
+ + 158                   (generate others)) +
+ + 159               {property expression}))))) +
+ + 160   +
+ + 161  (defn generate-probable-action +
+ + 162    "From this `tree`, assumed to be a syntactically correct probable action, +
+ + 163    generate and return the appropriate clojure fragment." +
+ + 164    ([tree] +
+ + 165     (assert-type tree :PROBABLE-ACTION) +
+ + 166     (generate-probable-action tree [])) +
+ + 167    ([tree others] +
+ + 168     (assert-type tree :PROBABLE-ACTION) +
+ + 169     (let +
+ + 170      [chances (generate (nth tree 1)) +
+ + 171       total (generate (nth tree 2)) +
+ + 172       action (generate-action (nth tree 3) others)] +
+ + 173      ;; TODO: could almost certainly be done better with macro syntax +
+ + 174       (list 'if +
+ + 175             (list '< (list 'rand total) chances) +
+ + 176             action)))) +
+ + 177   +
+ + 178  (defn generate-action +
+ + 179    "From this `tree`, assumed to be a syntactically correct action, +
+ + 180    generate and return the appropriate clojure fragment." +
+ + 181    [tree others] +
+ + 182    (case (first tree) +
+ + 183      :ACTIONS (generate-action (first tree) others) +
+ + 184      :SIMPLE-ACTION (generate-simple-action tree others) +
+ + 185      :PROBABLE-ACTION (generate-probable-action tree others) +
+ + 186      (throw (Exception. (str "Not a known action type: " (first tree)))))) +
+ + 187   +
+ + 188  (defn generate-multiple-actions +
+ + 189    "From this `tree`, assumed to be one or more syntactically correct actions, +
+ + 190    generate and return the appropriate clojure fragment." +
+ + 191    [tree] +
+ + 192    (assert-type tree :ACTIONS) +
+ + 193    (generate-action (first (rest tree)) (second (rest tree)))) +
+ + 194   +
+ + 195  (defn generate-disjunct-value +
+ + 196    "Generate a disjunct value. Essentially what we need here is to generate a +
+ + 197    flat list of values, since the `member` has already been taken care of." +
+ + 198    [tree] +
+ + 199    (assert-type tree :DISJUNCT-VALUE) +
+ + 200    (if (= (count tree) 4) +
+ + 201      (cons (generate (second tree)) (generate (nth tree 3))) +
+ + 202      (list (generate (second tree))))) +
+ + 203   +
+ + 204  (defn generate-numeric-expression +
+ + 205    "From this `tree`, assumed to be a syntactically correct numeric expression, +
+ + 206    generate and return the appropriate clojure fragment." +
+ + 207    [tree] +
+ + 208    (assert-type tree :NUMERIC-EXPRESSION) +
+ + 209    (case (count tree) +
+ + 210      4 (let [[p operator expression] (rest tree) +
+ + 211              property (if (number? p) p (list p 'cell))] +
+ + 212          (list (generate operator) (generate property) (generate expression))) +
+ + 213      (case (first (second tree)) +
+ + 214        :SYMBOL (list (keyword (second (second tree))) 'cell) +
+ + 215        (generate (second tree))))) +
+ + 216   +
+ + 217  (defn generate-neighbours-condition +
+ + 218    "Generate code for a condition which refers to neighbours." +
+ + 219    ([tree] +
+ + 220     (assert-type tree :NEIGHBOURS-CONDITION) +
+ + 221     (case (first (second tree)) +
+ + 222       :NUMBER (read-string (second (second tree))) +
+ + 223       :QUANTIFIER (generate-neighbours-condition tree (first (second (second tree)))) +
+ + 224       :QUALIFIER (cons (generate (second tree)) (rest (generate (nth tree 2)))))) +
+ + 225    ([tree quantifier-type] +
+ + 226     (let [quantifier (second tree) +
+ + 227           pc (generate (nth tree 4))] +
+ + 228       (case quantifier-type +
+ + 229         :NUMBER (generate-neighbours-condition '= (read-string (second (second quantifier))) pc 1) +
+ + 230         :SOME (generate-neighbours-condition '> 0 pc 1) +
+ + 231         :MORE (let [value (generate (nth quantifier 3))] +
+ + 232                 (generate-neighbours-condition '> value pc 1)) +
+ + 233         :LESS (let [value (generate (nth quantifier 3))] +
+ + 234                 (generate-neighbours-condition '< value pc 1))))) +
+ + 235    ([comp1 quantity property-condition distance] +
+ + 236     (list comp1 +
+ + 237           (list 'count +
+ + 238                 (list 'remove 'false? +
+ + 239                       (list 'map (list 'fn ['cell] property-condition) +
+ + 240                             (list 'mw-engine.utils/get-neighbours 'world 'cell distance)))) quantity)) +
+ + 241    ([comp1 quantity property-condition] +
+ + 242     (generate-neighbours-condition comp1 quantity property-condition 1))) +
+ + 243   +
+ + 244   +
+ + 245  (defn generate-within-condition +
+ + 246    "Generate code for a condition which refers to neighbours within a specified distance. +
+ + 247    NOTE THAT there's clearly masses of commonality between this and +
+ + 248    `generate-neighbours-condition`, and that some refactoring is almost certainly +
+ + 249    desirable. It may be that it's better to simplify a `NEIGHBOURS-CONDITION` +
+ + 250    into a `WITHIN-CONDITION` in the simplification stage." +
+ + 251    ([tree] +
+ + 252     (assert-type tree :WITHIN-CONDITION) +
+ + 253     (case (first (second tree)) +
+ + 254       :QUANTIFIER (generate-within-condition tree (first (second (second tree)))) +
+ + 255       :QUALIFIER (TODO "qualified within... help!"))) +
+ + 256    ([tree quantifier-type] +
+ + 257     (let [quantifier (second tree) +
+ + 258           distance (generate (nth tree 4)) +
+ + 259           pc (generate (nth tree 6))] +
+ + 260       (case quantifier-type +
+ + 261         :NUMBER (generate-neighbours-condition '= (read-string (second (second quantifier))) pc distance) +
+ + 262         :SOME (generate-neighbours-condition '> 0 pc distance) +
+ + 263         :MORE (let [value (generate (nth quantifier 3))] +
+ + 264                 (generate-neighbours-condition '> value pc distance)) +
+ + 265         :LESS (let [value (generate (nth quantifier 3))] +
+ + 266                 (generate-neighbours-condition '< value pc distance)))))) +
+ + 267   +
+ + 268  (defn generate-flow +
+ + 269    [tree] +
+ + 270    (assert-type tree :WITHIN-CONDITION)) +
+ + 271   +
+ + 272  (defn generate +
+ + 273    "Generate code for this (fragment of a) parse tree" +
+ + 274    [tree] +
+ + 275    (if +
+ + 276     (coll? tree) +
+ + 277      (case (first tree) +
+ + 278        :ACTIONS (generate-multiple-actions tree) +
+ + 279        :COMPARATIVE (generate (second tree)) +
+ + 280        :COMPARATIVE-QUALIFIER (generate (second tree)) +
+ + 281        :CONDITION (generate-condition tree) +
+ + 282        :CONDITIONS (generate-conditions tree) +
+ + 283        :CONJUNCT-CONDITION (generate-conjunct-condition tree) +
+ + 284        :DISJUNCT-CONDITION (generate-disjunct-condition tree) +
+ + 285        :DISJUNCT-EXPRESSION (generate (nth tree 2)) +
+ + 286        :DISJUNCT-VALUE (generate-disjunct-value tree) +
+ + 287        :EQUIVALENCE '= +
+ + 288        :EXPRESSION (generate (second tree)) +
+ + 289        :FLOW-RULE (generate-flow tree) +
+ + 290        :LESS '< +
+ + 291        :MORE '> +
+ + 292        :NEGATED-QUALIFIER (case (generate (second tree)) +
+ + 293                             = 'not= +
+ + 294                             > '< +
+ + 295                             < '>) +
+ + 296        :NEIGHBOURS-CONDITION (generate-neighbours-condition tree) +
+ + 297        :NUMERIC-EXPRESSION (generate-numeric-expression tree) +
+ + 298        :NUMBER (read-string (second tree)) +
+ + 299        :OPERATOR (symbol (second tree)) +
+ + 300        :PROBABLE-ACTION (generate-probable-action tree) +
+ + 301        :PROPERTY (list (generate (second tree)) 'cell) ;; dubious - may not be right +
+ + 302        :PROPERTY-CONDITION (generate-property-condition tree) +
+ + 303        :QUALIFIER (generate-qualifier tree) +
+ + 304        :RULE (generate-rule tree) +
+ + 305        :SIMPLE-ACTION (generate-simple-action tree) +
+ + 306        :SYMBOL (keyword (second tree)) +
+ + 307        :VALUE (generate (second tree)) +
+ + 308        :WITHIN-CONDITION (generate-within-condition tree) +
+ + 309        (map generate tree)) +
+ + 310      tree)) +
+ + 311   +
+ + 312  ;;; Flow rules. A flow rule DOES NOT return a modified world; instead, it  +
+ + 313  ;;; returns a PLAN to modify the world, in the form of a sequence of `flows`. +
+ + 314  ;;; It is only when the plan is executed that the world is modified. +
+ + 315  ;;; +
+ + 316  ;;; so we're looking at something like +
+ + 317  ;;; (fn [cell world]) +
+ + 318  ;;;    (if (= (:state cell) (or (:house cell) :house)) +
+ + diff --git a/docs/cloverage/mw_parser/simplify.clj.html b/docs/cloverage/mw_parser/simplify.clj.html new file mode 100644 index 0000000..30b49a9 --- /dev/null +++ b/docs/cloverage/mw_parser/simplify.clj.html @@ -0,0 +1,260 @@ + + + + mw_parser/simplify.clj + + + + 001  (ns ^{:doc "Simplify a parse tree." +
+ + 002        :author "Simon Brooke"} +
+ + 003   mw-parser.simplify) +
+ + 004   +
+ + 005  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 006  ;;;; +
+ + 007  ;;;; mw-parser: a rule parser for MicroWorld. +
+ + 008  ;;;; +
+ + 009  ;;;; This program is free software; you can redistribute it and/or +
+ + 010  ;;;; modify it under the terms of the GNU General Public License +
+ + 011  ;;;; as published by the Free Software Foundation; either version 2 +
+ + 012  ;;;; of the License, or (at your option) any later version. +
+ + 013  ;;;; +
+ + 014  ;;;; This program is distributed in the hope that it will be useful, +
+ + 015  ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +
+ + 016  ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +
+ + 017  ;;;; GNU General Public License for more details. +
+ + 018  ;;;; +
+ + 019  ;;;; You should have received a copy of the GNU General Public License +
+ + 020  ;;;; along with this program; if not, write to the Free Software +
+ + 021  ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, +
+ + 022  ;;;; USA. +
+ + 023  ;;;; +
+ + 024  ;;;; Copyright (C) 2014 Simon Brooke +
+ + 025  ;;;; +
+ + 026  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 027   +
+ + 028  (declare simplify-flow simplify-rule) +
+ + 029   +
+ + 030  ;; (defn simplify-qualifier +
+ + 031  ;;   "Given that this `tree` fragment represents a qualifier, what +
+ + 032  ;;   qualifier is that?" +
+ + 033  ;;   [tree] +
+ + 034  ;;   (cond +
+ + 035  ;;     (empty? tree) nil +
+ + 036  ;;     (and (coll? tree) +
+ + 037  ;;          (#{:EQUIVALENCE :COMPARATIVE} (first tree))) tree +
+ + 038  ;;     (coll? (first tree)) (or (simplify-qualifier (first tree)) +
+ + 039  ;;                              (simplify-qualifier (rest tree))) +
+ + 040  ;;     (coll? tree) (simplify-qualifier (rest tree)) +
+ + 041  ;;     :else tree)) +
+ + 042   +
+ + 043  (defn simplify-second-of-two +
+ + 044    "There are a number of possible simplifications such that if the `tree` has +
+ + 045    only two elements, the second is semantically sufficient." +
+ + 046    [tree] +
+ + 047    (if (= (count tree) 2) (simplify-rule (nth tree 1)) tree)) +
+ + 048   +
+ + 049  ;; (defn simplify-quantifier +
+ + 050  ;;   "If this quantifier is a number, 'simplifiy' it into a comparative whose operator is '=' +
+ + 051  ;;   and whose quantity is that number. This is actually more complicated but makes generation easier." +
+ + 052  ;;   [tree] +
+ + 053  ;;   (if (number? (second tree)) [:COMPARATIVE '= (second tree)] (simplify-rule (second tree)))) +
+ + 054   +
+ + 055  (defn simplify-rule +
+ + 056    "Simplify/canonicalise this `tree`. Opportunistically replace complex fragments with +
+ + 057    semantically identical simpler fragments" +
+ + 058    [tree] +
+ + 059    (if +
+ + 060     (coll? tree) +
+ + 061      (case (first tree) +
+ + 062        :ACTION (simplify-second-of-two tree) +
+ + 063        :ACTIONS (cons (first tree) (simplify-rule (rest tree))) +
+ + 064        :CHANCE-IN nil +
+ + 065        :COMPARATIVE (simplify-second-of-two tree) +
+ + 066        :CONDITION (simplify-second-of-two tree) +
+ + 067        :CONDITIONS (simplify-second-of-two tree) +
+ + 068        :EXPRESSION (simplify-second-of-two tree) +
+ + 069        :PROPERTY (simplify-second-of-two tree) +
+ + 070        :PROPERTY-CONDITION-OR-EXPRESSION (simplify-second-of-two tree) +
+ + 071        :SPACE nil +
+ + 072        :THEN nil +
+ + 073        :AND nil +
+ + 074        :VALUE (simplify-second-of-two tree) +
+ + 075        (remove nil? (map simplify-rule tree))) +
+ + 076      tree)) +
+ + 077   +
+ + 078  (defn simplify-determiner-condition +
+ + 079    [tree] +
+ + 080    (apply vector +
+ + 081           (cons :DETERMINER-CONDITION +
+ + 082                 (cons +
+ + 083                  (simplify-second-of-two (second tree)) +
+ + 084                  (rest (rest tree)))))) +
+ + diff --git a/docs/cloverage/mw_parser/utils.clj.html b/docs/cloverage/mw_parser/utils.clj.html new file mode 100644 index 0000000..93367ea --- /dev/null +++ b/docs/cloverage/mw_parser/utils.clj.html @@ -0,0 +1,200 @@ + + + + mw_parser/utils.clj + + + + 001  (ns ^{:doc "Utilities used in more than one namespace within the parser." +
+ + 002        :author "Simon Brooke"} +
+ + 003    mw-parser.utils) +
+ + 004   +
+ + 005  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 006  ;;;; +
+ + 007  ;;;; mw-parser: a rule parser for MicroWorld. +
+ + 008  ;;;; +
+ + 009  ;;;; This program is free software; you can redistribute it and/or +
+ + 010  ;;;; modify it under the terms of the GNU General Public License +
+ + 011  ;;;; as published by the Free Software Foundation; either version 2 +
+ + 012  ;;;; of the License, or (at your option) any later version. +
+ + 013  ;;;; +
+ + 014  ;;;; This program is distributed in the hope that it will be useful, +
+ + 015  ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +
+ + 016  ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +
+ + 017  ;;;; GNU General Public License for more details. +
+ + 018  ;;;; +
+ + 019  ;;;; You should have received a copy of the GNU General Public License +
+ + 020  ;;;; along with this program; if not, write to the Free Software +
+ + 021  ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, +
+ + 022  ;;;; USA. +
+ + 023  ;;;; +
+ + 024  ;;;; Copyright (C) 2014 Simon Brooke +
+ + 025  ;;;; +
+ + 026  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +
+ + 027   +
+ + 028   +
+ + 029  (defn suitable-fragment? +
+ + 030    "Return `true` if `tree-fragment` appears to be a tree fragment of the expected `type`." +
+ + 031    [tree-fragment type] +
+ + 032    (and (coll? tree-fragment) +
+ + 033         (keyword? type) +
+ + 034         (= (first tree-fragment) type))) +
+ + 035   +
+ + 036  (defn rule? +
+ + 037    "Return true if the argument appears to be a parsed rule tree, else false." +
+ + 038    [maybe-rule] +
+ + 039    (suitable-fragment? maybe-rule :RULE)) +
+ + 040   +
+ + 041  (defn TODO +
+ + 042    "Marker to indicate I'm not yet finished!" +
+ + 043    [message] +
+ + 044    message) +
+ + 045   +
+ + 046   +
+ + 047   +
+ + 048  (defn assert-type +
+ + 049    "If `tree-fragment` is not a tree fragment of the expected `type`, throw an exception." +
+ + 050    [tree-fragment type] +
+ + 051    (assert (suitable-fragment? tree-fragment type) +
+ + 052            (throw (Exception. (format "Expected a %s fragment" type))))) +
+ + 053   +
+ + 054   +
+ + 055  (defn search-tree +
+ + 056    "Return the first element of this tree which has this tag in a depth-first, left-to-right search" +
+ + 057    [tree tag] +
+ + 058    (cond  +
+ + 059      (= (first tree) tag) tree +
+ + 060      :else (first +
+ + 061              (remove nil? +
+ + 062                      (map +
+ + 063                        #(search-tree % tag) +
+ + 064                        (filter coll? (rest tree))))))) +
+ + diff --git a/docs/codox/css/default.css b/docs/codox/css/default.css new file mode 100644 index 0000000..33f78fe --- /dev/null +++ b/docs/codox/css/default.css @@ -0,0 +1,551 @@ +body { + font-family: Helvetica, Arial, sans-serif; + font-size: 15px; +} + +pre, code { + font-family: Monaco, DejaVu Sans Mono, Consolas, monospace; + font-size: 9pt; + margin: 15px 0; +} + +h1 { + font-weight: normal; + font-size: 29px; + margin: 10px 0 2px 0; + padding: 0; +} + +h2 { + font-weight: normal; + font-size: 25px; +} + +h5.license { + margin: 9px 0 22px 0; + color: #555; + font-weight: normal; + font-size: 12px; + font-style: italic; +} + +.document h1, .namespace-index h1 { + font-size: 32px; + margin-top: 12px; +} + +#header, #content, .sidebar { + position: fixed; +} + +#header { + top: 0; + left: 0; + right: 0; + height: 22px; + color: #f5f5f5; + padding: 5px 7px; +} + +#content { + top: 32px; + right: 0; + bottom: 0; + overflow: auto; + background: #fff; + color: #333; + padding: 0 18px; +} + +.sidebar { + position: fixed; + top: 32px; + bottom: 0; + overflow: auto; +} + +.sidebar.primary { + background: #e2e2e2; + border-right: solid 1px #cccccc; + left: 0; + width: 250px; +} + +.sidebar.secondary { + background: #f2f2f2; + border-right: solid 1px #d7d7d7; + left: 251px; + width: 200px; +} + +#content.namespace-index, #content.document { + left: 251px; +} + +#content.namespace-docs { + left: 452px; +} + +#content.document { + padding-bottom: 10%; +} + +#header { + background: #3f3f3f; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.4); + z-index: 100; +} + +#header h1 { + margin: 0; + padding: 0; + font-size: 18px; + font-weight: lighter; + text-shadow: -1px -1px 0px #333; +} + +#header h1 .project-version { + font-weight: normal; +} + +.project-version { + padding-left: 0.15em; +} + +#header a, .sidebar a { + display: block; + text-decoration: none; +} + +#header a { + color: #f5f5f5; +} + +.sidebar a { + color: #333; +} + +#header h2 { + float: right; + font-size: 9pt; + font-weight: normal; + margin: 4px 3px; + padding: 0; + color: #bbb; +} + +#header h2 a { + display: inline; +} + +.sidebar h3 { + margin: 0; + padding: 10px 13px 0 13px; + font-size: 19px; + font-weight: lighter; +} + +.sidebar h3 a { + color: #444; +} + +.sidebar h3.no-link { + color: #636363; +} + +.sidebar ul { + padding: 7px 0 6px 0; + margin: 0; +} + +.sidebar ul.index-link { + padding-bottom: 4px; +} + +.sidebar li { + display: block; + vertical-align: middle; +} + +.sidebar li a, .sidebar li .no-link { + border-left: 3px solid transparent; + padding: 0 10px; + white-space: nowrap; +} + +.sidebar li .no-link { + display: block; + color: #777; + font-style: italic; +} + +.sidebar li .inner { + display: inline-block; + padding-top: 7px; + height: 24px; +} + +.sidebar li a, .sidebar li .tree { + height: 31px; +} + +.depth-1 .inner { padding-left: 2px; } +.depth-2 .inner { padding-left: 6px; } +.depth-3 .inner { padding-left: 20px; } +.depth-4 .inner { padding-left: 34px; } +.depth-5 .inner { padding-left: 48px; } +.depth-6 .inner { padding-left: 62px; } + +.sidebar li .tree { + display: block; + float: left; + position: relative; + top: -10px; + margin: 0 4px 0 0; + padding: 0; +} + +.sidebar li.depth-1 .tree { + display: none; +} + +.sidebar li .tree .top, .sidebar li .tree .bottom { + display: block; + margin: 0; + padding: 0; + width: 7px; +} + +.sidebar li .tree .top { + border-left: 1px solid #aaa; + border-bottom: 1px solid #aaa; + height: 19px; +} + +.sidebar li .tree .bottom { + height: 22px; +} + +.sidebar li.branch .tree .bottom { + border-left: 1px solid #aaa; +} + +.sidebar.primary li.current a { + border-left: 3px solid #a33; + color: #a33; +} + +.sidebar.secondary li.current a { + border-left: 3px solid #33a; + color: #33a; +} + +.namespace-index h2 { + margin: 30px 0 0 0; +} + +.namespace-index h3 { + font-size: 16px; + font-weight: bold; + margin-bottom: 0; +} + +.namespace-index .topics { + padding-left: 30px; + margin: 11px 0 0 0; +} + +.namespace-index .topics li { + padding: 5px 0; +} + +.namespace-docs h3 { + font-size: 18px; + font-weight: bold; +} + +.public h3 { + margin: 0; + float: left; +} + +.usage { + clear: both; +} + +.public { + margin: 0; + border-top: 1px solid #e0e0e0; + padding-top: 14px; + padding-bottom: 6px; +} + +.public:last-child { + margin-bottom: 20%; +} + +.members .public:last-child { + margin-bottom: 0; +} + +.members { + margin: 15px 0; +} + +.members h4 { + color: #555; + font-weight: normal; + font-variant: small-caps; + margin: 0 0 5px 0; +} + +.members .inner { + padding-top: 5px; + padding-left: 12px; + margin-top: 2px; + margin-left: 7px; + border-left: 1px solid #bbb; +} + +#content .members .inner h3 { + font-size: 12pt; +} + +.members .public { + border-top: none; + margin-top: 0; + padding-top: 6px; + padding-bottom: 0; +} + +.members .public:first-child { + padding-top: 0; +} + +h4.type, +h4.dynamic, +h4.added, +h4.deprecated { + float: left; + margin: 3px 10px 15px 0; + font-size: 15px; + font-weight: bold; + font-variant: small-caps; +} + +.public h4.type, +.public h4.dynamic, +.public h4.added, +.public h4.deprecated { + font-size: 13px; + font-weight: bold; + margin: 3px 0 0 10px; +} + +.members h4.type, +.members h4.added, +.members h4.deprecated { + margin-top: 1px; +} + +h4.type { + color: #717171; +} + +h4.dynamic { + color: #9933aa; +} + +h4.added { + color: #508820; +} + +h4.deprecated { + color: #880000; +} + +.namespace { + margin-bottom: 30px; +} + +.namespace:last-child { + margin-bottom: 10%; +} + +.index { + padding: 0; + font-size: 80%; + margin: 15px 0; + line-height: 16px; +} + +.index * { + display: inline; +} + +.index p { + padding-right: 3px; +} + +.index li { + padding-right: 5px; +} + +.index ul { + padding-left: 0; +} + +.type-sig { + clear: both; + color: #088; +} + +.type-sig pre { + padding-top: 10px; + margin: 0; +} + +.usage code { + display: block; + color: #008; + margin: 2px 0; +} + +.usage code:first-child { + padding-top: 10px; +} + +p { + margin: 15px 0; +} + +.public p:first-child, .public pre.plaintext { + margin-top: 12px; +} + +.doc { + margin: 0 0 26px 0; + clear: both; +} + +.public .doc { + margin: 0; +} + +.namespace-index .doc { + margin-bottom: 20px; +} + +.namespace-index .namespace .doc { + margin-bottom: 10px; +} + +.markdown p, .markdown li, .markdown dt, .markdown dd, .markdown td { + line-height: 22px; +} + +.markdown li { + padding: 2px 0; +} + +.markdown h2 { + font-weight: normal; + font-size: 25px; + margin: 30px 0 10px 0; +} + +.markdown h3 { + font-weight: normal; + font-size: 20px; + margin: 30px 0 0 0; +} + +.markdown h4 { + font-size: 15px; + margin: 22px 0 -4px 0; +} + +.doc, .public, .namespace .index { + max-width: 680px; + overflow-x: visible; +} + +.markdown pre > code { + display: block; + padding: 10px; +} + +.markdown pre > code, .src-link a { + border: 1px solid #e4e4e4; + border-radius: 2px; +} + +.markdown code:not(.hljs), .src-link a { + background: #f6f6f6; +} + +pre.deps { + display: inline-block; + margin: 0 10px; + border: 1px solid #e4e4e4; + border-radius: 2px; + padding: 10px; + background-color: #f6f6f6; +} + +.markdown hr { + border-style: solid; + border-top: none; + color: #ccc; +} + +.doc ul, .doc ol { + padding-left: 30px; +} + +.doc table { + border-collapse: collapse; + margin: 0 10px; +} + +.doc table td, .doc table th { + border: 1px solid #dddddd; + padding: 4px 6px; +} + +.doc table th { + background: #f2f2f2; +} + +.doc dl { + margin: 0 10px 20px 10px; +} + +.doc dl dt { + font-weight: bold; + margin: 0; + padding: 3px 0; + border-bottom: 1px solid #ddd; +} + +.doc dl dd { + padding: 5px 0; + margin: 0 0 5px 10px; +} + +.doc abbr { + border-bottom: 1px dotted #333; + font-variant: none; + cursor: help; +} + +.src-link { + margin-bottom: 15px; +} + +.src-link a { + font-size: 70%; + padding: 1px 4px; + text-decoration: none; + color: #5555bb; +} diff --git a/docs/codox/css/highlight.css b/docs/codox/css/highlight.css new file mode 100644 index 0000000..d0cdaa3 --- /dev/null +++ b/docs/codox/css/highlight.css @@ -0,0 +1,97 @@ +/* +github.com style (c) Vasily Polovnyov +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #333; + background: #f8f8f8; +} + +.hljs-comment, +.hljs-quote { + color: #998; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #333; + font-weight: bold; +} + +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-tag .hljs-attr { + color: #008080; +} + +.hljs-string, +.hljs-doctag { + color: #d14; +} + +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: #900; + font-weight: bold; +} + +.hljs-subst { + font-weight: normal; +} + +.hljs-type, +.hljs-class .hljs-title { + color: #458; + font-weight: bold; +} + +.hljs-tag, +.hljs-name, +.hljs-attribute { + color: #000080; + font-weight: normal; +} + +.hljs-regexp, +.hljs-link { + color: #009926; +} + +.hljs-symbol, +.hljs-bullet { + color: #990073; +} + +.hljs-built_in, +.hljs-builtin-name { + color: #0086b3; +} + +.hljs-meta { + color: #999; + font-weight: bold; +} + +.hljs-deletion { + background: #fdd; +} + +.hljs-addition { + background: #dfd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/docs/codox/index.html b/docs/codox/index.html new file mode 100644 index 0000000..8e7cd0c --- /dev/null +++ b/docs/codox/index.html @@ -0,0 +1,11 @@ + +Mw-parser 0.2.0-SNAPSHOT

Mw-parser 0.2.0-SNAPSHOT

Released under the GNU General Public License v2

Parser for production rules for MicroWorld engine.

Installation

To install, add the following dependency to your project or build file:

[mw-parser "0.2.0-SNAPSHOT"]

Topics

Namespaces

mw-parser.bulk

parse multiple rules from a stream, possibly a file.

+

mw-parser.declarative

A very simple parser which parses production rules.

+

mw-parser.errors

Display parse errors in a format which makes it easy for the user to see where the error occurred.

+

mw-parser.flow

A very simple parser which parses flow rules.

+

Public variables and functions:

mw-parser.utils

Utilities used in more than one namespace within the parser.

+

Public variables and functions:

\ No newline at end of file diff --git a/docs/codox/intro.html b/docs/codox/intro.html new file mode 100644 index 0000000..a6a5191 --- /dev/null +++ b/docs/codox/intro.html @@ -0,0 +1,5 @@ + +Introduction to mw-parser

Introduction to mw-parser

+

TODO: write great documentation

+
\ No newline at end of file diff --git a/docs/codox/js/highlight.min.js b/docs/codox/js/highlight.min.js new file mode 100644 index 0000000..6486ffd --- /dev/null +++ b/docs/codox/js/highlight.min.js @@ -0,0 +1,2 @@ +/*! highlight.js v9.6.0 | BSD3 License | git.io/hljslicense */ +!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/[&<>]/gm,function(e){return I[e]})}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return R(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||R(i))return i}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset"}function u(e){l+=""}function c(e){("start"===e.event?o:u)(e.node)}for(var s=0,l="",f=[];e.length||r.length;){var g=i();if(l+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===s);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return l+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):E(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"===e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var l=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=l.length?t(l.join("|"),!0):{exec:function(){return null}}}}r(e)}function l(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function g(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function h(e,n,t,r){var a=r?"":y.classPrefix,i='',i+n+o}function p(){var e,t,r,a;if(!E.k)return n(B);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(B);r;)a+=n(B.substr(t,r.index-t)),e=g(E,r),e?(M+=e[1],a+=h(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(B);return a+n(B.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!x[E.sL])return n(B);var t=e?l(E.sL,B,!0,L[E.sL]):f(B,E.sL.length?E.sL:void 0);return E.r>0&&(M+=t.r),e&&(L[E.sL]=t.top),h(t.language,t.value,!1,!0)}function b(){k+=null!=E.sL?d():p(),B=""}function v(e){k+=e.cN?h(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(B+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?B+=n:(t.eB&&(B+=n),b(),t.rB||t.eB||(B=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?B+=n:(a.rE||a.eE||(B+=n),b(),a.eE&&(B=n));do E.cN&&(k+=C),E.skip||(M+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"")+'"');return B+=n,n.length||1}var N=R(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var w,E=i||N,L={},k="";for(w=E;w!==N;w=w.parent)w.cN&&(k=h(w.cN,"",!0)+k);var B="",M=0;try{for(var I,j,O=0;;){if(E.t.lastIndex=O,I=E.t.exec(t),!I)break;j=m(t.substr(O,I.index-O),I[0]),O=I.index+j}for(m(t.substr(O)),w=E;w.parent;w=w.parent)w.cN&&(k+=C);return{r:M,value:k,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function f(e,t){t=t||y.languages||E(x);var r={r:0,value:n(e)},a=r;return t.filter(R).forEach(function(n){var t=l(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function g(e){return y.tabReplace||y.useBR?e.replace(M,function(e,n){return y.useBR&&"\n"===e?"
":y.tabReplace?n.replace(/\t/g,y.tabReplace):void 0}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function p(e){var n,t,r,o,s,p=i(e);a(p)||(y.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):n=e,s=n.textContent,r=p?l(p,s,!0):f(s),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),s)),r.value=g(r.value),e.innerHTML=r.value,e.className=h(e.className,p,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function d(e){y=o(y,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");w.forEach.call(e,p)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=x[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function N(){return E(x)}function R(e){return e=(e||"").toLowerCase(),x[e]||x[L[e]]}var w=[],E=Object.keys,x={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="
",y={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},I={"&":"&","<":"<",">":">"};return e.highlight=l,e.highlightAuto=f,e.fixMarkup=g,e.highlightBlock=p,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=R,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("clojure",function(e){var t={"builtin-name":"def defonce cond apply if-not if-let if not not= = < > <= >= == + / * - rem quot neg? pos? delay? symbol? keyword? true? false? integer? empty? coll? list? set? ifn? fn? associative? sequential? sorted? counted? reversible? number? decimal? class? distinct? isa? float? rational? reduced? ratio? odd? even? char? seq? vector? string? map? nil? contains? zero? instance? not-every? not-any? libspec? -> ->> .. . inc compare do dotimes mapcat take remove take-while drop letfn drop-last take-last drop-while while intern condp case reduced cycle split-at split-with repeat replicate iterate range merge zipmap declare line-seq sort comparator sort-by dorun doall nthnext nthrest partition eval doseq await await-for let agent atom send send-off release-pending-sends add-watch mapv filterv remove-watch agent-error restart-agent set-error-handler error-handler set-error-mode! error-mode shutdown-agents quote var fn loop recur throw try monitor-enter monitor-exit defmacro defn defn- macroexpand macroexpand-1 for dosync and or when when-not when-let comp juxt partial sequence memoize constantly complement identity assert peek pop doto proxy defstruct first rest cons defprotocol cast coll deftype defrecord last butlast sigs reify second ffirst fnext nfirst nnext defmulti defmethod meta with-meta ns in-ns create-ns import refer keys select-keys vals key val rseq name namespace promise into transient persistent! conj! assoc! dissoc! pop! disj! use class type num float double short byte boolean bigint biginteger bigdec print-method print-dup throw-if printf format load compile get-in update-in pr pr-on newline flush read slurp read-line subvec with-open memfn time re-find re-groups rand-int rand mod locking assert-valid-fdecl alias resolve ref deref refset swap! reset! set-validator! compare-and-set! alter-meta! reset-meta! commute get-validator alter ref-set ref-history-count ref-min-history ref-max-history ensure sync io! new next conj set! to-array future future-call into-array aset gen-class reduce map filter find empty hash-map hash-set sorted-map sorted-map-by sorted-set sorted-set-by vec vector seq flatten reverse assoc dissoc list disj get union difference intersection extend extend-type extend-protocol int nth delay count concat chunk chunk-buffer chunk-append chunk-first chunk-rest max min dec unchecked-inc-int unchecked-inc unchecked-dec-inc unchecked-dec unchecked-negate unchecked-add-int unchecked-add unchecked-subtract-int unchecked-subtract chunk-next chunk-cons chunked-seq? prn vary-meta lazy-seq spread list* str find-keyword keyword symbol gensym force rationalize"},r="a-zA-Z_\\-!.?+*=<>&#'",n="["+r+"]["+r+"0-9/;:]*",a="[-+]?\\d+(\\.\\d+)?",o={b:n,r:0},s={cN:"number",b:a,r:0},i=e.inherit(e.QSM,{i:null}),c=e.C(";","$",{r:0}),d={cN:"literal",b:/\b(true|false|nil)\b/},l={b:"[\\[\\{]",e:"[\\]\\}]"},m={cN:"comment",b:"\\^"+n},p=e.C("\\^\\{","\\}"),u={cN:"symbol",b:"[:]{1,2}"+n},f={b:"\\(",e:"\\)"},h={eW:!0,r:0},y={k:t,l:n,cN:"name",b:n,starts:h},b=[f,i,m,p,c,u,l,s,d,o];return f.c=[e.C("comment",""),y,h],h.c=b,l.c=b,{aliases:["clj"],i:/\S/,c:[f,i,m,p,c,u,l,s,d]}});hljs.registerLanguage("clojure-repl",function(e){return{c:[{cN:"meta",b:/^([\w.-]+|\s*#_)=>/,starts:{e:/$/,sL:"clojure"}}]}}); \ No newline at end of file diff --git a/docs/codox/js/jquery.min.js b/docs/codox/js/jquery.min.js new file mode 100644 index 0000000..73f33fb --- /dev/null +++ b/docs/codox/js/jquery.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m="1.11.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(l.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:k&&!k.call("\ufeff\xa0")?function(a){return null==a?"":k.call(a)}:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||n.guid++,e):void 0},now:function(){return+new Date},support:l}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=a.document,A=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,B=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:A.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:z,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=z.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return y.find(a);this.length=1,this[0]=d}return this.context=z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};B.prototype=n.fn,y=n(z);var C=/^(?:parents|prev(?:Until|All))/,D={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!n(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function E(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return E(a,"nextSibling")},prev:function(a){return E(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(D[a]||(e=n.unique(e)),C.test(a)&&(e=e.reverse())),this.pushStack(e)}});var F=/\S+/g,G={};function H(a){var b=G[a]={};return n.each(a.match(F)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?G[a]||H(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&n.each(arguments,function(a,c){var d;while((d=n.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){if(a===!0?!--n.readyWait:!n.isReady){if(!z.body)return setTimeout(n.ready);n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(z,[n]),n.fn.trigger&&n(z).trigger("ready").off("ready"))}}});function J(){z.addEventListener?(z.removeEventListener("DOMContentLoaded",K,!1),a.removeEventListener("load",K,!1)):(z.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(z.addEventListener||"load"===event.type||"complete"===z.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===z.readyState)setTimeout(n.ready);else if(z.addEventListener)z.addEventListener("DOMContentLoaded",K,!1),a.addEventListener("load",K,!1);else{z.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&z.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!n.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}J(),n.ready()}}()}return I.promise(b)};var L="undefined",M;for(M in n(l))break;l.ownLast="0"!==M,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c=z.getElementsByTagName("body")[0];c&&(a=z.createElement("div"),a.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",b=z.createElement("div"),c.appendChild(a).appendChild(b),typeof b.style.zoom!==L&&(b.style.cssText="border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1",(l.inlineBlockNeedsLayout=3===b.offsetWidth)&&(c.style.zoom=1)),c.removeChild(a),a=b=null)}),function(){var a=z.createElement("div");if(null==l.deleteExpando){l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}}a=null}(),n.acceptData=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(n.acceptData(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f +}}function S(a,b,c){if(n.acceptData(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d]));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},X=/^(?:checkbox|radio)$/i;!function(){var a=z.createDocumentFragment(),b=z.createElement("div"),c=z.createElement("input");if(b.setAttribute("className","t"),b.innerHTML="
a",l.leadingWhitespace=3===b.firstChild.nodeType,l.tbody=!b.getElementsByTagName("tbody").length,l.htmlSerialize=!!b.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==z.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,a.appendChild(c),l.appendChecked=c.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,a.appendChild(b),b.innerHTML="",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){l.noCloneEvent=!1}),b.cloneNode(!0).click()),null==l.deleteExpando){l.deleteExpando=!0;try{delete b.test}catch(d){l.deleteExpando=!1}}a=b=c=null}(),function(){var b,c,d=z.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),l[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var Y=/^(?:input|select|textarea)$/i,Z=/^key/,$=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;function bb(){return!0}function cb(){return!1}function db(){try{return z.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof n===L||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(F)||[""],h=b.length;while(h--)f=ab.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(F)||[""],j=b.length;while(j--)if(h=ab.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,m,o=[d||z],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||z,3!==d.nodeType&&8!==d.nodeType&&!_.test(p+n.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[n.expando]?b:new n.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),k=n.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!n.isWindow(d)){for(i=k.delegateType||p,_.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||z)&&o.push(l.defaultView||l.parentWindow||a)}m=0;while((h=o[m++])&&!b.isPropagationStopped())b.type=m>1?i:k.bindType||p,f=(n._data(h,"events")||{})[b.type]&&n._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&n.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&n.acceptData(d)&&g&&d[p]&&!n.isWindow(d)){l=d[g],l&&(d[g]=null),n.event.triggered=p;try{d[p]()}catch(r){}n.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((n.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?n(c,this).index(i)>=0:n.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ib=/^\s+/,jb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,kb=/<([\w:]+)/,lb=/\s*$/g,sb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]},tb=eb(z),ub=tb.appendChild(z.createElement("div"));sb.optgroup=sb.option,sb.tbody=sb.tfoot=sb.colgroup=sb.caption=sb.thead,sb.th=sb.td;function vb(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==L?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==L?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,vb(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function wb(a){X.test(a.type)&&(a.defaultChecked=a.checked)}function xb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function yb(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function zb(a){var b=qb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ab(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}function Bb(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Cb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(yb(b).text=a.text,zb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&X.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}n.extend({clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!hb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ub.innerHTML=a.outerHTML,ub.removeChild(f=ub.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=vb(f),h=vb(a),g=0;null!=(e=h[g]);++g)d[g]&&Cb(e,d[g]);if(b)if(c)for(h=h||vb(a),d=d||vb(f),g=0;null!=(e=h[g]);g++)Bb(e,d[g]);else Bb(a,f);return d=vb(f,"script"),d.length>0&&Ab(d,!i&&vb(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,m=a.length,o=eb(b),p=[],q=0;m>q;q++)if(f=a[q],f||0===f)if("object"===n.type(f))n.merge(p,f.nodeType?[f]:f);else if(mb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(kb.exec(f)||["",""])[1].toLowerCase(),k=sb[i]||sb._default,h.innerHTML=k[1]+f.replace(jb,"<$1>")+k[2],e=k[0];while(e--)h=h.lastChild;if(!l.leadingWhitespace&&ib.test(f)&&p.push(b.createTextNode(ib.exec(f)[0])),!l.tbody){f="table"!==i||lb.test(f)?""!==k[1]||lb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)n.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}n.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),l.appendChecked||n.grep(vb(p,"input"),wb),q=0;while(f=p[q++])if((!d||-1===n.inArray(f,d))&&(g=n.contains(f.ownerDocument,f),h=vb(o.appendChild(f),"script"),g&&Ab(h),c)){e=0;while(f=h[e++])pb.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.deleteExpando,m=n.event.special;null!=(d=a[h]);h++)if((b||n.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k?delete d[i]:typeof d.removeAttribute!==L?d.removeAttribute(i):d[i]=null,c.push(f))}}}),n.fn.extend({text:function(a){return W(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||z).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(vb(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&Ab(vb(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(vb(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return W(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(gb,""):void 0;if(!("string"!=typeof a||nb.test(a)||!l.htmlSerialize&&hb.test(a)||!l.leadingWhitespace&&ib.test(a)||sb[(kb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(jb,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(vb(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(vb(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,o=k-1,p=a[0],q=n.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&ob.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(i=n.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=n.map(vb(i,"script"),yb),f=g.length;k>j;j++)d=i,j!==o&&(d=n.clone(d,!0,!0),f&&n.merge(g,vb(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,n.map(g,zb),j=0;f>j;j++)d=g[j],pb.test(d.type||"")&&!n._data(d,"globalEval")&&n.contains(h,d)&&(d.src?n._evalUrl&&n._evalUrl(d.src):n.globalEval((d.text||d.textContent||d.innerHTML||"").replace(rb,"")));i=c=null}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],g=n(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Db,Eb={};function Fb(b,c){var d=n(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:n.css(d[0],"display");return d.detach(),e}function Gb(a){var b=z,c=Eb[a];return c||(c=Fb(a,b),"none"!==c&&c||(Db=(Db||n("