Skip to content

Commit

Permalink
Add comparison operators & ternary operator (#41)
Browse files Browse the repository at this point in the history
* add comparison operators

* add ternary operator

* document new features

* bump version

* wrap condition with '()'

* update line in the README related to a ternary op syntax change
  • Loading branch information
shevchuk committed Feb 17, 2023
1 parent 7f71a75 commit e36e8aa
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 22 deletions.
38 changes: 21 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,23 +196,25 @@ referenced in a subsequent function definition:

### Aliased Operators & Functions

| Alias | Operator | | Alias | Operator | | Alias | Operator |
| ------- | ----------------------- | --- | ------ | --------------- | --- | ----- | --------------- |
| && | and | | abs | Math/abs | | sin | Math/sin |
| \|\| | or | | signum | Math/signum | | cos | Math/cos |
| == | = | | \*\* | Math/pow | | tan | Math/tan |
| != | not= | | exp | Math/exp | | asin | Math/asin |
| % | mod | | log | Math/log | | acos | Math/acos |
| << | bit-shift-left | | e | Math/E | | atan | Math/atan |
| >> | bit-shift-right | | π | Math/PI | | sinh | Math/sinh |
| ! | not | | sqrt | Math/sqrt | | cosh | Math/cosh |
| & | bit-and | | √ | Math/sqrt | | tanh | Math/tanh |
| \| | bit-or | | root | b √ a | | sec | Secant |
| | | | φ | Golden ratio | | csc | Cosecant |
| gcd     | Greatest common divisor |   | fact   | Factorial       |   | cot   | Cotangent       |
| lcm | Least common multiple | | ∑ | Sum | | asec | Arcsecant |
| rand | Random number generator | | ∏ | Product | | acsc | Arccosecant |
| randInt | Random int between 0..n | | | | | acot | Arccotangent |
| Alias | Operator | | Alias | Operator | | Alias | Operator |
|---------|-------------------------|---|--------|--------------|---|-------|--------------|
| && | and | | abs | Math/abs | | sin | Math/sin |
| \|\| | or | | signum | Math/signum | | cos | Math/cos |
| == | = | | \*\* | Math/pow | | tan | Math/tan |
| > | > | | < | < | | | |
| >= | >= | | <= | <= | | | |
| != | not= | | exp | Math/exp | | asin | Math/asin |
| % | mod | | log | Math/log | | acos | Math/acos |
| << | bit-shift-left | | e | Math/E | | atan | Math/atan |
| >> | bit-shift-right | | π | Math/PI | | sinh | Math/sinh |
| ! | not | | sqrt | Math/sqrt | | cosh | Math/cosh |
| & | bit-and | | √ | Math/sqrt | | tanh | Math/tanh |
| \| | bit-or | | root | b √ a | | sec | Secant |
| | | | φ | Golden ratio | | csc | Cosecant |
| gcd | Greatest common divisor | | fact | Factorial | | cot | Cotangent |
| lcm | Least common multiple | | ∑ | Sum | | asec | Arcsecant |
| rand | Random number generator | | ∏ | Product | | acsc | Arccosecant |
| randInt | Random int between 0..n | | | | | acot | Arccotangent |

## EBNF Grammar Rules

Expand All @@ -236,6 +238,8 @@ as follows:

- _**&lt;function&gt;** ::= envref expression | envref "(" &lt;empty&gt; | expression { "," expression } ")"._

- _**&lt;ternary&gt;** ::= "(" expression ")" "?" expression ":" expression._

- _**&lt;envref&gt;** ::= letter { letter | digit | "_" }.\_

- _**&lt;var&gt;** ::= envref._
Expand Down
2 changes: 1 addition & 1 deletion project.clj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(defproject rm-hull/infix "0.4.0"
(defproject rm-hull/infix "0.4.1"
:description "A small Clojure library for expressing LISP expressions as infix rather than prefix notation"
:url "https://github.com/rm-hull/infix"
:license {
Expand Down
6 changes: 5 additions & 1 deletion src/infix/core.clj
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,8 @@
:/ /
:% mod
:&& logical-and
:|| logical-or}))
:|| logical-or
:> >
:< <
:>= >=
:<= <=}))
22 changes: 19 additions & 3 deletions src/infix/grammar.clj
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@
; expression ::= term { addop term }.
; term ::= factor { mulop factor }.
; factor ::= base { expop base }
; base ::= "(" expression ")" | boolean | number | var | function.
; base ::= "(" expression ")" | boolean | number | var | function | ternary.
; addop ::= "+" | "-".
; mulop ::= "*" | "/".
; expop ::= "**"
;
; function ::= envref expression | envref "(" <empty> | expression { "," expression } ")".
; ternary ::= expression "?" expression ":" expression.
; envref ::= letter { letter | digit | "_" }.
; var ::= envref.
; boolean :: = "true" | "false"
Expand Down Expand Up @@ -147,6 +148,20 @@
(f env)
(map #(% env) args)))))))

(def ternary-op
(m/do*
(symb "(")
(condition <- expression)
(symb ")")
(symb "?")
(yes-exp <- expression)
(symb ":")
(no-exp <- expression)
(m/return (fn [env]
(if (condition env) (yes-exp env) (no-exp env))))
)
)

(def base
(any-of
(m/do*
Expand All @@ -157,7 +172,8 @@
boolean
number
var
function))
function
ternary-op))

(defn binary-op [& ops]
(m/do*
Expand All @@ -171,7 +187,7 @@
(str (name kw) " is not bound in environment")))))))))

(def expop (binary-op "**"))
(def mulop (binary-op "*" "/" "÷" "%" ">>" ">>>" "<<" "=" "==" "!="))
(def mulop (binary-op "*" "/" "÷" "%" ">>" ">>>" "<<" "=" "==" "!=" ">" "<" ">=" "<="))
(def addop (binary-op "+" "-" "|" "&" "||" "&&"))

(defn- resolve-var [arg env]
Expand Down
6 changes: 6 additions & 0 deletions test/infix/grammar_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@
(is (= 43 ((parse-all expression "3 + 5 * 8") env)))
(is (= 64 ((parse-all expression "(3 + 5) * 8") env)))))

(deftest check-ternary-op
(let [env (merge base-env {:t 150 :x 10 :y 20})]
(is (= 1 ((parse-all ternary-op "(t > 100) ? 1 : 0") env)))
(is (= -10 ((parse-all ternary-op "(t < 100) ? x + y : x - y") env)))
(is (= 30 ((parse-all ternary-op "(sum(x, y) >= 30) ? sum(x, y) : 0") env)))))

(deftest check-baseenv-functions
(is (= 16 ((parse-all expression "9 + 7") base-env)))
(is (= 12 ((parse-all expression "19 - 7") base-env)))
Expand Down
8 changes: 8 additions & 0 deletions test/infix/macros_tests.clj
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@
(is (true? (infix 5 != 3)))
(is (true? (infix 5 not= 4))))

(deftest check-comparison
(is (true? (infix 3 < 5)))
(is (false? (infix 3 > 5)))
(is (true? (infix 3 <= 5)))
(is (false? (infix 3 >= 5)))
(is (true? (infix 3 >= 3)))
(is (true? (infix 3 <= 3))))

(deftest check-meta
(let [hypot (from-string [x y] "sqrt(x**2 + y**2)")
no-params (from-string "1 + 2")]
Expand Down

0 comments on commit e36e8aa

Please sign in to comment.