Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
commit
fe92045f14
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,3 +4,5 @@ buildall.tmp.*
|
||||||
target/
|
target/
|
||||||
pom.xml
|
pom.xml
|
||||||
|
|
||||||
|
|
||||||
|
.nrepl-port
|
||||||
|
|
|
@ -15,4 +15,4 @@
|
||||||
[org.clojure/tools.trace "0.7.11"]
|
[org.clojure/tools.trace "0.7.11"]
|
||||||
[instaparse "1.4.12"]
|
[instaparse "1.4.12"]
|
||||||
[mw-engine "0.1.6-SNAPSHOT"]
|
[mw-engine "0.1.6-SNAPSHOT"]
|
||||||
])
|
[trptr/java-wrapper "0.2.3"]])
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
(ns mw-parser.declarative
|
|
||||||
(:require [mw-engine.utils :refer [member?]])
|
|
||||||
(:require [instaparse.core :as insta]))
|
|
||||||
(ns ^{:doc "A very simple parser which parses production rules."
|
(ns ^{:doc "A very simple parser which parses production rules."
|
||||||
:author "Simon Brooke"}
|
:author "Simon Brooke"}
|
||||||
mw-parser.declarative
|
mw-parser.declarative
|
||||||
(:require [instaparse.core :as insta]
|
(:require [instaparse.core :as insta]
|
||||||
[clojure.string :refer [split trim triml]]
|
[clojure.string :refer [join trim]]
|
||||||
[mw-parser.errors :as pe]
|
[mw-parser.errors :refer [throw-parse-exception]]
|
||||||
[mw-parser.generate :as pg]
|
[mw-parser.generate :refer [generate]]
|
||||||
[mw-parser.simplify :as ps]
|
[mw-parser.simplify :refer [simplify]]
|
||||||
[mw-parser.utils :refer [rule?]]))
|
[mw-parser.utils :refer [rule?]]
|
||||||
|
[trptr.java-wrapper.locale :refer [get-default]])
|
||||||
|
(:import [java.util Locale]))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;
|
;;;;
|
||||||
|
@ -34,67 +33,85 @@
|
||||||
;;;;
|
;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
|
||||||
(def grammar
|
(def grammar
|
||||||
;; in order to simplify translation into other natural languages, all
|
"Basic rule language grammar.
|
||||||
;; TOKENS within the parser should be unambiguous
|
|
||||||
"RULE := IF SPACE CONDITIONS SPACE THEN SPACE ACTIONS;
|
in order to simplify translation into other natural languages, all
|
||||||
CONDITIONS := DISJUNCT-CONDITION | CONJUNCT-CONDITION | CONDITION ;
|
TOKENS within the parser should be unambiguou."
|
||||||
DISJUNCT-CONDITION := CONDITION SPACE OR SPACE CONDITIONS;
|
(join "\n" ["RULE := IF SPACE CONDITIONS SPACE THEN SPACE ACTIONS;"
|
||||||
CONJUNCT-CONDITION := CONDITION SPACE AND SPACE CONDITIONS;
|
"CONDITIONS := DISJUNCT-CONDITION | CONJUNCT-CONDITION | CONDITION ;"
|
||||||
CONDITION := WITHIN-CONDITION | NEIGHBOURS-CONDITION | PROPERTY-CONDITION;
|
"DISJUNCT-CONDITION := CONDITION SPACE OR SPACE CONDITIONS;"
|
||||||
WITHIN-CONDITION := QUANTIFIER SPACE NEIGHBOURS SPACE WITHIN SPACE NUMBER SPACE IS SPACE PROPERTY-CONDITION-OR-EXPRESSION;
|
"CONJUNCT-CONDITION := CONDITION SPACE AND SPACE CONDITIONS;"
|
||||||
NEIGHBOURS-CONDITION := QUANTIFIER SPACE NEIGHBOURS SPACE IS SPACE PROPERTY-CONDITION | QUALIFIER SPACE NEIGHBOURS-CONDITION;
|
"CONDITION := WITHIN-CONDITION | NEIGHBOURS-CONDITION | PROPERTY-CONDITION;"
|
||||||
PROPERTY-CONDITION-OR-EXPRESSION := PROPERTY-CONDITION | EXPRESSION;
|
"WITHIN-CONDITION := QUANTIFIER SPACE NEIGHBOURS SPACE WITHIN SPACE NUMBER SPACE IS SPACE PROPERTY-CONDITION-OR-EXPRESSION;"
|
||||||
PROPERTY-CONDITION := PROPERTY SPACE QUALIFIER SPACE EXPRESSION | VALUE;
|
"NEIGHBOURS-CONDITION := QUANTIFIER SPACE NEIGHBOURS SPACE IS SPACE PROPERTY-CONDITION | QUALIFIER SPACE NEIGHBOURS-CONDITION;"
|
||||||
EXPRESSION := SIMPLE-EXPRESSION | RANGE-EXPRESSION | NUMERIC-EXPRESSION | DISJUNCT-EXPRESSION | VALUE;
|
"PROPERTY-CONDITION-OR-EXPRESSION := PROPERTY-CONDITION | EXPRESSION;"
|
||||||
SIMPLE-EXPRESSION := QUALIFIER SPACE EXPRESSION | VALUE;
|
"PROPERTY-CONDITION := PROPERTY SPACE QUALIFIER SPACE EXPRESSION | VALUE;"
|
||||||
DISJUNCT-EXPRESSION := IN SPACE DISJUNCT-VALUE;
|
"EXPRESSION := SIMPLE-EXPRESSION | RANGE-EXPRESSION | NUMERIC-EXPRESSION | DISJUNCT-EXPRESSION | VALUE;"
|
||||||
RANGE-EXPRESSION := BETWEEN SPACE NUMERIC-EXPRESSION SPACE AND SPACE NUMERIC-EXPRESSION;
|
"SIMPLE-EXPRESSION := QUALIFIER SPACE EXPRESSION | VALUE;"
|
||||||
NUMERIC-EXPRESSION := VALUE | VALUE SPACE OPERATOR SPACE NUMERIC-EXPRESSION;
|
"DISJUNCT-EXPRESSION := IN SPACE DISJUNCT-VALUE;"
|
||||||
NEGATED-QUALIFIER := QUALIFIER SPACE NOT | NOT SPACE QUALIFIER;
|
"RANGE-EXPRESSION := BETWEEN SPACE NUMERIC-EXPRESSION SPACE AND SPACE NUMERIC-EXPRESSION;"
|
||||||
COMPARATIVE-QUALIFIER := IS SPACE COMPARATIVE SPACE THAN | COMPARATIVE SPACE THAN;
|
"NUMERIC-EXPRESSION := VALUE | VALUE SPACE OPERATOR SPACE NUMERIC-EXPRESSION;"
|
||||||
QUALIFIER := COMPARATIVE-QUALIFIER | NEGATED-QUALIFIER | EQUIVALENCE | IS SPACE QUALIFIER;
|
"NEGATED-QUALIFIER := QUALIFIER SPACE NOT | NOT SPACE QUALIFIER;"
|
||||||
QUANTIFIER := NUMBER | SOME | NONE | ALL | COMPARATIVE SPACE THAN SPACE NUMBER;
|
"COMPARATIVE-QUALIFIER := IS SPACE COMPARATIVE SPACE THAN | COMPARATIVE SPACE THAN;"
|
||||||
EQUIVALENCE := IS SPACE EQUAL | EQUAL | IS ;
|
"QUALIFIER := COMPARATIVE-QUALIFIER | NEGATED-QUALIFIER | EQUIVALENCE | IS SPACE QUALIFIER;"
|
||||||
COMPARATIVE := MORE | LESS;
|
"QUANTIFIER := NUMBER | SOME | NONE | ALL | COMPARATIVE SPACE THAN SPACE NUMBER;"
|
||||||
DISJUNCT-VALUE := VALUE | VALUE SPACE OR SPACE DISJUNCT-VALUE;
|
"EQUIVALENCE := IS SPACE EQUAL | EQUAL | IS ;"
|
||||||
IF := 'if';
|
"COMPARATIVE := MORE | LESS;"
|
||||||
THEN := 'then';
|
"DISJUNCT-VALUE := VALUE | VALUE SPACE OR SPACE DISJUNCT-VALUE;"
|
||||||
THAN := 'than';
|
"PROPERTY := SYMBOL;"
|
||||||
OR := 'or';
|
"VALUE := SYMBOL | NUMBER;"
|
||||||
NOT := 'not';
|
"OPERATOR := '+' | '-' | '*' | '/';"
|
||||||
AND := 'and';
|
"NUMBER := #'[0-9]+' | #'[0-9]+.[0-9]+';"
|
||||||
SOME := 'some';
|
"ACTIONS := ACTION | ACTION SPACE AND SPACE ACTIONS"
|
||||||
NONE := 'no';
|
"ACTION := SIMPLE-ACTION | PROBABLE-ACTION;"
|
||||||
ALL := 'all'
|
"PROBABLE-ACTION := VALUE SPACE CHANCE-IN SPACE VALUE SPACE SIMPLE-ACTION;"
|
||||||
BETWEEN := 'between';
|
"SIMPLE-ACTION := SYMBOL SPACE BECOMES SPACE EXPRESSION;"
|
||||||
WITHIN := 'within';
|
"SPACE := #'\\s+';"]))
|
||||||
IN := 'in';
|
|
||||||
MORE := 'more' | 'greater';
|
|
||||||
LESS := 'less' | 'fewer';
|
|
||||||
OPERATOR := '+' | '-' | '*' | '/';
|
|
||||||
NEIGHBOURS := 'neighbour' | 'neighbor' | 'neighbours' | 'neighbors';
|
|
||||||
PROPERTY := SYMBOL;
|
|
||||||
VALUE := SYMBOL | NUMBER;
|
|
||||||
EQUAL := 'equal to';
|
|
||||||
IS := 'is' | 'are' | 'have' | 'has';
|
|
||||||
NUMBER := #'[0-9]+' | #'[0-9]+.[0-9]+';
|
|
||||||
SYMBOL := #'[a-z]+';
|
|
||||||
ACTIONS := ACTION | ACTION SPACE AND SPACE ACTIONS
|
|
||||||
ACTION := SIMPLE-ACTION | PROBABLE-ACTION;
|
|
||||||
PROBABLE-ACTION := VALUE SPACE CHANCE-IN SPACE VALUE SPACE SIMPLE-ACTION;
|
|
||||||
SIMPLE-ACTION := SYMBOL SPACE BECOMES SPACE EXPRESSION;
|
|
||||||
CHANCE-IN := 'chance in';
|
|
||||||
BECOMES := 'should be' | 'becomes';
|
|
||||||
SPACE := #' *'";
|
|
||||||
)
|
|
||||||
|
|
||||||
|
(def keywords-en
|
||||||
|
"English language keyword literals used in rules.
|
||||||
|
|
||||||
|
It's a long term aim that the rule language should be easy to
|
||||||
|
internationalise; this isn't a full solution but it's a step towards
|
||||||
|
a solution."
|
||||||
|
(join "\n" ["IF := 'if';"
|
||||||
|
"THEN := 'then';"
|
||||||
|
"THAN := 'than';"
|
||||||
|
"OR := 'or';"
|
||||||
|
"NOT := 'not';"
|
||||||
|
"AND := 'and';"
|
||||||
|
"SOME := 'some';"
|
||||||
|
"NONE := 'no';"
|
||||||
|
"ALL := 'all'"
|
||||||
|
"BETWEEN := 'between';"
|
||||||
|
"WITHIN := 'within';"
|
||||||
|
"IN := 'in';"
|
||||||
|
"MORE := 'more' | 'greater';"
|
||||||
|
"LESS := 'less' | 'fewer';"
|
||||||
|
"NEIGHBOURS := 'neighbour' | 'neighbor' | 'neighbours' | 'neighbors';"
|
||||||
|
"EQUAL := 'equal to';"
|
||||||
|
"IS := 'is' | 'are' | 'have' | 'has';"
|
||||||
|
"CHANCE-IN := 'chance in';"
|
||||||
|
"BECOMES := 'should be' | 'becomes';"
|
||||||
|
;; SYMBOL is in the per-language file so that languages that use
|
||||||
|
;; (e.g.) Cyrillic characters can change the definition.
|
||||||
|
"SYMBOL := #'[a-z]+';"
|
||||||
|
]))
|
||||||
|
|
||||||
|
(defn select-keywords-for-locale
|
||||||
|
"For now, just return `keywords-en`; plan is to have resource files of
|
||||||
|
keywords for different languages in a resource directory, but that isn't
|
||||||
|
done yet. It's probably not going to work easily for languages that use
|
||||||
|
non-latin alphabets, anyway."
|
||||||
|
([]
|
||||||
|
(select-keywords-for-locale (get-default)))
|
||||||
|
([^Locale locale]
|
||||||
|
keywords-en))
|
||||||
|
|
||||||
(def parse-rule
|
(def parse-rule
|
||||||
"Parse the argument, assumed to be a string in the correct syntax, and return a parse tree."
|
"Parse the argument, assumed to be a string in the correct syntax, and return a parse tree."
|
||||||
(insta/parser grammar))
|
(insta/parser (join "\n" [grammar (select-keywords-for-locale)])))
|
||||||
|
|
||||||
|
|
||||||
(defn compile-rule
|
(defn compile-rule
|
||||||
"Parse this `rule-text`, a string conforming to the grammar of MicroWorld rules,
|
"Parse this `rule-text`, a string conforming to the grammar of MicroWorld rules,
|
||||||
|
@ -108,10 +125,10 @@
|
||||||
([rule-text return-tuple?]
|
([rule-text return-tuple?]
|
||||||
(assert (string? rule-text))
|
(assert (string? rule-text))
|
||||||
(let [rule (trim rule-text)
|
(let [rule (trim rule-text)
|
||||||
tree (ps/simplify (parse-rule rule))
|
tree (simplify (parse-rule rule))
|
||||||
afn (if (rule? tree) (eval (pg/generate tree))
|
afn (if (rule? tree) (eval (generate tree))
|
||||||
;; else
|
;; else
|
||||||
(pe/throw-parse-exception tree))]
|
(throw-parse-exception tree))]
|
||||||
(if return-tuple?
|
(if return-tuple?
|
||||||
(list afn rule)
|
(list afn rule)
|
||||||
;; else
|
;; else
|
||||||
|
|
0
src/mw_parser/flow.clj
Normal file
0
src/mw_parser/flow.clj
Normal file
Loading…
Reference in a new issue