Compare commits

..

No commits in common. "develop" and "master" have entirely different histories.

6 changed files with 48 additions and 170 deletions

View file

@ -1,31 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:og="https://ogp.me/ns#" lang="en" xml:lang="en">
<head>
<title>ANTONIVS ORNARE | SIMON RIVVLVS HOC FECIT | MMXXIV</title>
<a rel="me" href="https://mastodon.scot/@simon_brooke"></a>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
</head>
<body>
<h1>ANTONIVS ORNARE | SIMON RIVVLVS HOC FECIT | MMXXIV</h1>
<form>
<div class="widget">
<label for="input">COMPVTARE</label>
<input id="input" name="input" type="text" autocapitalize="characters" onchange="handleInputChange(this)">
</div>
<div class="result" id="result"></div>
</form>
<script src="js/antonine.js" type="text/javascript"></script>
<script type="text/javascript">
function handleInputChange(elt) {
if (event.key === 'Enter') {
event.preventDefault();
alert(ele.value);
}
}
</script>
</body>
</html>

View file

@ -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']);

View file

@ -1,8 +0,0 @@
EXPRESSION := NUMBER | NUMBER <SPACE> OPERATOR <SPACE> EXPRESSION
<NUMBER> := #'[IVXLCDM]+'
<OPERATOR> := ADD | SUBTRACT | MULTIPLY | DIVIDE
ADD := <'+'>
SUBTRACT := <'-'>
MULTIPLY := <'x'> | <'*'>
DIVIDE := <'/'>
SPACE := #'(?U)\s+'

View file

@ -1,19 +1,15 @@
(defproject antonine "0.2.1-SNAPSHOT" (defproject antonine "0.2.0"
:aot :all :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." :description "A calculator which uses Roman numerals."
:url "http://example.com/FIXME"
:license {:name "GNU General Public License" :license {:name "GNU General Public License"
:url "http://www.gnu.org/licenses/gpl-2.0.html"} :url "http://www.gnu.org/licenses/gpl-2.0.html"}
:main antonine.core :main antonine.core
:plugins [[com.bhauman/figwheel-main "0.2.18"] :dependencies [[instaparse "1.5.0"]
[com.bhauman/rebel-readline-cljs "0.1.4"] [org.clojure/clojure "1.11.3"]
[lein-cljsbuild "1.1.8"]] [org.clojure/tools.cli "1.1.230"]
[org.jline/jline "3.23.0"]]
:plugins [[lein-cljsbuild "1.1.8"]]
:profiles {:jar {:aot :all} :profiles {:jar {:aot :all}
:uberjar {:aot :all}} :uberjar {:aot :all}}
:url "http://example.com/FIXME") )

View file

