Compare commits

...

9 Commits

9 changed files with 412 additions and 181 deletions
+17 -3
View File
@@ -8,6 +8,20 @@ import (
"fmt" "fmt"
) )
func errTooFewParams(minArgs, maxArgs, argCount int) (err error) {
if maxArgs < 0 {
err = fmt.Errorf("too few params -- expected %d or more, got %d", minArgs, argCount)
} else {
err = fmt.Errorf("too few params -- expected %d, got %d", minArgs, argCount)
}
return
}
func errTooMuchParams(maxArgs, argCount int) (err error) {
err = fmt.Errorf("too much params -- expected %d, got %d", maxArgs, argCount)
return
}
// --- General errors // --- General errors
func errCantConvert(funcName string, value any, kind string) error { func errCantConvert(funcName string, value any, kind string) error {
@@ -24,9 +38,9 @@ func errDivisionByZero(funcName string) error {
// --- Parameter errors // --- Parameter errors
func errOneParam(funcName string) error { // func errOneParam(funcName string) error {
return fmt.Errorf("%s() requires exactly one param", funcName) // return fmt.Errorf("%s() requires exactly one param", funcName)
} // }
func errMissingRequiredParameter(funcName, paramName string) error { func errMissingRequiredParameter(funcName, paramName string) error {
return fmt.Errorf("%s() missing required parameter %q", funcName, paramName) return fmt.Errorf("%s() missing required parameter %q", funcName, paramName)
+137 -62
View File
@@ -22,7 +22,7 @@ Expressions calculator
toc::[] toc::[]
#TODO: Work in progress (last update on 2024/05/10, 06:52 a.m.)# #TODO: Work in progress (last update on 2024/05/16, 7:08 a.m.)#
== Expr == Expr
_Expr_ is a GO package capable of analysing, interpreting and calculating expressions. _Expr_ is a GO package capable of analysing, interpreting and calculating expressions.
@@ -33,9 +33,9 @@ _Expr_ is a GO package capable of analysing, interpreting and calculating expres
image::expression-diagram.png[] image::expression-diagram.png[]
=== `dev-expr` test tool === `dev-expr` test tool
`dev-expr` is a simple program that can be used to evaluate expressions interactively. As its name suggests, it was created for testing purpose. In fact, beyond in additon to the automatic test suite based on the Go test framework, `dev-expr` provides an important aid for quickly testing of new features during their development. `dev-expr` is a simple program that can be used to evaluate expressions interactively. As its name suggests, it was created for testing purpose. In fact, in additon to the automatic verification test suite based on the Go test framework, `dev-expr` provides an important aid for quickly testing of new features during their development.
It cat work as a _REPL_, _**R**ead-**E**xecute-**P**rint-**L**oop_, or it can process expression acquired from files or standard input. `dev-expr` can work as a _REPL_, _**R**ead-**E**xecute-**P**rint-**L**oop_, or it can process expression acquired from files or standard input.
The program can be downloaded from https://git.portale-stac.it/go-pkg/-/packages/generic/dev-expr/[dev-expr]. The program can be downloaded from https://git.portale-stac.it/go-pkg/-/packages/generic/dev-expr/[dev-expr].
@@ -46,19 +46,21 @@ Here are some examples of execution.
---- ----
# Assume the expr source directory. Type 'exit' or Ctrl+D to quit the program. # Assume the expr source directory. Type 'exit' or Ctrl+D to quit the program.
[user]$ tools/expr -- Expressions calculator v1.7.0,2024/05/08 (celestino.amoroso@portale-stac.it) [user]$ ./dev-expr
Type help to get the list of command. expr -- Expressions calculator v1.7.1(build 2),2024/05/16 (celestino.amoroso@portale-stac.it)
Based on the Expr package v0.10.0
Type help to get the list of available commands
See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc
>>> help >>> help
--- REPL commands: --- REPL commands:
source -- Load a file as input
tty -- Enable/Disable ansi output <1>
base -- Set the integer output base: 2, 8, 10, or 16 base -- Set the integer output base: 2, 8, 10, or 16
exit -- Exit the program exit -- Exit the program
help -- Show command list help -- Show command list
ml -- Enable/Disable multi-line output ml -- Enable/Disable multi-line output
mods -- List builtin modules mods -- List builtin modules
source -- Load a file as input
tty -- Enable/Disable ansi output <1>
--- Command line options: --- Command line options:
-b <builtin> Import builtin modules. -b <builtin> Import builtin modules.
@@ -80,9 +82,12 @@ Here are some examples of execution.
.REPL examples .REPL examples
[source,shell] [source,shell]
---- ----
[user]$ tools/expr -- Expressions calculator v1.6.1,2024/05/06 (celestino.amoroso@portale-stac.it) [user]$ ./dev-expr
Type help to get the list of command. expr -- Expressions calculator v1.7.1(build 2),2024/05/16 (celestino.amoroso@portale-stac.it)
See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc Based on the Expr package v0.10.0
Type help to get the list of available commands
See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc
>>> 2+3 >>> 2+3
5 5
>>> 2+3*(4-1.5) >>> 2+3*(4-1.5)
@@ -113,55 +118,116 @@ Here are some examples of execution.
_Expr_ supports numerical, string, relational, boolean expressions, and mixed-type lists. _Expr_ supports numerical, string, relational, boolean expressions, and mixed-type lists.
=== Numbers === Numbers
Numbers can be integers (GO int64) or float (GO float64). In mixed operations involving integers and floats, integers are automatically promoted to floats. _Expr_ supports three type of numbers:
. [blue]#Integers#
. [blue]#Floats#
. [blue]#Factions# internally are stored as _pairs of_ Golang _int64_ values.
In mixed operations involving integers, fractions and floats, automatic type promotion to the largest type take place.
==== Integers
__Expr__'s integers are a subset of the integer set. Internally they are stored as Golang _int64_ values.
.Integer literal syntax
====
*_integer_* = [_sign_] _digit-seq_ +
_sign_ = "**+**" | "**-**" +
_digit-seq_ = _dec-seq_ | _bin-seq_ | _oct-seq_ | _hex-seq_ +
_dec-seq_ = {__dec-digit__} +
_dec-digit_ = "**0**"|"**1**"|...|"**9**" +
_bin-seq_ = "**0b**"{__bin-digit__} +
_bin-digit_ = "**0**"|"**1**" +
_oct-seq_ = "**0o**"{__oct-digit__} +
_oct-digit_ = "**0**"|"**1**"|...|"**7**" +
_hex-seq_ = "**0x**"{__hex-digit__} +
_hex-digit_ = "**0**"|"**1**"|...|"**9**"|"**a**"|...|"**z**"|"**A**"|...|"**Z**"
====
Value range: *-9223372036854775808* to *9223372036854775807*
.Arithmetic operators .Arithmetic operators
[cols="^1,^2,6,4"] [cols="^1,^2,6,4"]
|=== |===
| Symbol | Operation | Description | Examples | Symbol | Operation | Description | Examples
| [blue]`+` | _sum_ | Add two values | [blue]`-1 + 2` -> 1
| [blue]`+` / [blue]`-` | _change sign_ | Change the sign of values | [blue]`-1` _[-1]_ + | [blue]`-` | _subtraction_ | Subtract the right value from the left one | [blue]`3 - 1` -> 2
[blue]`-(+2)` _[-2]_ | [blue]`*` | _product_ | Multiply two values | [blue]`-1 * 2` -> -2
| [blue]`/` | _Division_ | Divide the left value by the right one^(*)^ | [blue]`-10 / 2` -> 5
| [blue]`+` | _sum_ | Add two values | [blue]`-1 + 2` _[1]_ + | [blue]`%` | _Modulo_ | Remainder of the integer division | [blue]`5 % 2` -> 1
[blue]`4 + 0.5` _[4.5]_
| [blue]`-` | _subtraction_ | Subtract the right value from the left one | [blue]`3 - 1` _[2]_ +
[blue]`4 - 0.5` _[3.5]_
| [blue]`*` | _product_ | Multiply two values | `-1 * 2` _[-2]_ +
[blue]`4 * 0.5` _[2.0]_
| [blue]`/` | _Division_ | Divide the left value by the right one | [blue]`-1 / 2` _[0]_ +
[blue]`1.0 / 2` _[0.5]_
| [blue]`./` | _Float division_ | Force float division | [blue]`-1 ./ 2` _[-0.5]_
| [blue]`%` | _Modulo_ | Remainder of the integer division | [blue]`5 % 2` _[1]_
|=== |===
=== Fractions ^(*)^ See also the _float division_ [blue]`./` below.
==== Floats
__Expr__'s floats are a subset of the rational number set. Note that they can't hold the exact value of an unlimited number; floats can only approximate them. Internally floats are stored as Golang's _float64_ values.
.Float literal syntax
====
*_float_* = [_sign_] _dec-seq_ "**.**" [_dec-seq_] [("**e**"|"**E**") [_sign_] _dec-seq_] +
_sign_ = "**+**" | "**-**" +
_dec-seq_ = _see-integer-literal-syntax_
====
.Examples
`>>>` [blue]`1.0` +
[green]`1` +
`>>>` [blue]`0.123` +
[green]`0.123` +
`>>>` [blue]`4.5e+3` +
[green]`4500` +
`>>>` [blue]`4.5E-33` +
[green]`4.5e-33` +
`>>>` [blue]`4.5E-3` +
[green]`0.0045` +
`>>>` [blue]`4.5E10` +
[green]`4.5e+10` +
.Arithmetic operators
[cols="^1,^2,6,4"]
|===
| Symbol | Operation | Description | Examples
| [blue]`+` | _sum_ | Add two values | [blue]`4 + 0.5` -> 4.5
| [blue]`-` | _subtraction_ | Subtract the right value from the left one | [blue]`4 - 0.5` -> 3.5
| [blue]`*` | _product_ | Multiply two values | [blue]`4 * 0.5` -> 2.0
| [blue]`/` | _Division_ | Divide the left value by the right one | [blue]`1.0 / 2` -> 0.5
| [blue]`./`| _Float division_ | Force float division | [blue]`-1 ./ 2` -> -0.5
|===
==== Fractions
_Expr_ also supports fractions. Fraction literals are made with two integers separated by a vertical bar `|`. _Expr_ also supports fractions. Fraction literals are made with two integers separated by a vertical bar `|`.
.Fraction literal syntax
====
*_fraction_* = [__sign__] (_num-den-spec_ | _float-spec_) +
_sign_ = "**+**" | "**-**" +
_num-den-spec_ = _digit-seq_ "**|**" _digit-seq_ +
_float-spec_ = _dec-seq_ "**.**" [_dec-seq_] "**(**" _dec-seq_ "**)**" +
_dec-seq_ = _see-integer-literal-syntax_ +
_digit-seq_ = _see-integer-literal-syntax_ +
====
.Examples .Examples
// [source,go] // [source,go]
// ---- // ----
`>>>` [blue]`1 | 2` + `>>>` [blue]`1 | 2` +
[green]`1|2` + [green]`1|2` +
`>>>` [blue]`4|6` + `>>>` [blue]`4|6` [gray]_// Fractions are always reduced to their lowest terms_ +
[green]`2|3` [gray]_Fractions are always reduced to their lowest terms_ + [green]`2|3` +
`>>>` [blue]`1|2 + 2|3` + `>>>` [blue]`1|2 + 2|3` +
[green]`7|6` + [green]`7|6` +
`>>>` [blue]`1|2 * 2|3` + `>>>` [blue]`1|2 * 2|3` +
[green]`1|3` + [green]`1|3` +
`>>>` [blue]`1|2 / 1|3` + `>>>` [blue]`1|2 / 1|3` +
[green]`3|2` + [green]`3|2` +
`>>>` [blue]`1|2 ./ 1|3` [gray]_Force decimal division_ + `>>>` [blue]`1|2 ./ 1|3` [gray]_// Force decimal division_ +
[green]`1.5` + [green]`1.5` +
`>>>` [blue]`-1|2` + `>>>` [blue]`-1|2` +
[green]`-1|2` + [green]`-1|2` +
`>>>` [blue]`1|-2` [gray]_Wrong sign specification_ + `>>>` [blue]`1|-2` [gray]_// Invalid sign specification_ +
[red]_Eval Error: [1:3] infix operator "|" requires two non-nil operands, got 1_ + [red]_Eval Error: [1:3] infix operator "|" requires two non-nil operands, got 1_ +
`>>>` [blue]`1|(-2)` + `>>>` [blue]`1|(-2)` +
[green]`-1|2` [green]`-1|2`
@@ -179,7 +245,18 @@ Fractions can be used together with integers and floats in expressions.
=== Strings === Strings
Strings are character sequences enclosed between two double quote [blue]`"`. Example: [blue]`"I'm a string"`. Strings are character sequences enclosed between two double quote [blue]`"`.
.Examples
`>>>` [blue]`"I'm a string"` +
[green]`I'm a string` +
`>>>` [blue]`"123abc?!"` +
[green]`123abc?!` +
`>>>` [blue]`"123\nabc"` +
[green]`123` +
[green]`abc` +
`>>>` [blue]`"123\tabc"` +
[green]`123{nbsp}{nbsp}{nbsp}{nbsp}abc`
Some arithmetic operators can also be used with strings. Some arithmetic operators can also be used with strings.
@@ -197,10 +274,9 @@ Some arithmetic operators can also be used with strings.
The items of strings can be accessed using the dot `.` operator. The items of strings can be accessed using the dot `.` operator.
.Item access syntax .Item access syntax
[source,bnf] ====
---- _item_ = _string-expr_ "**.**" _integer-expr_
<item> ::= <string-expr>"."<index-expr> ====
----
.String examples .String examples
`>>>` [blue]`s="abc"` [gray]_assign the string to variable s_ + `>>>` [blue]`s="abc"` [gray]_assign the string to variable s_ +
@@ -215,26 +291,25 @@ The items of strings can be accessed using the dot `.` operator.
[green]`3` + [green]`3` +
=== Boolean === Boolean
Boolean data type has two values only: _true_ and _false_. Relational and Boolean expressions produce Boolean values. Boolean data type has two values only: [blue]_true_ and [blue]_false_. Relational and boolean expressions result in boolean values.
.Relational operators .Relational operators
[cols="^1,^2,6,4"] [cols="^1,^2,6,4"]
|=== |===
| Symbol | Operation | Description | Examples | Symbol | Operation | Description | Examples
| [blue]`==` | _Equal_ | True if the left value is equal to the right one | [blue]`5 == 2` _[false]_ + | [blue]`==` | _Equal_ | True if the left value is equal to the right one | [blue]`5 == 2` -> _false_ +
[blue]`"a" == "a"` _[true]_ [blue]`"a" == "a"` -> _true_
| [blue]`!=` | _Not Equal_ | True if the left value is NOT equal to the right one | [blue]`5 != 2` _[true]_ + | [blue]`!=` | _Not Equal_ | True if the left value is NOT equal to the right one | [blue]`5 != 2` -> _true_ +
[blue]`"a" != "a"` _[false]_ [blue]`"a" != "a"` -> _false_
| [blue]`<` | _Less_ | True if the left value is less than the right one | [blue]`5 < 2` _[false]_ + | [blue]`<` | _Less_ | True if the left value is less than the right one | [blue]`5 < 2` -> _false_ +
[blue]`"a" < "b"` _[true]_ [blue]`"a" < "b"` -> _true_
| [blue]`\<=` | _Less or Equal_ | True if the left value is less than or equal to the right one | [blue]`5 \<= 2` _[false]_ + | [blue]`\<=` | _Less or Equal_ | True if the left value is less than or equal to the right one | [blue]`5 \<= 2` -> _false_ +
[blue]`"b" \<= "b"` _[true]_ [blue]`"b" \<= "b"` -> _true_
| [blue]`>` | _Greater_ | True if the left value is greater than the right one | [blue]`5 > 2` _[true]_ + | [blue]`>` | _Greater_ | True if the left value is greater than the right one | [blue]`5 > 2` -> _true_ +
[blue]`"a" < "b"` _[false]_ [blue]`"a" < "b"` -> _false_
| [blue]`>=` | _Greater or Equal_ | True if the left value is greater than or equal to the right one | [blue]`5 >= 2` _[true]_ + | [blue]`>=` | _Greater or Equal_ | True if the left value is greater than or equal to the right one | [blue]`5 >= 2` -> _true_ +
[blue]`"b" \<= "b"` _[true]_ [blue]`"b" \<= "b"` -> _true_
|=== |===
@@ -243,19 +318,19 @@ Boolean data type has two values only: _true_ and _false_. Relational and Boolea
|=== |===
| Symbol | Operation | Description | Examples | Symbol | Operation | Description | Examples
| [blue]`NOT` | _Not_ | True if the right value is false | [blue]`NOT true` _[false]_ + | [blue]`NOT` | _Not_ | True if the right value is false | [blue]`NOT true` -> _false_ +
[blue]`NOT (2 < 1)` _[true]_ [blue]`NOT (2 < 1)` -> _true_
| [blue]`AND` / [blue]`&&` | _And_ | True if both left and right values are true | [blue]`false && true` _[false]_ + | [blue]`AND` / [blue]`&&` | _And_ | True if both left and right values are true | [blue]`false && true` -> _false_ +
[blue]`"a" < "b" AND NOT (2 < 1)` _[true]_ [blue]`"a" < "b" AND NOT (2 < 1)` -> _true_
| [blue]`OR` / [blue]`\|\|` | _Or_ | True if at least one of the left and right values integers true| [blue]`false or true` _[true]_ + | [blue]`OR` / [blue]`\|\|` | _Or_ | True if at least one of the left and right values integers true| [blue]`false or true` -> _true_ +
[blue]`"a" == "b" OR (2 == 1)` _[false]_ [blue]`"a" == "b" OR (2 == 1)` -> _false_
|=== |===
[CAUTION] [CAUTION]
==== ====
Currently, boolean operations are evaluated using _short cut evaluation_. This means that, if the left expression of operators [blue]`and` and [blue]`or` is sufficient to establish the result of the whole operation, the right expression would not evaluated at all. Currently, boolean operations are evaluated using _short cut evaluation_. This means that, if the left expression of the [blue]`and` and [blue]`or` operators is sufficient to establish the result of the whole operation, the right expression would not evaluated at all.
.Example .Example
[source,go] [source,go]
+226 -84
View File
@@ -541,11 +541,16 @@ pre.rouge .ss {
</li> </li>
<li><a href="#_data_types">2. Data types</a> <li><a href="#_data_types">2. Data types</a>
<ul class="sectlevel2"> <ul class="sectlevel2">
<li><a href="#_numbers">2.1. Numbers</a></li> <li><a href="#_numbers">2.1. Numbers</a>
<li><a href="#_fractions">2.2. Fractions</a></li> <ul class="sectlevel3">
<li><a href="#_strings">2.3. Strings</a></li> <li><a href="#_integers">2.1.1. Integers</a></li>
<li><a href="#_boolean">2.4. Boolean</a></li> <li><a href="#_floats">2.1.2. Floats</a></li>
<li><a href="#_lists">2.5. Lists</a></li> <li><a href="#_fractions">2.1.3. Fractions</a></li>
</ul>
</li>
<li><a href="#_strings">2.2. Strings</a></li>
<li><a href="#_boolean">2.3. Boolean</a></li>
<li><a href="#_lists">2.4. Lists</a></li>
</ul> </ul>
</li> </li>
<li><a href="#_dictionaries">3. Dictionaries</a></li> <li><a href="#_dictionaries">3. Dictionaries</a></li>
@@ -579,7 +584,7 @@ pre.rouge .ss {
<div class="sectionbody"> <div class="sectionbody">
<!-- toc disabled --> <!-- toc disabled -->
<div class="paragraph"> <div class="paragraph">
<p><mark>TODO: Work in progress (last update on 2024/05/10, 06:52 a.m.)</mark></p> <p><mark>TODO: Work in progress (last update on 2024/05/16, 7:08 a.m.)</mark></p>
</div> </div>
</div> </div>
</div> </div>
@@ -603,10 +608,10 @@ pre.rouge .ss {
<div class="sect2"> <div class="sect2">
<h3 id="_dev_expr_test_tool"><a class="anchor" href="#_dev_expr_test_tool"></a><a class="link" href="#_dev_expr_test_tool">1.2. <code>dev-expr</code> test tool</a></h3> <h3 id="_dev_expr_test_tool"><a class="anchor" href="#_dev_expr_test_tool"></a><a class="link" href="#_dev_expr_test_tool">1.2. <code>dev-expr</code> test tool</a></h3>
<div class="paragraph"> <div class="paragraph">
<p><code>dev-expr</code> is a simple program that can be used to evaluate expressions interactively. As its name suggests, it was created for testing purpose. In fact, beyond in additon to the automatic test suite based on the Go test framework, <code>dev-expr</code> provides an important aid for quickly testing of new features during their development.</p> <p><code>dev-expr</code> is a simple program that can be used to evaluate expressions interactively. As its name suggests, it was created for testing purpose. In fact, in additon to the automatic verification test suite based on the Go test framework, <code>dev-expr</code> provides an important aid for quickly testing of new features during their development.</p>
</div> </div>
<div class="paragraph"> <div class="paragraph">
<p>It cat work as a <em>REPL</em>, <em><strong>R</strong>ead-<strong>E</strong>xecute-<strong>P</strong>rint-<strong>L</strong>oop</em>, or it can process expression acquired from files or standard input.</p> <p><code>dev-expr</code> can work as a <em>REPL</em>, <em><strong>R</strong>ead-<strong>E</strong>xecute-<strong>P</strong>rint-<strong>L</strong>oop</em>, or it can process expression acquired from files or standard input.</p>
</div> </div>
<div class="paragraph"> <div class="paragraph">
<p>The program can be downloaded from <a href="https://git.portale-stac.it/go-pkg/-/packages/generic/dev-expr/">dev-expr</a>.</p> <p>The program can be downloaded from <a href="https://git.portale-stac.it/go-pkg/-/packages/generic/dev-expr/">dev-expr</a>.</p>
@@ -619,19 +624,21 @@ pre.rouge .ss {
<div class="content"> <div class="content">
<pre class="rouge highlight"><code data-lang="shell"><span class="c"># Assume the expr source directory. Type 'exit' or Ctrl+D to quit the program.</span> <pre class="rouge highlight"><code data-lang="shell"><span class="c"># Assume the expr source directory. Type 'exit' or Ctrl+D to quit the program.</span>
<span class="o">[</span>user]<span class="nv">$ </span>tools/expr <span class="nt">--</span> Expressions calculator v1.7.0,2024/05/08 <span class="o">(</span>celestino.amoroso@portale-stac.it<span class="o">)</span> <span class="o">[</span>user]<span class="nv">$ </span>./dev-expr
Type <span class="nb">help </span>to get the list of command. <span class="nb">expr</span> <span class="nt">--</span> Expressions calculator v1.7.1<span class="o">(</span>build 2<span class="o">)</span>,2024/05/16 <span class="o">(</span>celestino.amoroso@portale-stac.it<span class="o">)</span>
Based on the Expr package v0.10.0
Type <span class="nb">help </span>to get the list of available commands
See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc
<span class="o">&gt;&gt;&gt;</span> <span class="nb">help</span> <span class="o">&gt;&gt;&gt;</span> <span class="nb">help</span>
<span class="nt">---</span> REPL commands: <span class="nt">---</span> REPL commands:
<span class="nb">source</span> <span class="nt">--</span> Load a file as input
<span class="nb">tty</span> <span class="nt">--</span> Enable/Disable ansi output <i class="conum" data-value="1"></i><b>(1)</b>
base <span class="nt">--</span> Set the integer output base: 2, 8, 10, or 16 base <span class="nt">--</span> Set the integer output base: 2, 8, 10, or 16
<span class="nb">exit</span> <span class="nt">--</span> Exit the program <span class="nb">exit</span> <span class="nt">--</span> Exit the program
<span class="nb">help</span> <span class="nt">--</span> Show <span class="nb">command </span>list <span class="nb">help</span> <span class="nt">--</span> Show <span class="nb">command </span>list
ml <span class="nt">--</span> Enable/Disable multi-line output ml <span class="nt">--</span> Enable/Disable multi-line output
mods <span class="nt">--</span> List <span class="nb">builtin </span>modules mods <span class="nt">--</span> List <span class="nb">builtin </span>modules
<span class="nb">source</span> <span class="nt">--</span> Load a file as input
<span class="nb">tty</span> <span class="nt">--</span> Enable/Disable ansi output <i class="conum" data-value="1"></i><b>(1)</b>
<span class="nt">---</span> Command line options: <span class="nt">---</span> Command line options:
<span class="nt">-b</span> &lt;<span class="nb">builtin</span><span class="o">&gt;</span> Import <span class="nb">builtin </span>modules. <span class="nt">-b</span> &lt;<span class="nb">builtin</span><span class="o">&gt;</span> Import <span class="nb">builtin </span>modules.
@@ -662,9 +669,12 @@ pre.rouge .ss {
<div class="listingblock"> <div class="listingblock">
<div class="title">REPL examples</div> <div class="title">REPL examples</div>
<div class="content"> <div class="content">
<pre class="rouge highlight"><code data-lang="shell"><span class="o">[</span>user]<span class="nv">$ </span>tools/expr <span class="nt">--</span> Expressions calculator v1.6.1,2024/05/06 <span class="o">(</span>celestino.amoroso@portale-stac.it<span class="o">)</span> <pre class="rouge highlight"><code data-lang="shell"><span class="o">[</span>user]<span class="nv">$ </span>./dev-expr
Type <span class="nb">help </span>to get the list of command. <span class="nb">expr</span> <span class="nt">--</span> Expressions calculator v1.7.1<span class="o">(</span>build 2<span class="o">)</span>,2024/05/16 <span class="o">(</span>celestino.amoroso@portale-stac.it<span class="o">)</span>
See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc Based on the Expr package v0.10.0
Type <span class="nb">help </span>to get the list of available commands
See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc
<span class="o">&gt;&gt;&gt;</span> 2+3 <span class="o">&gt;&gt;&gt;</span> 2+3
5 5
<span class="o">&gt;&gt;&gt;</span> 2+3<span class="k">*</span><span class="o">(</span>4-1.5<span class="o">)</span> <span class="o">&gt;&gt;&gt;</span> 2+3<span class="k">*</span><span class="o">(</span>4-1.5<span class="o">)</span>
@@ -721,7 +731,49 @@ pre.rouge .ss {
<div class="sect2"> <div class="sect2">
<h3 id="_numbers"><a class="anchor" href="#_numbers"></a><a class="link" href="#_numbers">2.1. Numbers</a></h3> <h3 id="_numbers"><a class="anchor" href="#_numbers"></a><a class="link" href="#_numbers">2.1. Numbers</a></h3>
<div class="paragraph"> <div class="paragraph">
<p>Numbers can be integers (GO int64) or float (GO float64). In mixed operations involving integers and floats, integers are automatically promoted to floats.</p> <p><em>Expr</em> supports three type of numbers:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p><span class="blue">Integers</span></p>
</li>
<li>
<p><span class="blue">Floats</span></p>
</li>
<li>
<p><span class="blue">Factions</span> internally are stored as <em>pairs of</em> Golang <em>int64</em> values.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>In mixed operations involving integers, fractions and floats, automatic type promotion to the largest type take place.</p>
</div>
<div class="sect3">
<h4 id="_integers"><a class="anchor" href="#_integers"></a><a class="link" href="#_integers">2.1.1. Integers</a></h4>
<div class="paragraph">
<p><em>Expr</em>'s integers are a subset of the integer set. Internally they are stored as Golang <em>int64</em> values.</p>
</div>
<div class="exampleblock">
<div class="title">Example 1. Integer literal syntax</div>
<div class="content">
<div class="paragraph">
<p><strong><em>integer</em></strong> = [<em>sign</em>] <em>digit-seq</em><br>
<em>sign</em> = "<strong>+</strong>" | "<strong>-</strong>"<br>
<em>digit-seq</em> = <em>dec-seq</em> | <em>bin-seq</em> | <em>oct-seq</em> | <em>hex-seq</em><br>
<em>dec-seq</em> = {<em>dec-digit</em>}<br>
<em>dec-digit</em> = "<strong>0</strong>"|"<strong>1</strong>"|&#8230;&#8203;|"<strong>9</strong>"<br>
<em>bin-seq</em> = "<strong>0b</strong>"{<em>bin-digit</em>}<br>
<em>bin-digit</em> = "<strong>0</strong>"|"<strong>1</strong>"<br>
<em>oct-seq</em> = "<strong>0o</strong>"{<em>oct-digit</em>}<br>
<em>oct-digit</em> = "<strong>0</strong>"|"<strong>1</strong>"|&#8230;&#8203;|"<strong>7</strong>"<br>
<em>hex-seq</em> = "<strong>0x</strong>"{<em>hex-digit</em>}<br>
<em>hex-digit</em> = "<strong>0</strong>"|"<strong>1</strong>"|&#8230;&#8203;|"<strong>9</strong>"|"<strong>a</strong>"|&#8230;&#8203;|"<strong>z</strong>"|"<strong>A</strong>"|&#8230;&#8203;|"<strong>Z</strong>"</p>
</div>
</div>
</div>
<div class="paragraph">
<p>Value range: <strong>-9223372036854775808</strong> to <strong>9223372036854775807</strong></p>
</div> </div>
<table class="tableblock frame-all grid-all stretch"> <table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 1. Arithmetic operators</caption> <caption class="title">Table 1. Arithmetic operators</caption>
@@ -731,87 +783,162 @@ pre.rouge .ss {
<col style="width: 46.1538%;"> <col style="width: 46.1538%;">
<col style="width: 30.7693%;"> <col style="width: 30.7693%;">
</colgroup> </colgroup>
<thead>
<tr>
<th class="tableblock halign-center valign-top">Symbol</th>
<th class="tableblock halign-center valign-top">Operation</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Examples</th>
</tr>
</thead>
<tbody> <tbody>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">+</code> / <code class="blue">-</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock">Symbol</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>change sign</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock">Operation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Change the sign of values</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Description</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">-1</code> <em>[-1]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock">Examples</p></td>
<code class="blue">-(+2)</code> <em>[-2]</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">+</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">+</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>sum</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>sum</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Add two values</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Add two values</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">-1 + 2</code> <em>[1]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">-1 + 2</code> &#8594; 1</p></td>
<code class="blue">4 + 0.5</code> <em>[4.5]</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">-</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">-</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>subtraction</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>subtraction</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Subtract the right value from the left one</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Subtract the right value from the left one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">3 - 1</code> <em>[2]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">3 - 1</code> &#8594; 2</p></td>
<code class="blue">4 - 0.5</code> <em>[3.5]</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">*</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">*</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>product</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>product</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Multiply two values</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Multiply two values</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code>-1 * 2</code> <em>[-2]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">-1 * 2</code> &#8594; -2</p></td>
<code class="blue">4 * 0.5</code> <em>[2.0]</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">/</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">/</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Division</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Division</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Divide the left value by the right one</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Divide the left value by the right one<sup>(*)</sup></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">-1 / 2</code> <em>[0]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">-10 / 2</code> &#8594; 5</p></td>
<code class="blue">1.0 / 2</code> <em>[0.5]</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">./</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Float division</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Force float division</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">-1 ./ 2</code> <em>[-0.5]</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">%</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">%</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Modulo</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Modulo</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Remainder of the integer division</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Remainder of the integer division</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 % 2</code> <em>[1]</em></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 % 2</code> &#8594; 1</p></td>
</tr>
</tbody>
</table>
<div class="paragraph">
<p><sup>(*)</sup> See also the <em>float division</em> <code class="blue">./</code> below.</p>
</div>
</div>
<div class="sect3">
<h4 id="_floats"><a class="anchor" href="#_floats"></a><a class="link" href="#_floats">2.1.2. Floats</a></h4>
<div class="paragraph">
<p><em>Expr</em>'s floats are a subset of the rational number set. Note that they can&#8217;t hold the exact value of an unlimited number; floats can only approximate them. Internally floats are stored as Golang&#8217;s <em>float64</em> values.</p>
</div>
<div class="exampleblock">
<div class="title">Example 2. Float literal syntax</div>
<div class="content">
<div class="paragraph">
<p><strong><em>float</em></strong> = [<em>sign</em>] <em>dec-seq</em> "<strong>.</strong>" [<em>dec-seq</em>] [("<strong>e</strong>"|"<strong>E</strong>") [<em>sign</em>] <em>dec-seq</em>]<br>
<em>sign</em> = "<strong>+</strong>" | "<strong>-</strong>"<br>
<em>dec-seq</em> = <em>see-integer-literal-syntax</em></p>
</div>
</div>
</div>
<div class="paragraph">
<div class="title">Examples</div>
<p><code>&gt;&gt;&gt;</code> <code class="blue">1.0</code><br>
<code class="green">1</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">0.123</code><br>
<code class="green">0.123</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">4.5e+3</code><br>
<code class="green">4500</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">4.5E-33</code><br>
<code class="green">4.5e-33</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">4.5E-3</code><br>
<code class="green">0.0045</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">4.5E10</code><br>
<code class="green">4.5e+10</code><br></p>
</div>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 2. Arithmetic operators</caption>
<colgroup>
<col style="width: 7.6923%;">
<col style="width: 15.3846%;">
<col style="width: 46.1538%;">
<col style="width: 30.7693%;">
</colgroup>
<tbody>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock">Symbol</p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock">Operation</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Description</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Examples</p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">+</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>sum</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Add two values</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">4 + 0.5</code> &#8594; 4.5</p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">-</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>subtraction</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Subtract the right value from the left one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">4 - 0.5</code> &#8594; 3.5</p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">*</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>product</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Multiply two values</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">4 * 0.5</code> &#8594; 2.0</p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">/</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Division</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Divide the left value by the right one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">1.0 / 2</code> &#8594; 0.5</p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">./</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Float division</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Force float division</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">-1 ./ 2</code> &#8594; -0.5</p></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="sect2"> <div class="sect3">
<h3 id="_fractions"><a class="anchor" href="#_fractions"></a><a class="link" href="#_fractions">2.2. Fractions</a></h3> <h4 id="_fractions"><a class="anchor" href="#_fractions"></a><a class="link" href="#_fractions">2.1.3. Fractions</a></h4>
<div class="paragraph"> <div class="paragraph">
<p><em>Expr</em> also supports fractions. Fraction literals are made with two integers separated by a vertical bar <code>|</code>.</p> <p><em>Expr</em> also supports fractions. Fraction literals are made with two integers separated by a vertical bar <code>|</code>.</p>
</div> </div>
<div class="exampleblock">
<div class="title">Example 3. Fraction literal syntax</div>
<div class="content">
<div class="paragraph">
<p><strong><em>fraction</em></strong> = [<em>sign</em>] (<em>num-den-spec</em> | <em>float-spec</em>)<br>
<em>sign</em> = "<strong>+</strong>" | "<strong>-</strong>"<br>
<em>num-den-spec</em> = <em>digit-seq</em> "<strong>|</strong>" <em>digit-seq</em><br>
<em>float-spec</em> = <em>dec-seq</em> "<strong>.</strong>" [<em>dec-seq</em>] "<strong>(</strong>" <em>dec-seq</em> "<strong>)</strong>"<br>
<em>dec-seq</em> = <em>see-integer-literal-syntax</em><br>
<em>digit-seq</em> = <em>see-integer-literal-syntax</em><br></p>
</div>
</div>
</div>
<div class="paragraph"> <div class="paragraph">
<div class="title">Examples</div> <div class="title">Examples</div>
<p><code>&gt;&gt;&gt;</code> <code class="blue">1 | 2</code><br> <p><code>&gt;&gt;&gt;</code> <code class="blue">1 | 2</code><br>
<code class="green">1|2</code><br> <code class="green">1|2</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">4|6</code><br> <code>&gt;&gt;&gt;</code> <code class="blue">4|6</code> <em class="gray">// Fractions are always reduced to their lowest terms</em><br>
<code class="green">2|3</code> <em class="gray">Fractions are always reduced to their lowest terms</em><br> <code class="green">2|3</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">1|2 + 2|3</code><br> <code>&gt;&gt;&gt;</code> <code class="blue">1|2 + 2|3</code><br>
<code class="green">7|6</code><br> <code class="green">7|6</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">1|2 * 2|3</code><br> <code>&gt;&gt;&gt;</code> <code class="blue">1|2 * 2|3</code><br>
<code class="green">1|3</code><br> <code class="green">1|3</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">1|2 / 1|3</code><br> <code>&gt;&gt;&gt;</code> <code class="blue">1|2 / 1|3</code><br>
<code class="green">3|2</code><br> <code class="green">3|2</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">1|2 ./ 1|3</code> <em class="gray">Force decimal division</em><br> <code>&gt;&gt;&gt;</code> <code class="blue">1|2 ./ 1|3</code> <em class="gray">// Force decimal division</em><br>
<code class="green">1.5</code><br> <code class="green">1.5</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">-1|2</code><br> <code>&gt;&gt;&gt;</code> <code class="blue">-1|2</code><br>
<code class="green">-1|2</code><br> <code class="green">-1|2</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">1|-2</code> <em class="gray">Wrong sign specification</em><br> <code>&gt;&gt;&gt;</code> <code class="blue">1|-2</code> <em class="gray">// Invalid sign specification</em><br>
<em class="red">Eval Error: [1:3] infix operator "|" requires two non-nil operands, got 1</em><br> <em class="red">Eval Error: [1:3] infix operator "|" requires two non-nil operands, got 1</em><br>
<code>&gt;&gt;&gt;</code> <code class="blue">1|(-2)</code><br> <code>&gt;&gt;&gt;</code> <code class="blue">1|(-2)</code><br>
<code class="green">-1|2</code></p> <code class="green">-1|2</code></p>
@@ -828,16 +955,29 @@ pre.rouge .ss {
<code class="green">1.5</code><br></p> <code class="green">1.5</code><br></p>
</div> </div>
</div> </div>
</div>
<div class="sect2"> <div class="sect2">
<h3 id="_strings"><a class="anchor" href="#_strings"></a><a class="link" href="#_strings">2.3. Strings</a></h3> <h3 id="_strings"><a class="anchor" href="#_strings"></a><a class="link" href="#_strings">2.2. Strings</a></h3>
<div class="paragraph"> <div class="paragraph">
<p>Strings are character sequences enclosed between two double quote <code class="blue">"</code>. Example: <code class="blue">"I&#8217;m a string"</code>.</p> <p>Strings are character sequences enclosed between two double quote <code class="blue">"</code>.</p>
</div>
<div class="paragraph">
<div class="title">Examples</div>
<p><code>&gt;&gt;&gt;</code> <code class="blue">"I&#8217;m a string"</code><br>
<code class="green">I&#8217;m a string</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">"123abc?!"</code><br>
<code class="green">123abc?!</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">"123\nabc"</code><br>
<code class="green">123</code><br>
<code class="green">abc</code><br>
<code>&gt;&gt;&gt;</code> <code class="blue">"123\tabc"</code><br>
<code class="green">123&#160;&#160;&#160;&#160;abc</code></p>
</div> </div>
<div class="paragraph"> <div class="paragraph">
<p>Some arithmetic operators can also be used with strings.</p> <p>Some arithmetic operators can also be used with strings.</p>
</div> </div>
<table class="tableblock frame-all grid-all stretch"> <table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 2. String operators</caption> <caption class="title">Table 3. String operators</caption>
<colgroup> <colgroup>
<col style="width: 7.6923%;"> <col style="width: 7.6923%;">
<col style="width: 15.3846%;"> <col style="width: 15.3846%;">
@@ -871,10 +1011,12 @@ pre.rouge .ss {
<div class="paragraph"> <div class="paragraph">
<p>The items of strings can be accessed using the dot <code>.</code> operator.</p> <p>The items of strings can be accessed using the dot <code>.</code> operator.</p>
</div> </div>
<div class="listingblock"> <div class="exampleblock">
<div class="title">Item access syntax</div> <div class="title">Example 4. Item access syntax</div>
<div class="content"> <div class="content">
<pre class="rouge highlight"><code data-lang="bnf">&lt;item&gt; ::= &lt;string-expr&gt;"."&lt;index-expr&gt;</code></pre> <div class="paragraph">
<p><em>item</em> = <em>string-expr</em> "<strong>.</strong>" <em>integer-expr</em></p>
</div>
</div> </div>
</div> </div>
<div class="paragraph"> <div class="paragraph">
@@ -892,12 +1034,12 @@ pre.rouge .ss {
</div> </div>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_boolean"><a class="anchor" href="#_boolean"></a><a class="link" href="#_boolean">2.4. Boolean</a></h3> <h3 id="_boolean"><a class="anchor" href="#_boolean"></a><a class="link" href="#_boolean">2.3. Boolean</a></h3>
<div class="paragraph"> <div class="paragraph">
<p>Boolean data type has two values only: <em>true</em> and <em>false</em>. Relational and Boolean expressions produce Boolean values.</p> <p>Boolean data type has two values only: <em class="blue">true</em> and <em class="blue">false</em>. Relational and boolean expressions result in boolean values.</p>
</div> </div>
<table class="tableblock frame-all grid-all stretch"> <table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 3. Relational operators</caption> <caption class="title">Table 4. Relational operators</caption>
<colgroup> <colgroup>
<col style="width: 7.6923%;"> <col style="width: 7.6923%;">
<col style="width: 15.3846%;"> <col style="width: 15.3846%;">
@@ -917,48 +1059,48 @@ pre.rouge .ss {
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">==</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">==</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Equal</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Equal</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is equal to the right one</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is equal to the right one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 == 2</code> <em>[false]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 == 2</code> &#8594; <em>false</em><br>
<code class="blue">"a" == "a"</code> <em>[true]</em></p></td> <code class="blue">"a" == "a"</code> &#8594; <em>true</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">!=</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">!=</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Not Equal</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Not Equal</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is NOT equal to the right one</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is NOT equal to the right one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 != 2</code> <em>[true]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 != 2</code> &#8594; <em>true</em><br>
<code class="blue">"a" != "a"</code> <em>[false]</em></p></td> <code class="blue">"a" != "a"</code> &#8594; <em>false</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&lt;</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&lt;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Less</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Less</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is less than the right one</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is less than the right one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 &lt; 2</code> <em>[false]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 &lt; 2</code> &#8594; <em>false</em><br>
<code class="blue">"a" &lt; "b"</code> <em>[true]</em></p></td> <code class="blue">"a" &lt; "b"</code> &#8594; <em>true</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&lt;=</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&lt;=</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Less or Equal</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Less or Equal</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is less than or equal to the right one</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is less than or equal to the right one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 &lt;= 2</code> <em>[false]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 &lt;= 2</code> &#8594; <em>false</em><br>
<code class="blue">"b" &lt;= "b"</code> <em>[true]</em></p></td> <code class="blue">"b" &lt;= "b"</code> &#8594; <em>true</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&gt;</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&gt;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Greater</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Greater</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is greater than the right one</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is greater than the right one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 &gt; 2</code> <em>[true]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 &gt; 2</code> &#8594; <em>true</em><br>
<code class="blue">"a" &lt; "b"</code> <em>[false]</em></p></td> <code class="blue">"a" &lt; "b"</code> &#8594; <em>false</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&gt;=</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&gt;=</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Greater or Equal</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Greater or Equal</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is greater than or equal to the right one</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if the left value is greater than or equal to the right one</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 &gt;= 2</code> <em>[true]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">5 &gt;= 2</code> &#8594; <em>true</em><br>
<code class="blue">"b" &lt;= "b"</code> <em>[true]</em></p></td> <code class="blue">"b" &lt;= "b"</code> &#8594; <em>true</em></p></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<table class="tableblock frame-all grid-all stretch"> <table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 4. Boolean operators</caption> <caption class="title">Table 5. Boolean operators</caption>
<colgroup> <colgroup>
<col style="width: 15.3846%;"> <col style="width: 15.3846%;">
<col style="width: 15.3846%;"> <col style="width: 15.3846%;">
@@ -978,22 +1120,22 @@ pre.rouge .ss {
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">NOT</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">NOT</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Not</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Not</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if the right value is false</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if the right value is false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">NOT true</code> <em>[false]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">NOT true</code> &#8594; <em>false</em><br>
<code class="blue">NOT (2 &lt; 1)</code> <em>[true]</em></p></td> <code class="blue">NOT (2 &lt; 1)</code> &#8594; <em>true</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">AND</code> / <code class="blue">&amp;&amp;</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">AND</code> / <code class="blue">&amp;&amp;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>And</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>And</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if both left and right values are true</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if both left and right values are true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">false &amp;&amp; true</code> <em>[false]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">false &amp;&amp; true</code> &#8594; <em>false</em><br>
<code class="blue">"a" &lt; "b" AND NOT (2 &lt; 1)</code> <em>[true]</em></p></td> <code class="blue">"a" &lt; "b" AND NOT (2 &lt; 1)</code> &#8594; <em>true</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">OR</code> / <code class="blue">||</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">OR</code> / <code class="blue">||</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Or</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Or</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">True if at least one of the left and right values integers true</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">True if at least one of the left and right values integers true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">false or true</code> <em>[true]</em><br> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">false or true</code> &#8594; <em>true</em><br>
<code class="blue">"a" == "b" OR (2 == 1)</code> <em>[false]</em></p></td> <code class="blue">"a" == "b" OR (2 == 1)</code> &#8594; <em>false</em></p></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -1005,7 +1147,7 @@ pre.rouge .ss {
</td> </td>
<td class="content"> <td class="content">
<div class="paragraph"> <div class="paragraph">
<p>Currently, boolean operations are evaluated using <em>short cut evaluation</em>. This means that, if the left expression of operators <code class="blue">and</code> and <code class="blue">or</code> is sufficient to establish the result of the whole operation, the right expression would not evaluated at all.</p> <p>Currently, boolean operations are evaluated using <em>short cut evaluation</em>. This means that, if the left expression of the <code class="blue">and</code> and <code class="blue">or</code> operators is sufficient to establish the result of the whole operation, the right expression would not evaluated at all.</p>
</div> </div>
<div class="listingblock"> <div class="listingblock">
<div class="title">Example</div> <div class="title">Example</div>
@@ -1027,7 +1169,7 @@ pre.rouge .ss {
</div> </div>
</div> </div>
<div class="sect2"> <div class="sect2">
<h3 id="_lists"><a class="anchor" href="#_lists"></a><a class="link" href="#_lists">2.5. Lists</a></h3> <h3 id="_lists"><a class="anchor" href="#_lists"></a><a class="link" href="#_lists">2.4. Lists</a></h3>
<div class="paragraph"> <div class="paragraph">
<p><em>Expr</em> supports list of mixed-type values, also specified by normal expressions.</p> <p><em>Expr</em> supports list of mixed-type values, also specified by normal expressions.</p>
</div> </div>
@@ -1042,7 +1184,7 @@ pre.rouge .ss {
</div> </div>
</div> </div>
<table class="tableblock frame-all grid-all stretch"> <table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 5. List operators</caption> <caption class="title">Table 6. List operators</caption>
<colgroup> <colgroup>
<col style="width: 15.3846%;"> <col style="width: 15.3846%;">
<col style="width: 15.3846%;"> <col style="width: 15.3846%;">
@@ -1261,7 +1403,7 @@ The value on the left side of <code class="blue">=</code> must be an identifier.
<p>The table below shows all supported operators by decreasing priorities.</p> <p>The table below shows all supported operators by decreasing priorities.</p>
</div> </div>
<table class="tableblock frame-all grid-all stretch"> <table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 6. Operators priorities</caption> <caption class="title">Table 7. Operators priorities</caption>
<colgroup> <colgroup>
<col style="width: 12.5%;"> <col style="width: 12.5%;">
<col style="width: 12.5%;"> <col style="width: 12.5%;">
@@ -1519,7 +1661,7 @@ The value on the left side of <code class="blue">=</code> must be an identifier.
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2024-05-11 20:13:17 +0200 Last updated 2024-05-16 07:10:03 +0200
</div> </div>
</div> </div>
</body> </body>
+1 -5
View File
@@ -10,11 +10,7 @@ import (
) )
func isNilFunc(ctx ExprContext, name string, args []any) (result any, err error) { func isNilFunc(ctx ExprContext, name string, args []any) (result any, err error) {
if len(args) == 1 { result = args[0] == nil
result = args[0] == nil
} else {
err = errOneParam(name)
}
return return
} }
+18 -18
View File
@@ -33,9 +33,9 @@ func doJoinStr(funcName string, sep string, it Iterator) (result any, err error)
} }
func joinStrFunc(ctx ExprContext, name string, args []any) (result any, err error) { func joinStrFunc(ctx ExprContext, name string, args []any) (result any, err error) {
if len(args) < 1 { // if len(args) < 1 {
return nil, errMissingRequiredParameter(name, paramSeparator) // return nil, errMissingRequiredParameter(name, paramSeparator)
} // }
if sep, ok := args[0].(string); ok { if sep, ok := args[0].(string); ok {
if len(args) == 1 { if len(args) == 1 {
result = "" result = ""
@@ -62,9 +62,9 @@ func subStrFunc(ctx ExprContext, name string, args []any) (result any, err error
var source string var source string
var ok bool var ok bool
if len(args) < 1 { // if len(args) < 1 {
return nil, errMissingRequiredParameter(name, paramSource) // return nil, errMissingRequiredParameter(name, paramSource)
} // }
if source, ok = args[0].(string); !ok { if source, ok = args[0].(string); !ok {
return nil, errWrongParamType(name, paramSource, typeString, args[0]) return nil, errWrongParamType(name, paramSource, typeString, args[0])
} }
@@ -93,9 +93,9 @@ func trimStrFunc(ctx ExprContext, name string, args []any) (result any, err erro
var source string var source string
var ok bool var ok bool
if len(args) < 1 { // if len(args) < 1 {
return nil, errMissingRequiredParameter(name, paramSource) // return nil, errMissingRequiredParameter(name, paramSource)
} // }
if source, ok = args[0].(string); !ok { if source, ok = args[0].(string); !ok {
return nil, errWrongParamType(name, paramSource, typeString, args[0]) return nil, errWrongParamType(name, paramSource, typeString, args[0])
} }
@@ -108,9 +108,9 @@ func startsWithStrFunc(ctx ExprContext, name string, args []any) (result any, er
var ok bool var ok bool
result = false result = false
if len(args) < 1 { // if len(args) < 1 {
return result, errMissingRequiredParameter(name, paramSource) // return result, errMissingRequiredParameter(name, paramSource)
} // }
if source, ok = args[0].(string); !ok { if source, ok = args[0].(string); !ok {
return result, errWrongParamType(name, paramSource, typeString, args[0]) return result, errWrongParamType(name, paramSource, typeString, args[0])
} }
@@ -133,9 +133,9 @@ func endsWithStrFunc(ctx ExprContext, name string, args []any) (result any, err
var ok bool var ok bool
result = false result = false
if len(args) < 1 { // if len(args) < 1 {
return result, errMissingRequiredParameter(name, paramSource) // return result, errMissingRequiredParameter(name, paramSource)
} // }
if source, ok = args[0].(string); !ok { if source, ok = args[0].(string); !ok {
return result, errWrongParamType(name, paramSource, typeString, args[0]) return result, errWrongParamType(name, paramSource, typeString, args[0])
} }
@@ -159,9 +159,9 @@ func splitStrFunc(ctx ExprContext, name string, args []any) (result any, err err
var parts []string var parts []string
var ok bool var ok bool
if len(args) < 1 { // if len(args) < 1 {
return result, errMissingRequiredParameter(name, paramSource) // return result, errMissingRequiredParameter(name, paramSource)
} // }
if source, ok = args[0].(string); !ok { if source, ok = args[0].(string); !ok {
return result, errWrongParamType(name, paramSource, typeString, args[0]) return result, errWrongParamType(name, paramSource, typeString, args[0])
} }
+3
View File
@@ -76,6 +76,9 @@ func TestFuncs(t *testing.T) {
/* 63 */ {`dec(true)`, float64(1), nil}, /* 63 */ {`dec(true)`, float64(1), nil},
/* 64 */ {`dec(true")`, nil, errors.New("[1:11] missing string termination \"")}, /* 64 */ {`dec(true")`, nil, errors.New("[1:11] missing string termination \"")},
/* 65 */ {`builtin "string"; joinStr("-", [1, "two", "three"])`, nil, errors.New(`joinStr() expected string, got int64 (1)`)}, /* 65 */ {`builtin "string"; joinStr("-", [1, "two", "three"])`, nil, errors.New(`joinStr() expected string, got int64 (1)`)},
/* 65 */ {`dec()`, nil, errors.New(`too few params -- expected 1, got 0`)},
/* 66 */ {`dec(1,2,3)`, nil, errors.New(`too much params -- expected 1, got 3`)},
/* 67 */ {`builtin "string"; joinStr()`, nil, errors.New(`too few params -- expected 1 or more, got 0`)},
// /* 64 */ {`string(true)`, "true", nil}, // /* 64 */ {`string(true)`, "true", nil},
} }
+2 -6
View File
@@ -25,14 +25,10 @@ func newFuncCallTerm(tk *Token, args []*term) *term {
func checkFunctionCall(ctx ExprContext, name string, params []any) (err error) { func checkFunctionCall(ctx ExprContext, name string, params []any) (err error) {
if info, exists, owner := GetFuncInfo(ctx, name); exists { if info, exists, owner := GetFuncInfo(ctx, name); exists {
if info.MinArgs() > len(params) { if info.MinArgs() > len(params) {
if info.MaxArgs() < 0 { err = errTooFewParams(info.MinArgs(), info.MaxArgs(), len(params))
err = fmt.Errorf("too few params -- expected %d or more, got %d", info.MinArgs(), len(params))
} else {
err = fmt.Errorf("too few params -- expected %d, got %d", info.MinArgs(), len(params))
}
} }
if err == nil && info.MaxArgs() >= 0 && info.MaxArgs() < len(params) { if err == nil && info.MaxArgs() >= 0 && info.MaxArgs() < len(params) {
err = fmt.Errorf("too much params -- expected %d, got %d", info.MaxArgs(), len(params)) err = errTooMuchParams(info.MaxArgs(), len(params))
} }
if err == nil && owner != ctx { if err == nil && owner != ctx {
ctx.RegisterFunc(name, info.Functor(), info.MinArgs(), info.MaxArgs()) ctx.RegisterFunc(name, info.Functor(), info.MinArgs(), info.MaxArgs())
+6 -3
View File
@@ -29,7 +29,7 @@ func float64ToFraction(f float64) (fract *fraction, err error) {
var sign string var sign string
intPart, decPart := math.Modf(f) intPart, decPart := math.Modf(f)
if decPart < 0.0 { if decPart < 0.0 {
sign="-" sign = "-"
intPart = -intPart intPart = -intPart
decPart = -decPart decPart = -decPart
} }
@@ -89,11 +89,14 @@ func makeGeneratingFraction(s string) (f *fraction, err error) {
goto exit goto exit
} }
if s[0] == '-' { if s[0] == '-' {
sign=int64(-1) sign = int64(-1)
s = s[1:] s = s[1:]
} else if s[0] == '+' { } else if s[0] == '+' {
s = s[1:] s = s[1:]
} }
if strings.HasSuffix(s, "()") {
s = s[0 : len(s)-2]
}
parts = strings.SplitN(s, ".", 2) parts = strings.SplitN(s, ".", 2)
if num, err = strconv.ParseInt(parts[0], 10, 64); err != nil { if num, err = strconv.ParseInt(parts[0], 10, 64); err != nil {
return return
@@ -106,7 +109,7 @@ func makeGeneratingFraction(s string) (f *fraction, err error) {
den = 1 den = 1
dec := parts[1] dec := parts[1]
lsd := len(dec) lsd := len(dec)
for i:=lsd-1; i>= 0 && dec[i]=='0'; i-- { for i := lsd - 1; i >= 0 && dec[i] == '0'; i-- {
lsd-- lsd--
} }
for _, c := range dec[0:lsd] { for _, c := range dec[0:lsd] {
+2
View File
@@ -158,6 +158,8 @@ func TestGeneralParser(t *testing.T) {
/* 137 */ {`builtin "os.file"`, int64(1), nil}, /* 137 */ {`builtin "os.file"`, int64(1), nil},
/* 138 */ {`v=10; v++; v`, int64(11), nil}, /* 138 */ {`v=10; v++; v`, int64(11), nil},
/* 139 */ {`1+1|2+0.5`, float64(2), nil}, /* 139 */ {`1+1|2+0.5`, float64(2), nil},
/* 140 */ {`1.2()`, newFraction(6, 5), nil},
/* 141 */ {`1|(2-2)`, nil, errors.New(`division by zero`)},
} }
// t.Setenv("EXPR_PATH", ".") // t.Setenv("EXPR_PATH", ".")