diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 3f0bde8..0000000 --- a/docs/index.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - ANTONIVS ORNARE | SIMON RIVVLVS HOC FECIT | MMXXIV - - - - - - -

ANTONIVS ORNARE | SIMON RIVVLVS HOC FECIT | MMXXIV

-
-
- - -
-
-
- - - - - \ No newline at end of file diff --git a/docs/js/antonine.js b/docs/js/antonine.js deleted file mode 100644 index 9146fa0..0000000 --- a/docs/js/antonine.js +++ /dev/null @@ -1,70 +0,0 @@ -goog.addDependency("base.js", ['goog'], []); -goog.addDependency("debug/error.js", ['goog.debug.Error'], []); -goog.addDependency("dom/nodetype.js", ['goog.dom.NodeType'], []); -goog.addDependency("asserts/asserts.js", ['goog.asserts'], ['goog.debug.Error', 'goog.dom.NodeType']); -goog.addDependency("dom/htmlelement.js", ['goog.dom.HtmlElement'], []); -goog.addDependency("dom/tagname.js", ['goog.dom.TagName'], ['goog.dom.HtmlElement']); -goog.addDependency("dom/element.js", ['goog.dom.element'], ['goog.dom.NodeType', 'goog.dom.TagName']); -goog.addDependency("asserts/dom.js", ['goog.asserts.dom'], ['goog.dom.TagName', 'goog.asserts', 'goog.dom.element']); -goog.addDependency("dom/asserts.js", ['goog.dom.asserts'], ['goog.asserts']); -goog.addDependency("functions/functions.js", ['goog.functions'], []); -goog.addDependency("string/typedstring.js", ['goog.string.TypedString'], []); -goog.addDependency("string/const.js", ['goog.string.Const'], ['goog.asserts', 'goog.string.TypedString']); -goog.addDependency("html/trustedtypes.js", ['goog.html.trustedtypes'], []); -goog.addDependency("html/safescript.js", ['goog.html.SafeScript'], ['goog.string.Const', 'goog.string.TypedString', 'goog.html.trustedtypes', 'goog.asserts']); -goog.addDependency("fs/url.js", ['goog.fs.url'], []); -goog.addDependency("fs/blob.js", ['goog.fs.blob'], []); -goog.addDependency("html/trustedresourceurl.js", ['goog.html.TrustedResourceUrl'], ['goog.asserts', 'goog.fs.blob', 'goog.fs.url', 'goog.html.SafeScript', 'goog.html.trustedtypes', 'goog.string.Const', 'goog.string.TypedString']); -goog.addDependency("string/internal.js", ['goog.string.internal'], []); -goog.addDependency("html/safeurl.js", ['goog.html.SafeUrl'], ['goog.asserts', 'goog.fs.url', 'goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.string.TypedString', 'goog.string.internal']); -goog.addDependency("html/safestyle.js", ['goog.html.SafeStyle'], ['goog.string.Const', 'goog.html.SafeUrl', 'goog.string.TypedString', 'goog.asserts', 'goog.string.internal']); -goog.addDependency("object/object.js", ['goog.object'], []); -goog.addDependency("html/safestylesheet.js", ['goog.html.SafeStyleSheet'], ['goog.string.Const', 'goog.html.SafeStyle', 'goog.string.TypedString', 'goog.object', 'goog.asserts', 'goog.string.internal']); -goog.addDependency("flags/flags.js", ['goog.flags'], []); -goog.addDependency("labs/useragent/useragent.js", ['goog.labs.userAgent'], ['goog.flags']); -goog.addDependency("labs/useragent/util.js", ['goog.labs.userAgent.util'], ['goog.string.internal', 'goog.labs.userAgent']); -goog.addDependency("labs/useragent/highentropy/highentropyvalue.js", ['goog.labs.userAgent.highEntropy.highEntropyValue'], ['goog.labs.userAgent.util', 'goog.string.internal']); -goog.addDependency("labs/useragent/highentropy/highentropydata.js", ['goog.labs.userAgent.highEntropy.highEntropyData'], ['goog.labs.userAgent.highEntropy.highEntropyValue']); -goog.addDependency("labs/useragent/browser.js", ['goog.labs.userAgent.browser'], ['goog.labs.userAgent.util', 'goog.labs.userAgent.highEntropy.highEntropyValue', 'goog.asserts', 'goog.string.internal', 'goog.labs.userAgent.highEntropy.highEntropyData', 'goog.labs.userAgent']); -goog.addDependency("array/array.js", ['goog.array'], ['goog.asserts']); -goog.addDependency("dom/tags.js", ['goog.dom.tags'], ['goog.object']); -goog.addDependency("html/safehtml.js", ['goog.html.SafeHtml'], ['goog.string.Const', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.dom.TagName', 'goog.html.TrustedResourceUrl', 'goog.string.TypedString', 'goog.asserts', 'goog.labs.userAgent.browser', 'goog.array', 'goog.object', 'goog.string.internal', 'goog.dom.tags', 'goog.html.trustedtypes']); -goog.addDependency("html/uncheckedconversions.js", ['goog.html.uncheckedconversions'], ['goog.asserts', 'goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeStyleSheet', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.string.Const', 'goog.string.internal']); -goog.addDependency("dom/safe.js", ['goog.dom.safe', 'goog.dom.safe.InsertAdjacentHtmlPosition'], ['goog.asserts', 'goog.asserts.dom', 'goog.dom.asserts', 'goog.functions', 'goog.html.SafeHtml', 'goog.html.SafeScript', 'goog.html.SafeStyle', 'goog.html.SafeUrl', 'goog.html.TrustedResourceUrl', 'goog.html.uncheckedconversions', 'goog.string.Const', 'goog.string.internal']); -goog.addDependency("string/string.js", ['goog.string', 'goog.string.Unicode'], ['goog.dom.safe', 'goog.html.uncheckedconversions', 'goog.string.Const', 'goog.string.internal']); -goog.addDependency("collections/maps.js", ['goog.collections.maps'], []); -goog.addDependency("structs/structs.js", ['goog.structs'], ['goog.array', 'goog.object']); -goog.addDependency("uri/utils.js", ['goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.QueryArray', 'goog.uri.utils.QueryValue', 'goog.uri.utils.StandardQueryParam'], ['goog.asserts', 'goog.string']); -goog.addDependency("uri/uri.js", ['goog.Uri', 'goog.Uri.QueryData'], ['goog.array', 'goog.asserts', 'goog.collections.maps', 'goog.string', 'goog.structs', 'goog.uri.utils', 'goog.uri.utils.ComponentIndex', 'goog.uri.utils.StandardQueryParam']); -goog.addDependency("reflect/reflect.js", ['goog.reflect'], []); -goog.addDependency("math/integer.js", ['goog.math.Integer'], ['goog.reflect']); -goog.addDependency("string/stringbuffer.js", ['goog.string.StringBuffer'], []); -goog.addDependency("math/long.js", ['goog.math.Long'], ['goog.asserts', 'goog.reflect']); -goog.addDependency("../cljs/core.js", ['cljs.core'], ['goog.string', 'goog.Uri', 'goog.object', 'goog.math.Integer', 'goog.string.StringBuffer', 'goog.array', 'goog.math.Long']); -goog.addDependency("../process/env.js", ['process.env'], ['cljs.core']); -goog.addDependency("../cljs/math.js", ['cljs.math'], ['cljs.core']); -goog.addDependency("../instaparse/util.js", ['instaparse.util'], ['cljs.core']); -goog.addDependency("../instaparse/auto_flatten_seq.js", ['instaparse.auto_flatten_seq'], ['cljs.core']); -goog.addDependency("../instaparse/reduction.js", ['instaparse.reduction'], ['cljs.core', 'instaparse.util', 'instaparse.auto_flatten_seq']); -goog.addDependency("../instaparse/combinators_source.js", ['instaparse.combinators_source'], ['instaparse.reduction', 'cljs.core', 'instaparse.util']); -goog.addDependency("../clojure/string.js", ['clojure.string'], ['goog.string', 'cljs.core', 'goog.string.StringBuffer']); -goog.addDependency("../instaparse/print.js", ['instaparse.print'], ['cljs.core', 'clojure.string']); -goog.addDependency("i18n/uchar.js", ['goog.i18n.uChar'], []); -goog.addDependency("../instaparse/failure.js", ['instaparse.failure'], ['instaparse.print', 'cljs.core']); -goog.addDependency("../instaparse/gll.js", ['instaparse.gll'], ['instaparse.combinators_source', 'instaparse.print', 'instaparse.reduction', 'cljs.core', 'goog.i18n.uChar', 'instaparse.util', 'instaparse.auto_flatten_seq', 'instaparse.failure']); -goog.addDependency("../instaparse/transform.js", ['instaparse.transform'], ['cljs.core', 'instaparse.util', 'instaparse.gll']); -goog.addDependency("../instaparse/line_col.js", ['instaparse.line_col'], ['cljs.core', 'instaparse.transform', 'instaparse.util']); -goog.addDependency("../cljs/tools/reader/impl/utils.js", ['cljs.tools.reader.impl.utils'], ['goog.string', 'cljs.core', 'clojure.string']); -goog.addDependency("../cljs/tools/reader/reader_types.js", ['cljs.tools.reader.reader_types'], ['goog.string', 'cljs.core', 'goog.string.StringBuffer', 'cljs.tools.reader.impl.utils']); -goog.addDependency("../cljs/tools/reader/impl/inspect.js", ['cljs.tools.reader.impl.inspect'], ['cljs.core']); -goog.addDependency("../cljs/tools/reader/impl/errors.js", ['cljs.tools.reader.impl.errors'], ['cljs.core', 'cljs.tools.reader.reader_types', 'cljs.tools.reader.impl.inspect', 'clojure.string']); -goog.addDependency("../cljs/tools/reader/impl/commons.js", ['cljs.tools.reader.impl.commons'], ['cljs.tools.reader.impl.errors', 'cljs.core', 'cljs.tools.reader.reader_types', 'cljs.tools.reader.impl.utils']); -goog.addDependency("../cljs/tools/reader.js", ['cljs.tools.reader'], ['cljs.tools.reader.impl.commons', 'goog.string', 'cljs.tools.reader.impl.errors', 'cljs.core', 'cljs.tools.reader.reader_types', 'goog.string.StringBuffer', 'cljs.tools.reader.impl.utils', 'goog.array']); -goog.addDependency("../instaparse/cfg.js", ['instaparse.cfg'], ['instaparse.combinators_source', 'cljs.tools.reader', 'instaparse.reduction', 'cljs.core', 'cljs.tools.reader.reader_types', 'instaparse.util', 'instaparse.gll', 'clojure.string']); -goog.addDependency("string/stringformat.js", ['goog.string.format'], ['goog.string']); -goog.addDependency("../clojure/walk.js", ['clojure.walk'], ['cljs.core']); -goog.addDependency("../instaparse/abnf.js", ['instaparse.abnf'], ['instaparse.combinators_source', 'instaparse.reduction', 'cljs.core', 'instaparse.transform', 'instaparse.cfg', 'instaparse.util', 'goog.string.format', 'instaparse.gll', 'clojure.walk']); -goog.addDependency("../instaparse/viz.js", ['instaparse.viz'], ['cljs.core']); -goog.addDependency("../instaparse/repeat.js", ['instaparse.repeat'], ['instaparse.combinators_source', 'instaparse.reduction', 'cljs.core', 'instaparse.auto_flatten_seq', 'instaparse.failure', 'instaparse.gll', 'instaparse.viz']); -goog.addDependency("../instaparse/core.js", ['instaparse.core'], ['instaparse.combinators_source', 'instaparse.line_col', 'instaparse.print', 'instaparse.reduction', 'cljs.core', 'instaparse.transform', 'instaparse.cfg', 'instaparse.util', 'instaparse.abnf', 'instaparse.failure', 'instaparse.gll', 'instaparse.viz', 'clojure.walk', 'instaparse.repeat']); -goog.addDependency("../antonine/calculator.js", ['antonine.calculator'], ['goog.string', 'cljs.math', 'instaparse.core', 'cljs.core']); diff --git a/docs/js/grammar.bnf b/docs/js/grammar.bnf deleted file mode 100644 index d9ce30c..0000000 --- a/docs/js/grammar.bnf +++ /dev/null @@ -1,8 +0,0 @@ -EXPRESSION := NUMBER | NUMBER OPERATOR EXPRESSION - := #'[IVXLCDM]+' - := ADD | SUBTRACT | MULTIPLY | DIVIDE -ADD := <'+'> -SUBTRACT := <'-'> -MULTIPLY := <'x'> | <'*'> -DIVIDE := <'/'> -SPACE := #'(?U)\s+' \ No newline at end of file diff --git a/project.clj b/project.clj index b2e5cf2..f258f07 100644 --- a/project.clj +++ b/project.clj @@ -1,19 +1,15 @@ -(defproject antonine "0.2.1-SNAPSHOT" +(defproject antonine "0.2.0" :aot :all - :cljsbuild {:builds [{:source-paths ["src"] - :compiler {:output-to "docs/js/antonine.js"}}]} - :dependencies [[instaparse "1.5.0"] - [org.clojure/clojure "1.11.3"] - [org.clojure/clojurescript "1.11.132"] - [org.clojure/tools.cli "1.1.230"] - [org.jline/jline "3.23.0"]] :description "A calculator which uses Roman numerals." + :url "http://example.com/FIXME" :license {:name "GNU General Public License" :url "http://www.gnu.org/licenses/gpl-2.0.html"} :main antonine.core - :plugins [[com.bhauman/figwheel-main "0.2.18"] - [com.bhauman/rebel-readline-cljs "0.1.4"] - [lein-cljsbuild "1.1.8"]] + :dependencies [[instaparse "1.5.0"] + [org.clojure/clojure "1.11.3"] + [org.clojure/tools.cli "1.1.230"] + [org.jline/jline "3.23.0"]] + :plugins [[lein-cljsbuild "1.1.8"]] :profiles {:jar {:aot :all} :uberjar {:aot :all}} - :url "http://example.com/FIXME") + ) diff --git a/src/antonine/calculator.cljc b/src/antonine/calculator.cljc index f2a05ac..e224100 100644 --- a/src/antonine/calculator.cljc +++ b/src/antonine/calculator.cljc @@ -1,10 +1,7 @@ (ns antonine.calculator - (:require #?(:clj [clojure.java.io :refer [resource]]) - #?(:clj [clojure.core :refer [format]] - :cljs [goog.string :refer [format]]) - [clojure.math :refer [floor]] - [instaparse.core :refer [get-failure parser]]) - #?(:clj (:import [java.lang NumberFormatException]))) + (:require [clojure.math :refer [floor]] + [instaparse.core :refer [get-failure]]) + (:import [java.lang NumberFormatException])) (defn incordec "In reading roman numerals, a lower value character preceding a higher value may imply a decrement @@ -23,15 +20,9 @@ (= c \C) (incordec accumulator 500 100) (= c \D) (+ 500 accumulator) (= c \M) (+ 1000 accumulator) - :else (let [m (format "Did not recognise the character '%c' as valid in a Roman number", c)] - #?(:clj - (throw - (NumberFormatException. m)) - :cljs - (throw {:type :number-format-exception - :message m - :character c - :cause :reader}))))) + :else (throw + (NumberFormatException. + (format "Did not recognise the character '%c'", c))))) (defn read-roman "Read this `input`, interpreting it as a Roman numeral, and return the @@ -96,32 +87,27 @@ [arg1 arg2] (apply r-op (list / arg1 arg2))) - -(def ^:export grammar (parser #?(:clj (resource "grammar.bnf") - :cljs (js/require "grammar.bnf")))) - (defn calculate - [input] - (let [parse-tree (if (string? input) (grammar input) input) - failure-text (:text (get-failure parse-tree))] - (if (= :EXPRESSION (first parse-tree)) - (case (count parse-tree) - 2 (read-roman (second parse-tree)) - 4 (let [lhs (read-roman (second parse-tree)) - op (case (first (nth parse-tree 2)) - :ADD + - :MULTIPLY * - :SUBTRACT - - :DIVIDE /) - rhs (calculate (nth parse-tree 3))] - (int (floor (apply op (list lhs rhs))))) + [parse-tree] + (let [failure-text (:text (get-failure parse-tree))] + (if (= :EXPRESSION (first parse-tree)) + (case (count parse-tree) + 2 (read-roman (second parse-tree)) + 4 (let [lhs (read-roman (second parse-tree)) + op (case (first (nth parse-tree 2)) + :ADD + + :MULTIPLY * + :SUBTRACT - + :DIVIDE /) + rhs (calculate (nth parse-tree 3))] + (int (floor (apply op (list lhs rhs))))) ;;else - (throw - (ex-info - (format "Unexpected parse tree '%s'" failure-text) - {:problem parse-tree}))) - (throw - (ex-info - (format "Unexpected expression: '%s'" failure-text) - {:problem parse-tree}))))) + (throw + (ex-info + (format "Unexpected parse tree '%s'" failure-text) + {:problem parse-tree}))) + (throw + (ex-info + (format "Unexpected expression: '%s'" failure-text) + {:problem parse-tree}))))) diff --git a/src/antonine/core.clj b/src/antonine/core.clj index 8b4acf5..94a99aa 100644 --- a/src/antonine/core.clj +++ b/src/antonine/core.clj @@ -1,15 +1,17 @@ (ns antonine.core - (:require [antonine.calculator :refer [calculate grammar write-roman]] + (:require [antonine.calculator :refer [calculate write-roman]] [antonine.char-reader :refer [read-chars]] + [clojure.java.io :refer [resource]] [clojure.pprint :refer [pprint]] - [clojure.string :as s] - [clojure.tools.cli :refer [parse-opts]]) + [clojure.string :as s :refer [trim upper-case]] + [clojure.tools.cli :refer [parse-opts]] + [instaparse.core :refer [parser]]) (:gen-class)) (defn- romanise [arg] (s/replace (s/replace - (s/upper-case arg) + (upper-case arg) "J" "I") "U" "V")) @@ -28,6 +30,8 @@ ;; A boolean option defaulting to nil ["-h" "--help"]]) +(def grammar (parser (resource "grammar.bnf"))) + (defn repl "Read/eval/print loop, using these command line `options`." [options] @@ -37,15 +41,16 @@ (try (loop [] (flush) (try - (if-let [input (s/trim (s/upper-case (read-chars prompt)))] + (if-let [input (trim (upper-case (read-chars prompt)))] (if (or (empty? input) (= input stop-word)) (throw (ex-info (format "\nVALE %s" (romanise (System/getProperty "user.name"))) {:cause :quit})) - (let [v (calculate input)] + (let [tree (grammar input) + v (calculate tree)] (when (> vrb 1) - (println (format "(Parse tree: %s)" (grammar input)))) + (println (format "(Parse tree: %s)" tree))) (when (> vrb 0) (println (format "(Arabic: %d)" v))) (println (write-roman v)))) (println)) @@ -86,4 +91,4 @@ (if (empty? arguments) (repl options) - (println (write-roman (calculate (grammar (s/trim (s/join " " arguments))))))))) \ No newline at end of file + (println (write-roman (calculate (grammar (trim (s/join " " arguments))))))))) \ No newline at end of file