@ -1,10 +1,7 @@
(ns antonine.calculator (ns antonine.calculator
(:require #?(:clj [clojure.java.io :refer [resource]]) (:require [clojure.math :refer [floor]]
#?(:clj [clojure.core :refer [format]] [instaparse.core :refer [get-failure]])
:cljs [goog.string :refer [format]]) (:import [java.lang NumberFormatException]))
[clojure.math :refer [floor]]
[instaparse.core :refer [get-failure parser]])
#?(:clj (:import [java.lang NumberFormatException])))
(defn incordec (defn incordec
"In reading roman numerals, a lower value character preceding a higher value may imply a decrement "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 \C) (incordec accumulator 500 100)
(= c \D) (+ 500 accumulator) (= c \D) (+ 500 accumulator)
(= c \M) (+ 1000 accumulator) (= c \M) (+ 1000 accumulator)
:else (let [m (format "Did not recognise the character '%c' as valid in a Roman number", c)] :else (throw
#?(:clj (NumberFormatException.
(throw (format "Did not recognise the character '%c'", c)))))
(NumberFormatException. m))
:cljs
(throw {:type :number-format-exception
:message m
:character c
:cause :reader})))))
(defn read-roman (defn read-roman
"Read this `input`, interpreting it as a Roman numeral, and return the "Read this `input`, interpreting it as a Roman numeral, and return the
@ -96,32 +87,27 @@
[arg1 arg2] [arg1 arg2]
(apply r-op (list / arg1 arg2))) (apply r-op (list / arg1 arg2)))
(def ^:export grammar (parser #?(:clj (resource "grammar.bnf")
:cljs (js/require "grammar.bnf"))))
(defn calculate (defn calculate
[input] [parse-tree]
(let [parse-tree (if (string? input) (grammar input) input) (let [failure-text (:text (get-failure parse-tree))]
failure-text (:text (get-failure parse-tree))] (if (= :EXPRESSION (first parse-tree))
(if (= :EXPRESSION (first parse-tree)) (case (count parse-tree)
(case (count parse-tree) 2 (read-roman (second parse-tree))
2 (read-roman (second parse-tree)) 4 (let [lhs (read-roman (second parse-tree))
4 (let [lhs (read-roman (second parse-tree)) op (case (first (nth parse-tree 2))
op (case (first (nth parse-tree 2)) :ADD +
:ADD + :MULTIPLY *
:MULTIPLY * :SUBTRACT -
:SUBTRACT - :DIVIDE /)
:DIVIDE /) rhs (calculate (nth parse-tree 3))]
rhs (calculate (nth parse-tree 3))] (int (floor (apply op (list lhs rhs)))))
(int (floor (apply op (list lhs rhs)))))
;;else ;;else
(throw
(ex-info
(format "Unexpected parse tree '%s'" failure-text)
{:problem parse-tree})))
(throw (throw
(ex-info (ex-info
(format "Unexpected expression: '%s'" failure-text) (format "Unexpected parse tree '%s'" failure-text)
{:problem parse-tree}))))) {:problem parse-tree})))
(throw
(ex-info
(format "Unexpected expression: '%s'" failure-text)
{:problem parse-tree})))))

View file

@ -1,15 +1,17 @@
(ns antonine.core (ns antonine.core
(:require [antonine.calculator :refer [calculate grammar write-roman]] (:require [antonine.calculator :refer [calculate write-roman]]
[antonine.char-reader :refer [read-chars]] [antonine.char-reader :refer [read-chars]]
[clojure.java.io :refer [resource]]
[clojure.pprint :refer [pprint]] [clojure.pprint :refer [pprint]]
[clojure.string :as s] [clojure.string :as s :refer [trim upper-case]]
[clojure.tools.cli :refer [parse-opts]]) [clojure.tools.cli :refer [parse-opts]]
[instaparse.core :refer [parser]])
(:gen-class)) (:gen-class))
(defn- romanise [arg] (defn- romanise [arg]
(s/replace (s/replace
(s/replace (s/replace
(s/upper-case arg) (upper-case arg)
"J" "I") "J" "I")
"U" "V")) "U" "V"))
@ -28,6 +30,8 @@
;; A boolean option defaulting to nil ;; A boolean option defaulting to nil
["-h" "--help"]]) ["-h" "--help"]])
(def grammar (parser (resource "grammar.bnf")))
(defn repl (defn repl
"Read/eval/print loop, using these command line `options`." "Read/eval/print loop, using these command line `options`."
[options] [options]
@ -37,15 +41,16 @@
(try (loop [] (try (loop []
(flush) (flush)
(try (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)) (if (or (empty? input) (= input stop-word))
(throw (throw
(ex-info (ex-info
(format "\nVALE %s" (romanise (System/getProperty "user.name"))) (format "\nVALE %s" (romanise (System/getProperty "user.name")))
{:cause :quit})) {:cause :quit}))
(let [v (calculate input)] (let [tree (grammar input)
v (calculate tree)]
(when (> vrb 1) (when (> vrb 1)
(println (format "(Parse tree: %s)" (grammar input)))) (println (format "(Parse tree: %s)" tree)))
(when (> vrb 0) (println (format "(Arabic: %d)" v))) (when (> vrb 0) (println (format "(Arabic: %d)" v)))
(println (write-roman v)))) (println (write-roman v))))
(println)) (println))
@ -86,4 +91,4 @@
(if (empty? arguments) (if (empty? arguments)
(repl options) (repl options)
(println (write-roman (calculate (grammar (s/trim (s/join " " arguments))))))))) (println (write-roman (calculate (grammar (trim (s/join " " arguments)))))))))