Compare commits

..

No commits in common. "main" and "v0.29.0" have entirely different histories.

27 changed files with 385 additions and 917 deletions

View File

@ -33,7 +33,7 @@ func NewDict(dictAny map[any]any) (dict *DictType) {
} }
func newDict(dictAny map[any]*term) (dict *DictType) { func newDict(dictAny map[any]*term) (dict *DictType) {
// TODO Change with a call to NewDict() // TODO Change wi a call to NewDict()
var d DictType var d DictType
if dictAny != nil { if dictAny != nil {
d = make(DictType, len(dictAny)) d = make(DictType, len(dictAny))

View File

@ -439,8 +439,8 @@ _non-empty-list_ = "**[**" _any-value_ {"**,**" _any-value_} "**]**" +
| [blue]`+` | _Join_ | Joins two lists | [blue]`[1,2] + [3]` -> _[1,2,3]_ | [blue]`+` | _Join_ | Joins two lists | [blue]`[1,2] + [3]` -> _[1,2,3]_
| [blue]`-` | _Difference_ | Left list without elements in the right list | [blue]`[1,2,3] - [2]` -> _[1,3]_ | [blue]`-` | _Difference_ | Left list without elements in the right list | [blue]`[1,2,3] - [2]` -> _[1,3]_
| [blue]`+>` | _Front insertion_ | Insert an item in front | [blue]`0 +> [1,2]` -> _[0,1,2]_ | [blue]`>>` | _Front insertion_ | Insert an item in front | [blue]`0 >> [1,2]` -> _[0,1,2]_
| [blue]`<+` | _Back insertion_ | Insert an item at end | [blue]`[1,2] <+ 3` -> _[1,2,3]_ | [blue]`<<` | _Back insertion_ | Insert an item at end | [blue]`[1,2] << 3` -> _[1,2,3]_
| [blue]`[]` | _Item at index_ | Item at given position | [blue]`[1,2,3][1]` -> _2_ | [blue]`[]` | _Item at index_ | Item at given position | [blue]`[1,2,3][1]` -> _2_
| [blue]`in` | _Item in list_ | True if item is in list | [blue]`2 in [1,2,3]` -> _true_ + | [blue]`in` | _Item in list_ | True if item is in list | [blue]`2 in [1,2,3]` -> _true_ +
[blue]`6 in [1,2,3]` -> _false_ [blue]`6 in [1,2,3]` -> _false_
@ -735,17 +735,14 @@ NOTE: These operators have a high priority, in particular higher than the operat
The table below shows all supported operators by decreasing priorities. The table below shows all supported operators by decreasing priorities.
.Operators priorities .Operators priorities
[cols="^3,^2,^2,^5,^6"] [cols="^2,^2,^2,^5,^6"]
|=== |===
| Priority | Operator | Position | Operation | Operands and results | Priority | Operators | Position | Operation | Operands and results
.2+|*ITEM*| [blue]`[`...`]` | _Postfix_ | _List item_| _list_ `[` _integer_ `]` -> _any_ .2+|*ITEM*| [blue]`[`...`]` | _Postfix_ | _List item_| _list_ `[` _integer_ `]` -> _any_
| [blue]`[`...`]` | _Postfix_ | _Dict item_ | _dict_ `[` _any_ `]` -> _any_ | [blue]`[`...`]` | _Postfix_ | _Dict item_ | _dict_ `[` _any_ `]` -> _any_
.5+|*INC/DEC*| [blue]`++` | _Postfix_ | _Iterator next item_ | _iterator_ `++` -> _any_ .2+|*INC*| [blue]`++` | _Postfix_ | _Post increment_| _integer-variable_ `++` -> _integer_
| [blue]`++` | _Postfix_ | _Post increment_| _integer-variable_ `++` -> _integer_ | [blue]`++` | _Postfix_ | _Next item_ | _iterator_ `++` -> _any_
| [blue]`++` | _Prefix_ | _Pre increment_ | `++` _integer-variable_ -> _integer_
| [blue]`--` | _Postfix_ | _Post decrement_ | _integer-variable_ `--` -> _integer_
| [blue]`--` | _Prefix_ | _Pre decrement_ | `--` _integer-variable_ -> _integer_
.3+|*DEFAULT*| [blue]`??` | _Infix_ | _Default value_| _variable_ `??` _any-expr_ -> _any_ .3+|*DEFAULT*| [blue]`??` | _Infix_ | _Default value_| _variable_ `??` _any-expr_ -> _any_
| [blue]`?=` | _Infix_ | _Default/assign value_| _variable_ `?=` _any-expr_ -> _any_ | [blue]`?=` | _Infix_ | _Default/assign value_| _variable_ `?=` _any-expr_ -> _any_
| [blue]`?!` | _Infix_ | _Alternate value_| _variable_ `?!` _any-expr_ -> _any_ | [blue]`?!` | _Infix_ | _Alternate value_| _variable_ `?!` _any-expr_ -> _any_
@ -754,17 +751,13 @@ The table below shows all supported operators by decreasing priorities.
.3+|*SIGN*| [blue]`+`, [blue]`-` | _Prefix_ | _Change-sign_| (`+`\|`-`) _number_ -> _number_ .3+|*SIGN*| [blue]`+`, [blue]`-` | _Prefix_ | _Change-sign_| (`+`\|`-`) _number_ -> _number_
| [blue]`#` | _Prefix_ | _Lenght-of_ | `#` _collection_ -> _integer_ | [blue]`#` | _Prefix_ | _Lenght-of_ | `#` _collection_ -> _integer_
| [blue]`#` | _Prefix_ | _Size-of_ | `#` _iterator_ -> _integer_ | [blue]`#` | _Prefix_ | _Size-of_ | `#` _iterator_ -> _integer_
.2+|*BIT SHIFT*| [blue]`<<` | _Infix_ | _Left-Shift_ | _integer_ `<<` _integer_ -> _integer_
| [blue]`>>` | _Infix_ | _Right-Shift_ | _integer_ `>>` _iterator_ -> _integer_
.2+|*SELECT*| [blue]`? : ::` | _Multi-Infix_ | _Case-Selector_ | _any-expr_ `?` _case-list_ _case-expr_ `:` _case-list_ _case-expr_ ... `::` _default-expr_ -> _any_ .2+|*SELECT*| [blue]`? : ::` | _Multi-Infix_ | _Case-Selector_ | _any-expr_ `?` _case-list_ _case-expr_ `:` _case-list_ _case-expr_ ... `::` _default-expr_ -> _any_
| [blue]`? : ::` | _Multi-Infix_ | _Index-Selector_ | _int-expr_ `?` _case-expr_ `:` _case-expr_ ... `::` _default-expr_ -> _any_ | [blue]`? : ::` | _Multi-Infix_ | _Index-Selector_ | _int-expr_ `?` _case-expr_ `:` _case-expr_ ... `::` _default-expr_ -> _any_
.1+|*FRACT*| [blue]`:` | _Infix_ | _Fraction_ | _integer_ `:` _integer_ -> _fraction_ .1+|*FRACT*| [blue]`:` | _Infix_ | _Fraction_ | _integer_ `:` _integer_ -> _fraction_
.7+|*PROD*| [blue]`*` | _Infix_ | _Product_ | _number_ `*` _number_ -> _number_ .5+|*PROD*| [blue]`*` | _Infix_ | _Product_ | _number_ `*` _number_ -> _number_
| [blue]`*` | _Infix_ | _String-repeat_ | _string_ `*` _integer_ -> _string_ | [blue]`*` | _Infix_ | _String-repeat_ | _string_ `*` _integer_ -> _string_
| [blue]`/` | _Infix_ | _Division_ | _number_ `/` _number_ -> _number_ | [blue]`/` | _Infix_ | _Division_ | _number_ `/` _number_ -> _number_
| [blue]`./` | _Infix_ | _Float-division_ | __number__ `./` _number_ -> _float_ | [blue]`./` | _Infix_ | _Float-division_ | __number__ `./` _number_ -> _float_
| [blue]`/` | _Infix_ | _Split_ | _string_ `/` _string_ -> _list_
| [blue]`/` | _Infix_ | _Split_ | _string_ `/` integer -> _list_
| [blue]`%` | _Infix_ | _Integer-remainder_ | _integer_ `%` _integer_ -> _integer_ | [blue]`%` | _Infix_ | _Integer-remainder_ | _integer_ `%` _integer_ -> _integer_
.6+|*SUM*| [blue]`+` | _Infix_ | _Sum_ | _number_ `+` _number_ -> _number_ .6+|*SUM*| [blue]`+` | _Infix_ | _Sum_ | _number_ `+` _number_ -> _number_
| [blue]`+` | _Infix_ | _String-concat_ | (_string_\|_number_) `+` (_string_\|_number_) -> _string_ | [blue]`+` | _Infix_ | _String-concat_ | (_string_\|_number_) `+` (_string_\|_number_) -> _string_
@ -772,10 +765,9 @@ The table below shows all supported operators by decreasing priorities.
| [blue]`+` | _Infix_ | _Dict-join_ | _dict_ `+` _dict_ -> _dict_ | [blue]`+` | _Infix_ | _Dict-join_ | _dict_ `+` _dict_ -> _dict_
| [blue]`-` | _Infix_ | _Subtraction_ | _number_ `-` _number_ -> _number_ | [blue]`-` | _Infix_ | _Subtraction_ | _number_ `-` _number_ -> _number_
| [blue]`-` | _Infix_ | _List-difference_ | _list_ `-` _list_ -> _list_ | [blue]`-` | _Infix_ | _List-difference_ | _list_ `-` _list_ -> _list_
.1+|*BITWISE NOT*| [blue]`~` | _Prefix_ | _Binary Not_ | `~` _integer_ -> _integer_ .3+|*BINARY*| [blue]`&` | _Infix_ | _Binary And_ | _number_ `&` _number_ -> _number_
.1+|*BITWISE AND*| [blue]`&` | _Infix_ | _Binary And_ | _integer_ `&` _integer_ -> _integer_ | [blue]`\|` | _Infix_ | _Binary Or_ | _number_ `\|` _number_ -> _number_
.2+|*BITWISE OR*| [blue]`\|` | _Infix_ | _Binary Or_ | _integer_ `\|` _integer_ -> _integer_ | [blue]`~` | _Prefix_ | _Binary Not_ | `~` _number_ -> _number_
| [blue]`^` | _Infix_ | _Binary Xor_ | _integer_ `^` _integer_ -> _integer_
.8+|*RELATION*| [blue]`<` | _Infix_ | _Less_ | _comparable_ `<` _comparable_ -> _boolean_ .8+|*RELATION*| [blue]`<` | _Infix_ | _Less_ | _comparable_ `<` _comparable_ -> _boolean_
| [blue]`\<=` | _Infix_ | _less-equal_ | _comparable_ `\<=` _comparable_ -> _boolean_ | [blue]`\<=` | _Infix_ | _less-equal_ | _comparable_ `\<=` _comparable_ -> _boolean_
| [blue]`>` | _Infix_ | _Greater_ | _comparable_ `>` _comparable_ -> _boolean_ | [blue]`>` | _Infix_ | _Greater_ | _comparable_ `>` _comparable_ -> _boolean_
@ -784,54 +776,20 @@ The table below shows all supported operators by decreasing priorities.
| [blue]`!=` | _Infix_ | _Not-equal_ | _comparable_ `!=` _comparable_ -> _boolean_ | [blue]`!=` | _Infix_ | _Not-equal_ | _comparable_ `!=` _comparable_ -> _boolean_
| [blue]`in` | _Infix_ | _Member-of-list_ | _any_ `in` _list_ -> _boolean_ | [blue]`in` | _Infix_ | _Member-of-list_ | _any_ `in` _list_ -> _boolean_
| [blue]`in` | _Infix_ | _Key-of-dict_ | _any_ `in` _dict_ -> _boolean_ | [blue]`in` | _Infix_ | _Key-of-dict_ | _any_ `in` _dict_ -> _boolean_
.1+|*LOGIC NOT*| [blue]`not` | _Prefix_ | _Not_ | `not` _boolean_ -> _boolean_ .1+|*NOT*| [blue]`not` | _Prefix_ | _Not_ | `not` _boolean_ -> _boolean_
.2+|*LOGIC AND*| [blue]`and` | _Infix_ | _And_ | _boolean_ `and` _boolean_ -> _boolean_ .2+|*AND*| [blue]`and` | _Infix_ | _And_ | _boolean_ `and` _boolean_ -> _boolean_
| [blue]`&&` | _Infix_ | _And_ | _boolean_ `&&` _boolean_ -> _boolean_ | [blue]`&&` | _Infix_ | _And_ | _boolean_ `&&` _boolean_ -> _boolean_
.2+|*LOGIC OR*| [blue]`or` | _Infix_ | _Or_ | _boolean_ `or` _boolean_ -> _boolean_ .2+|*OR*| [blue]`or` | _Infix_ | _Or_ | _boolean_ `or` _boolean_ -> _boolean_
| [blue]`\|\|` | _Infix_ | _Or_ | _boolean_ `\|\|` _boolean_ -> _boolean_ | [blue]`\|\|` | _Infix_ | _Or_ | _boolean_ `\|\|` _boolean_ -> _boolean_
.2+|*INSERT*| [blue]`+>` | _Infix_ | _Prepend_ | _any_ `+>` _list_ -> _list_ .3+|*ASSIGN*| [blue]`=` | _Infix_ | _Assignment_ | _identifier_ `=` _any_ -> _any_
| [blue]`<+` | _Infix_ | _Append_ | _list_ `<+` _any_ -> _list_ | [blue]`>>` | _Infix_ | _Front-insert_ | _any_ `>>` _list_ -> _list_
.2+|*ASSIGN*| [blue]`=` | _Infix_ | _Assignment_ | _identifier_ `=` _any_ -> _any_ | [blue]`<<` | _Infix_ | _Back-insert_ | _list_ `<<` _any_ -> _list_
4+| _See also the table of special allocation operators below_
.1+|*BUT*| [blue]`but` | _Infix_ | _But_ | _any_ `but` _any_ -> _any_ .1+|*BUT*| [blue]`but` | _Infix_ | _But_ | _any_ `but` _any_ -> _any_
.1+|*RANGE*| [blue]`:` | _Infix_ | _Index-range_ | _integer_ `:` _integer_ -> _integer-pair_ .1+|*RANGE*| [blue]`:` | _Infix_ | _Index-range_ | _integer_ `:` _integer_ -> _integer-pair_
|=== |===
//^1^ Experimental //^1^ Experimental
.Special assignment perators
[cols="^2,^2,^4,^6"]
|===
| Priority | Operator | Operation |Equivalent operation
.9+|*ASSIGN*| [blue]`+=` | _Sum & Assign_ | _var_ `\+=` _expr_ +
short for +
_var_ `=` _value-of-var_ `+` _expr_
| [blue]`-=` | _Subtract & Assign_ | _var_ `-=` _expr_ +
short for +
_var_ `=` _value-of-var_ `-` _expr_
| [blue]`*=` | _Multiply & Assign_ | _var_ `\*=` _expr_ +
short for +
_var_ `=` _value-of-var_ `*` _expr_
| [blue]`/=` | _Divide & Assign_ | _var_ `/=` _expr_ +
short for +
_var_ `=` _value-of-var_ `/` _expr_
| [blue]`%=` | _Remainder & Assign_ | _var_ `%=` _expr_ +
short for +
_var_ `=` _value-of-var_ `%` _expr_
| [blue]`&=` | _Bitwise and & Assign_ | _var_ `&=` _expr_ +
short for +
_var_ `=` _value-of-var_ `&` _expr_
| [blue]`\|=` | _Bitwise or & Assign_ | _var_ `\|=` _expr_ +
short for +
_var_ `=` _value-of-var_ `\|` _expr_
| [blue]`<\<=` | _Left shift & Assign_ | _var_ `<\<=` _expr_ +
short for +
_var_ `=` _value-of-var_ `<<` _expr_
| [blue]`>>=` | _Right shift & Assign_ | _var_ `>>=` _expr_ +
short for +
_var_ `=` _value-of-var_ `>>` _expr_
|===
== Functions == Functions
Functions in _Expr_ are very similar to functions available in many programming languages. Currently, _Expr_ supports two types of function, _expr-functions_ and _go-functions_. Functions in _Expr_ are very similar to functions available in many programming languages. Currently, _Expr_ supports two types of function, _expr-functions_ and _go-functions_.
@ -882,7 +840,7 @@ _param-name_ = _identifier_
=== _Golang_ function definition === _Golang_ function definition
Description of how to define Golang functions and how to bind them to _Expr_ are topics covered in another document that I'll write, one day, maybe. Description of how to define Golan functions and how to bind them to _Expr_ are topics treated in another document that I'll write, one day, maybe.
=== Function calls === Function calls
To call a function, either Expr or Golang type, it is necessary to specify its name and, at least, its required parameters. To call a function, either Expr or Golang type, it is necessary to specify its name and, at least, its required parameters.

View File

@ -1380,16 +1380,16 @@ dev-expr <span class="nt">--</span> Expressions calculator v1.10.0<span class="o
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2,3] - [2]</code> &#8594; <em>[1,3]</em></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2,3] - [2]</code> &#8594; <em>[1,3]</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;&gt;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Front insertion</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Front insertion</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Insert an item in front</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Insert an item in front</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">0 +&gt; [1,2]</code> &#8594; <em>[0,1,2]</em></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">0 &gt;&gt; [1,2]</code> &#8594; <em>[0,1,2]</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;&lt;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Back insertion</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Back insertion</em></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Insert an item at end</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Insert an item at end</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2] &lt;+ 3</code> &#8594; <em>[1,2,3]</em></p></td> <td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2] &lt;&lt; 3</code> &#8594; <em>[1,2,3]</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>
@ -1900,16 +1900,16 @@ These operators have a high priority, in particular higher than the operator <co
<table class="tableblock frame-all grid-all stretch"> <table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 8. Operators priorities</caption> <caption class="title">Table 8. Operators priorities</caption>
<colgroup> <colgroup>
<col style="width: 16.6666%;"> <col style="width: 11.7647%;">
<col style="width: 11.1111%;"> <col style="width: 11.7647%;">
<col style="width: 11.1111%;"> <col style="width: 11.7647%;">
<col style="width: 27.7777%;"> <col style="width: 29.4117%;">
<col style="width: 33.3335%;"> <col style="width: 35.2942%;">
</colgroup> </colgroup>
<thead> <thead>
<tr> <tr>
<th class="tableblock halign-center valign-top">Priority</th> <th class="tableblock halign-center valign-top">Priority</th>
<th class="tableblock halign-center valign-top">Operator</th> <th class="tableblock halign-center valign-top">Operators</th>
<th class="tableblock halign-center valign-top">Position</th> <th class="tableblock halign-center valign-top">Position</th>
<th class="tableblock halign-center valign-top">Operation</th> <th class="tableblock halign-center valign-top">Operation</th>
<th class="tableblock halign-center valign-top">Operands and results</th> <th class="tableblock halign-center valign-top">Operands and results</th>
@ -1930,13 +1930,7 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>dict</em> <code>[</code> <em>any</em> <code>]</code> &#8594; <em>any</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>dict</em> <code>[</code> <em>any</em> <code>]</code> &#8594; <em>any</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="5"><p class="tableblock"><strong>INC/DEC</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>INC</strong></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>Postfix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Iterator next item</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>iterator</em> <code>++</code> &#8594; <em>any</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"><code class="blue">++</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Postfix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Postfix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Post increment</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Post increment</em></p></td>
@ -1944,21 +1938,9 @@ These operators have a high priority, in particular higher than the operator <co
</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>Prefix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Pre increment</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>++</code> <em>integer-variable</em> &#8594; <em>integer</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>Postfix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Postfix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Post decrement</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Next item</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer-variable</em> <code>--</code> &#8594; <em>integer</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>iterator</em> <code>++</code> &#8594; <em>any</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>Prefix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Pre decrement</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>--</code> <em>integer-variable</em> &#8594; <em>integer</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>DEFAULT</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>DEFAULT</strong></p></td>
@ -2006,19 +1988,6 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>#</code> <em>iterator</em> &#8594; <em>integer</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code>#</code> <em>iterator</em> &#8594; <em>integer</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>BIT SHIFT</strong></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&lt;&lt;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Left-Shift</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>&lt;&lt;</code> <em>integer</em> &#8594; <em>integer</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&gt;&gt;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Right-Shift</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>&gt;&gt;</code> <em>iterator</em> &#8594; <em>integer</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>SELECT</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>SELECT</strong></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"><code class="blue">? : ::</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Multi-Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Multi-Infix</em></p></td>
@ -2039,7 +2008,7 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>:</code> <em>integer</em> &#8594; <em>fraction</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>:</code> <em>integer</em> &#8594; <em>fraction</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="7"><p class="tableblock"><strong>PROD</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="5"><p class="tableblock"><strong>PROD</strong></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"><code class="blue">*</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></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>
@ -2064,18 +2033,6 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>./</code> <em>number</em> &#8594; <em>float</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>./</code> <em>number</em> &#8594; <em>float</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"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Split</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>string</em> <code>/</code> <em>string</em> &#8594; <em>list</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>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Split</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>string</em> <code>/</code> integer &#8594; <em>list</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"><code class="blue">%</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Integer-remainder</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Integer-remainder</em></p></td>
@ -2119,31 +2076,23 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code>-</code> <em>list</em> &#8594; <em>list</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code>-</code> <em>list</em> &#8594; <em>list</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>BITWISE NOT</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>BINARY</strong></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>Prefix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Not</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>~</code> <em>integer</em> &#8594; <em>integer</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>BITWISE AND</strong></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&amp;</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&amp;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary And</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary And</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>&amp;</code> <em>integer</em> &#8594; <em>integer</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>&amp;</code> <em>number</em> &#8594; <em>number</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>BITWISE OR</strong></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"><code class="blue">|</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Or</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Or</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>|</code> <em>integer</em> &#8594; <em>integer</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>|</code> <em>number</em> &#8594; <em>number</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>Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Xor</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Not</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>^</code> <em>integer</em> &#8594; <em>integer</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code>~</code> <em>number</em> &#8594; <em>number</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="8"><p class="tableblock"><strong>RELATION</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="8"><p class="tableblock"><strong>RELATION</strong></p></td>
@ -2195,14 +2144,14 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>in</code> <em>dict</em> &#8594; <em>boolean</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>in</code> <em>dict</em> &#8594; <em>boolean</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>LOGIC NOT</strong></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><strong>NOT</strong></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"><code class="blue">not</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></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-center valign-top"><p class="tableblock"><code>not</code> <em>boolean</em> &#8594; <em>boolean</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code>not</code> <em>boolean</em> &#8594; <em>boolean</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>LOGIC AND</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>AND</strong></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">and</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">and</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></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>
@ -2215,7 +2164,7 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>&amp;&amp;</code> <em>boolean</em> &#8594; <em>boolean</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>&amp;&amp;</code> <em>boolean</em> &#8594; <em>boolean</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>LOGIC OR</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>OR</strong></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">or</code></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">or</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></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>
@ -2228,27 +2177,23 @@ These operators have a high priority, in particular higher than the operator <co
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>||</code> <em>boolean</em> &#8594; <em>boolean</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>||</code> <em>boolean</em> &#8594; <em>boolean</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>INSERT</strong></p></td> <td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>ASSIGN</strong></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>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prepend</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>+&gt;</code> <em>list</em> &#8594; <em>list</em></p></td>
</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"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Append</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code>&lt;+</code> <em>any</em> &#8594; <em>list</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>ASSIGN</strong></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"><code class="blue">=</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Assignment</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>Assignment</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>identifier</em> <code>=</code> <em>any</em> &#8594; <em>any</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><em>identifier</em> <code>=</code> <em>any</em> &#8594; <em>any</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top" colspan="4"><p class="tableblock"><em>See also the table of special allocation operators below</em></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&gt;&gt;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Front-insert</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>&gt;&gt;</code> <em>list</em> &#8594; <em>list</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&lt;&lt;</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Back-insert</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code>&lt;&lt;</code> <em>any</em> &#8594; <em>list</em></p></td>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>BUT</strong></p></td> <td class="tableblock halign-center valign-top"><p class="tableblock"><strong>BUT</strong></p></td>
@ -2266,89 +2211,6 @@ These operators have a high priority, in particular higher than the operator <co
</tr> </tr>
</tbody> </tbody>
</table> </table>
<table class="tableblock frame-all grid-all stretch">
<caption class="title">Table 9. Special assignment perators</caption>
<colgroup>
<col style="width: 14.2857%;">
<col style="width: 14.2857%;">
<col style="width: 28.5714%;">
<col style="width: 42.8572%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-center valign-top">Priority</th>
<th class="tableblock halign-center valign-top">Operator</th>
<th class="tableblock halign-center valign-top">Operation</th>
<th class="tableblock halign-center valign-top">Equivalent operation</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-center valign-top" rowspan="9"><p class="tableblock"><strong>ASSIGN</strong></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 &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>+=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>+</code> <em>expr</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>Subtract &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>-=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>-</code> <em>expr</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>Multiply &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>*=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>*</code> <em>expr</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>Divide &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>/=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>/</code> <em>expr</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>Remainder &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>%=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>%</code> <em>expr</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&amp;=</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Bitwise and &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>&amp;=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>&amp;</code> <em>expr</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>Bitwise or &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>|=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>|</code> <em>expr</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&lt;&lt;=</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Left shift &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>&lt;&lt;=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>&lt;&lt;</code> <em>expr</em></p></td>
</tr>
<tr>
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&gt;&gt;=</code></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Right shift &amp; Assign</em></p></td>
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>&gt;&gt;=</code> <em>expr</em> <br>
short for<br>
<em>var</em> <code>=</code> <em>value-of-var</em> <code>&gt;&gt;</code> <em>expr</em></p></td>
</tr>
</tbody>
</table>
</div> </div>
</div> </div>
<div class="sect1"> <div class="sect1">
@ -2420,7 +2282,7 @@ short for<br>
<div class="sect2"> <div class="sect2">
<h3 id="_golang_function_definition"><a class="anchor" href="#_golang_function_definition"></a><a class="link" href="#_golang_function_definition">6.2. <em>Golang</em> function definition</a></h3> <h3 id="_golang_function_definition"><a class="anchor" href="#_golang_function_definition"></a><a class="link" href="#_golang_function_definition">6.2. <em>Golang</em> function definition</a></h3>
<div class="paragraph"> <div class="paragraph">
<p>Description of how to define Golang functions and how to bind them to <em>Expr</em> are topics covered in another document that I&#8217;ll write, one day, maybe.</p> <p>Description of how to define Golan functions and how to bind them to <em>Expr</em> are topics treated in another document that I&#8217;ll write, one day, maybe.</p>
</div> </div>
</div> </div>
<div class="sect2"> <div class="sect2">
@ -2599,7 +2461,7 @@ g(@p):any{}`
</div> </div>
<div id="footer"> <div id="footer">
<div id="footer-text"> <div id="footer-text">
Last updated 2025-01-05 12:15:58 +0100 Last updated 2024-12-23 07:20:48 +0100
</div> </div>
</div> </div>
</body> </body>

View File

@ -183,16 +183,6 @@ func evalOpAssign(ctx ExprContext, opTerm *term) (v any, err error) {
v, err = divValues(opTerm, leftValue, rightValue) v, err = divValues(opTerm, leftValue, rightValue)
case SymPercEqual: case SymPercEqual:
v, err = remainderValues(opTerm, leftValue, rightValue) v, err = remainderValues(opTerm, leftValue, rightValue)
case SymAmpersandEqual:
v, err = bitwiseAnd(opTerm, leftValue, rightValue)
case SymVertBarEqual:
v, err = bitwiseOr(opTerm, leftValue, rightValue)
case SymCaretEqual:
v, err = bitwiseXor(opTerm, leftValue, rightValue)
case SymDoubleLessEqual:
v, err = bitLeftShift(opTerm, leftValue, rightValue)
case SymDoubleGreaterEqual:
v, err = bitRightShift(opTerm, leftValue, rightValue)
default: default:
err = opTerm.Errorf("unsupported assign operator %q", opTerm.source()) err = opTerm.Errorf("unsupported assign operator %q", opTerm.source())
} }
@ -211,10 +201,4 @@ func init() {
registerTermConstructor(SymMinusEqual, newOpAssignTerm) registerTermConstructor(SymMinusEqual, newOpAssignTerm)
registerTermConstructor(SymStarEqual, newOpAssignTerm) registerTermConstructor(SymStarEqual, newOpAssignTerm)
registerTermConstructor(SymSlashEqual, newOpAssignTerm) registerTermConstructor(SymSlashEqual, newOpAssignTerm)
registerTermConstructor(SymPercEqual, newOpAssignTerm)
registerTermConstructor(SymDoubleLessEqual, newOpAssignTerm)
registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm)
registerTermConstructor(SymAmpersandEqual, newOpAssignTerm)
registerTermConstructor(SymVertBarEqual, newOpAssignTerm)
registerTermConstructor(SymCaretEqual, newOpAssignTerm)
} }

104
operator-binary.go Normal file
View File

@ -0,0 +1,104 @@
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// operator-binary.go
package expr
//-------- NOT term
func newBinNotTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 1),
position: posPrefix,
priority: priBinary,
evalFunc: evalBinaryNot,
}
}
func evalBinaryNot(ctx ExprContext, opTerm *term) (v any, err error) {
var value any
if value, err = opTerm.evalPrefix(ctx); err != nil {
return
}
if IsInteger(value) {
i, _ := value.(int64)
v = ^i
} else {
err = opTerm.errIncompatibleType(value)
}
return
}
//-------- Binary AND term
func newBinAndTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priBinary,
evalFunc: evalBinaryAnd,
}
}
func evalBinaryAnd(ctx ExprContext, self *term) (v any, err error) {
var leftValue, rightValue any
var leftInt, rightInt int64
var lok, rok bool
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
return
}
leftInt, lok = leftValue.(int64)
rightInt, rok = rightValue.(int64)
if lok && rok {
v = leftInt & rightInt
} else {
err = self.errIncompatibleTypes(leftValue, rightValue)
}
return
}
//-------- Binary OR term
func newBinOrTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priBinary,
evalFunc: evalBinaryOr,
}
}
func evalBinaryOr(ctx ExprContext, self *term) (v any, err error) {
var leftValue, rightValue any
var leftInt, rightInt int64
var lok, rok bool
if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
return
}
leftInt, lok = leftValue.(int64)
rightInt, rok = rightValue.(int64)
if lok && rok {
v = leftInt | rightInt
} else {
err = self.errIncompatibleTypes(leftValue, rightValue)
}
return
}
// init
func init() {
registerTermConstructor(SymTilde, newBinNotTerm)
registerTermConstructor(SymAmpersand, newBinAndTerm)
registerTermConstructor(SymVertBar, newBinOrTerm)
}

View File

@ -1,154 +0,0 @@
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// operator-bitwise.go
package expr
//-------- Bitwise NOT term
func newBitwiseNotTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 1),
position: posPrefix,
priority: priBitwiseNot,
evalFunc: evalBitwiseNot,
}
}
func evalBitwiseNot(ctx ExprContext, opTerm *term) (v any, err error) {
var value any
if value, err = opTerm.evalPrefix(ctx); err != nil {
return
}
if IsInteger(value) {
i, _ := value.(int64)
v = ^i
} else {
err = opTerm.errIncompatibleType(value)
}
return
}
//-------- Bitwise AND term
func newBitwiseAndTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priBitwiseAnd,
evalFunc: evalBitwiseAnd,
}
}
func bitwiseAnd(opTerm *term, leftValue, rightValue any) (v any, err error) {
var leftInt, rightInt int64
var lok, rok bool
leftInt, lok = leftValue.(int64)
rightInt, rok = rightValue.(int64)
if lok && rok {
v = leftInt & rightInt
} else {
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
}
return
}
func evalBitwiseAnd(ctx ExprContext, opTerm *term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
return
}
v, err = bitwiseAnd(opTerm, leftValue, rightValue)
return
}
//-------- Bitwise OR term
func newBitwiseOrTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priBitwiseOr,
evalFunc: evalBitwiseOr,
}
}
func bitwiseOr(opTerm *term, leftValue, rightValue any) (v any, err error) {
var leftInt, rightInt int64
var lok, rok bool
leftInt, lok = leftValue.(int64)
rightInt, rok = rightValue.(int64)
if lok && rok {
v = leftInt | rightInt
} else {
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
}
return
}
func evalBitwiseOr(ctx ExprContext, opTerm *term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
return
}
v, err = bitwiseOr(opTerm, leftValue, rightValue)
return
}
//-------- Bitwise XOR term
func newBitwiseXorTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priBitwiseOr,
evalFunc: evalBitwiseXor,
}
}
func bitwiseXor(opTerm *term, leftValue, rightValue any) (v any, err error) {
var leftInt, rightInt int64
var lok, rok bool
leftInt, lok = leftValue.(int64)
rightInt, rok = rightValue.(int64)
if lok && rok {
v = leftInt ^ rightInt
} else {
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
}
return
}
func evalBitwiseXor(ctx ExprContext, opTerm *term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
return
}
v, err = bitwiseXor(opTerm, leftValue, rightValue)
return
}
// init
func init() {
registerTermConstructor(SymTilde, newBitwiseNotTerm)
registerTermConstructor(SymAmpersand, newBitwiseAndTerm)
registerTermConstructor(SymVertBar, newBitwiseOrTerm)
registerTermConstructor(SymCaret, newBitwiseXorTerm)
}

View File

@ -7,6 +7,7 @@ package expr
//https://www.youmath.it/lezioni/algebra-elementare/lezioni-di-algebra-e-aritmetica-per-scuole-medie/553-dalle-frazioni-a-numeri-decimali.html //https://www.youmath.it/lezioni/algebra-elementare/lezioni-di-algebra-e-aritmetica-per-scuole-medie/553-dalle-frazioni-a-numeri-decimali.html
import ( import (
"errors"
"fmt" "fmt"
) )
@ -40,7 +41,7 @@ func evalFraction(ctx ExprContext, opTerm *term) (v any, err error) {
return return
} }
if den == 0 { if den == 0 {
err = opTerm.errDivisionByZero() err = errors.New("division by zero")
return return
} }

View File

@ -4,15 +4,15 @@
// operator-insert.go // operator-insert.go
package expr package expr
//-------- prepend term //-------- insert term
func newPrependTerm(tk *Token) (inst *term) { func newInsertTerm(tk *Token) (inst *term) {
return &term{ return &term{
tk: *tk, tk: *tk,
children: make([]*term, 0, 2), children: make([]*term, 0, 2),
position: posInfix, position: posInfix,
priority: priInsert, priority: priAssign,
evalFunc: evalPrepend, evalFunc: evalInsert,
} }
} }
@ -21,12 +21,12 @@ func newAppendTerm(tk *Token) (inst *term) {
tk: *tk, tk: *tk,
children: make([]*term, 0, 2), children: make([]*term, 0, 2),
position: posInfix, position: posInfix,
priority: priInsert, priority: priAssign,
evalFunc: evalAppend, evalFunc: evalAppend,
} }
} }
func evalPrepend(ctx ExprContext, opTerm *term) (v any, err error) { func evalInsert(ctx ExprContext, opTerm *term) (v any, err error) {
var leftValue, rightValue any var leftValue, rightValue any
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil { if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
@ -40,6 +40,10 @@ func evalPrepend(ctx ExprContext, opTerm *term) (v any, err error) {
if opTerm.children[1].symbol() == SymVariable { if opTerm.children[1].symbol() == SymVariable {
ctx.UnsafeSetVar(opTerm.children[1].source(), v) ctx.UnsafeSetVar(opTerm.children[1].source(), v)
} }
} else if IsInteger(leftValue) && IsInteger(rightValue) {
leftInt := leftValue.(int64)
rightInt := rightValue.(int64)
v = leftInt >> rightInt
} else { } else {
err = opTerm.errIncompatibleTypes(leftValue, rightValue) err = opTerm.errIncompatibleTypes(leftValue, rightValue)
} }
@ -60,6 +64,10 @@ func evalAppend(ctx ExprContext, opTerm *term) (v any, err error) {
if opTerm.children[0].symbol() == SymVariable { if opTerm.children[0].symbol() == SymVariable {
ctx.UnsafeSetVar(opTerm.children[0].source(), v) ctx.UnsafeSetVar(opTerm.children[0].source(), v)
} }
} else if IsInteger(leftValue) && IsInteger(rightValue) {
leftInt := leftValue.(int64)
rightInt := rightValue.(int64)
v = leftInt << rightInt
} else { } else {
err = opTerm.errIncompatibleTypes(leftValue, rightValue) err = opTerm.errIncompatibleTypes(leftValue, rightValue)
} }
@ -86,6 +94,6 @@ func evalAppend(ctx ExprContext, opTerm *term) (v any, err error) {
// init // init
func init() { func init() {
registerTermConstructor(SymPlusGreater, newPrependTerm) registerTermConstructor(SymInsert, newInsertTerm)
registerTermConstructor(SymLessPlus, newAppendTerm) registerTermConstructor(SymAppend, newAppendTerm)
} }

View File

@ -11,7 +11,7 @@ func newIterValueTerm(tk *Token) (inst *term) {
tk: *tk, tk: *tk,
children: make([]*term, 0, 1), children: make([]*term, 0, 1),
position: posPrefix, position: posPrefix,
priority: priDereference, priority: priIterValue,
evalFunc: evalIterValue, evalFunc: evalIterValue,
} }
} }
@ -33,6 +33,6 @@ func evalIterValue(ctx ExprContext, opTerm *term) (v any, err error) {
// init // init
func init() { func init() {
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm) // registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
registerTermConstructor(SymDereference, newIterValueTerm) registerTermConstructor(SymCaret, newIterValueTerm)
} }

View File

@ -1,7 +1,7 @@
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved. // All rights reserved.
// operator-post-inc-dec.go // operator-post-inc.go
package expr package expr
// -------- post increment term // -------- post increment term

View File

@ -1,69 +0,0 @@
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// operator-pre-inc-dec.go
package expr
// -------- pre increment term
func newPreIncTerm(tk *Token) *term {
return &term{
tk: *tk,
parent: nil,
children: make([]*term, 0, 1),
position: posPrefix,
priority: priIncDec,
evalFunc: evalPreInc,
}
}
func evalPreInc(ctx ExprContext, opTerm *term) (v any, err error) {
var childValue any
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
return
}
if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
i := childValue.(int64) + 1
ctx.SetVar(opTerm.children[0].source(), i)
v = i
} else {
err = opTerm.errIncompatibleType(childValue)
}
return
}
// -------- pre decrement term
func newPreDecTerm(tk *Token) *term {
return &term{
tk: *tk,
parent: nil,
children: make([]*term, 0, 1),
position: posPrefix,
priority: priIncDec,
evalFunc: evalPreDec,
}
}
func evalPreDec(ctx ExprContext, opTerm *term) (v any, err error) {
var childValue any
if childValue, err = opTerm.evalPrefix(ctx); err != nil {
return
}
if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
i := childValue.(int64) - 1
ctx.SetVar(opTerm.children[0].source(), i)
v = i
} else {
err = opTerm.errIncompatibleType(childValue)
}
return
}
// init
func init() {
registerTermConstructor(SymPreInc, newPreIncTerm)
registerTermConstructor(SymPreDec, newPreDecTerm)
}

View File

@ -5,6 +5,7 @@
package expr package expr
import ( import (
"errors"
"strings" "strings"
) )
@ -68,7 +69,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
if IsFloat(leftValue) || IsFloat(rightValue) { if IsFloat(leftValue) || IsFloat(rightValue) {
d := numAsFloat(rightValue) d := numAsFloat(rightValue)
if d == 0.0 { if d == 0.0 {
err = opTerm.errDivisionByZero() err = errors.New("division by zero")
} else { } else {
v = numAsFloat(leftValue) / d v = numAsFloat(leftValue) / d
} }
@ -77,36 +78,11 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
} else { } else {
leftInt, _ := leftValue.(int64) leftInt, _ := leftValue.(int64)
if rightInt, _ := rightValue.(int64); rightInt == 0 { if rightInt, _ := rightValue.(int64); rightInt == 0 {
err = opTerm.errDivisionByZero() err = errors.New("division by zero")
} else { } else {
v = leftInt / rightInt v = leftInt / rightInt
} }
} }
} else if IsString(leftValue) && IsString(rightValue) {
source := leftValue.(string)
sep := rightValue.(string)
v = ListFromStrings(strings.Split(source, sep))
} else if IsString(leftValue) && IsInteger(rightValue) {
source := leftValue.(string)
partSize := int(rightValue.(int64))
if partSize == 0 {
err = opTerm.errDivisionByZero()
} else {
partCount := len(source) / partSize
remainder := len(source) % partSize
listSize := partCount
if remainder > 0 {
listSize++
}
parts := make([]any, 0, listSize)
for i := 0; i < partCount; i++ {
parts = append(parts, source[i*partSize:(i+1)*partSize])
}
if remainder > 0 {
parts = append(parts, source[len(source)-remainder:])
}
v = newList(parts)
}
} else { } else {
err = opTerm.errIncompatibleTypes(leftValue, rightValue) err = opTerm.errIncompatibleTypes(leftValue, rightValue)
} }
@ -145,7 +121,7 @@ func evalDivideAsFloat(ctx ExprContext, floatDivTerm *term) (v any, err error) {
if isNumOrFract(leftValue) && isNumOrFract(rightValue) { if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
d := numAsFloat(rightValue) d := numAsFloat(rightValue)
if d == 0.0 { if d == 0.0 {
err = floatDivTerm.errDivisionByZero() err = errors.New("division by zero")
} else { } else {
v = numAsFloat(leftValue) / d v = numAsFloat(leftValue) / d
} }
@ -170,7 +146,7 @@ func remainderValues(opTerm *term, leftValue, rightValue any) (v any, err error)
if IsInteger(leftValue) && IsInteger(rightValue) { if IsInteger(leftValue) && IsInteger(rightValue) {
rightInt, _ := rightValue.(int64) rightInt, _ := rightValue.(int64)
if rightInt == 0 { if rightInt == 0 {
err = opTerm.errDivisionByZero() err = errors.New("division by zero")
} else { } else {
leftInt, _ := leftValue.(int64) leftInt, _ := leftValue.(int64)
v = leftInt % rightInt v = leftInt % rightInt

View File

@ -1,77 +0,0 @@
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// operator-shift.go
package expr
//-------- bit right shift term
func newRightShiftTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priBinShift,
evalFunc: evalRightShift,
}
}
func bitRightShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
if IsInteger(leftValue) && IsInteger(rightValue) {
leftInt := leftValue.(int64)
rightInt := rightValue.(int64)
v = leftInt >> rightInt
} else {
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
}
return
}
func evalRightShift(ctx ExprContext, opTerm *term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
return
}
v, err = bitRightShift(opTerm, leftValue, rightValue)
return
}
func newLeftShiftTerm(tk *Token) (inst *term) {
return &term{
tk: *tk,
children: make([]*term, 0, 2),
position: posInfix,
priority: priBinShift,
evalFunc: evalLeftShift,
}
}
func bitLeftShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
if IsInteger(leftValue) && IsInteger(rightValue) {
leftInt := leftValue.(int64)
rightInt := rightValue.(int64)
v = leftInt << rightInt
} else {
err = opTerm.errIncompatibleTypes(leftValue, rightValue)
}
return
}
func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) {
var leftValue, rightValue any
if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
return
}
v, err = bitLeftShift(opTerm, leftValue, rightValue)
return
}
// init
func init() {
registerTermConstructor(SymDoubleGreater, newRightShiftTerm)
registerTermConstructor(SymDoubleLess, newLeftShiftTerm)
}

View File

@ -409,23 +409,6 @@ func listSubTree(tree *ast, listTerm *term, allowIndeces bool) (root *term, err
return return
} }
func changePrefix(tk *Token) {
switch tk.Sym {
case SymMinus:
tk.SetSymbol(SymChangeSign)
case SymPlus:
tk.SetSymbol(SymUnchangeSign)
case SymStar:
tk.SetSymbol(SymDereference)
case SymExclamation:
tk.SetSymbol(SymNot)
case SymDoublePlus:
tk.SetSymbol(SymPreInc)
case SymDoubleMinus:
tk.SetSymbol(SymPreDec)
}
}
func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymbols ...Symbol) (tree *ast, err error) { func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymbols ...Symbol) (tree *ast, err error) {
var selectorTerm *term = nil var selectorTerm *term = nil
var currentTerm *term = nil var currentTerm *term = nil
@ -454,16 +437,14 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
//fmt.Println("Token:", tk) //fmt.Println("Token:", tk)
if firstToken { if firstToken {
changePrefix(tk) if tk.Sym == SymMinus {
// if tk.Sym == SymMinus { tk.Sym = SymChangeSign
// tk.Sym = SymChangeSign } else if tk.Sym == SymPlus {
// } else if tk.Sym == SymPlus { tk.Sym = SymUnchangeSign
// tk.Sym = SymUnchangeSign } else if tk.IsSymbol(SymExclamation) {
// } else if tk.IsSymbol(SymStar) { err = tk.Errorf("postfix opertor %q requires an operand on its left", tk)
// tk.SetSymbol(SymDereference) break
// } else if tk.IsSymbol(SymExclamation) { }
// tk.SetSymbol(SymNot)
// }
firstToken = false firstToken = false
} }
@ -471,12 +452,9 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
case SymOpenRound: case SymOpenRound:
var subTree *ast var subTree *ast
if subTree, err = parser.parseGeneral(scanner, ctx, SymClosedRound); err == nil { if subTree, err = parser.parseGeneral(scanner, ctx, SymClosedRound); err == nil {
exprTerm := newExprTerm(subTree.root) subTree.root.priority = priValue
err = tree.addTerm(exprTerm) err = tree.addTerm(newExprTerm(subTree.root))
currentTerm = exprTerm currentTerm = subTree.root
// subTree.root.priority = priValue
// err = tree.addTerm(newExprTerm(subTree.root))
// currentTerm = subTree.root
} }
case SymFuncCall: case SymFuncCall:
var funcCallTerm *term var funcCallTerm *term
@ -500,7 +478,7 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
currentTerm = mapTerm currentTerm = mapTerm
} }
} }
case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual, SymAmpersandEqual, SymVertBarEqual, SymDoubleLessEqual, SymDoubleGreaterEqual, SymCaretEqual: case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual:
currentTerm, err = tree.addToken(tk) currentTerm, err = tree.addToken(tk)
firstToken = true firstToken = true
case SymFuncDef: case SymFuncDef:
@ -537,11 +515,14 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
} }
} }
} else { } else {
// if hasFlag(ctx, allowIndex) {
// tk.Sym = SymRange
// }
currentTerm, err = tree.addToken(tk) currentTerm, err = tree.addToken(tk)
if tk.IsOneOfA(SymColon, SymRange) { }
// Colon outside a selector term acts like a separator if tk.IsOneOfA(SymColon, SymRange) {
firstToken = true // Colon outside a selector term acts like a separator
} firstToken = true
} }
default: default:
currentTerm, err = tree.addToken(tk) currentTerm, err = tree.addToken(tk)

View File

@ -124,8 +124,6 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
tk = scanner.moveOn(SymDoublePlus, ch, next) tk = scanner.moveOn(SymDoublePlus, ch, next)
} else if next == '=' { } else if next == '=' {
tk = scanner.moveOn(SymPlusEqual, ch, next) tk = scanner.moveOn(SymPlusEqual, ch, next)
} else if next == '>' {
tk = scanner.moveOn(SymPlusGreater, ch, next)
} else { } else {
tk = scanner.makeToken(SymPlus, ch) tk = scanner.makeToken(SymPlus, ch)
} }
@ -169,19 +167,13 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
case '|': case '|':
if next, _ := scanner.peek(); next == '|' { if next, _ := scanner.peek(); next == '|' {
tk = scanner.moveOn(SymDoubleVertBar, ch, next) tk = scanner.moveOn(SymDoubleVertBar, ch, next)
} else if next, _ = scanner.peek(); next == '=' {
tk = scanner.moveOn(SymVertBarEqual, ch, next)
} else { } else {
tk = scanner.makeToken(SymVertBar, ch) tk = scanner.makeToken(SymVertBar, ch)
} }
case ',': case ',':
tk = scanner.makeToken(SymComma, ch) tk = scanner.makeToken(SymComma, ch)
case '^': case '^':
if next, _ := scanner.peek(); next == '=' { tk = scanner.makeToken(SymCaret, ch)
tk = scanner.moveOn(SymCaretEqual, ch, next)
} else {
tk = scanner.makeToken(SymCaret, ch)
}
case ':': case ':':
if next, _ := scanner.peek(); next == ':' { if next, _ := scanner.peek(); next == ':' {
tk = scanner.moveOn(SymDoubleColon, ch, next) tk = scanner.moveOn(SymDoubleColon, ch, next)
@ -240,17 +232,11 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
case '&': case '&':
if next, _ := scanner.peek(); next == '&' { if next, _ := scanner.peek(); next == '&' {
tk = scanner.moveOn(SymDoubleAmpersand, ch, next) tk = scanner.moveOn(SymDoubleAmpersand, ch, next)
} else if next, _ = scanner.peek(); next == '=' {
tk = scanner.moveOn(SymAmpersandEqual, ch, next)
} else { } else {
tk = scanner.makeToken(SymAmpersand, ch) tk = scanner.makeToken(SymAmpersand, ch)
} }
case '%': case '%':
if next, _ := scanner.peek(); next == '=' { tk = scanner.makeToken(SymPercent, ch)
tk = scanner.moveOn(SymPercEqual, ch, next)
} else {
tk = scanner.makeToken(SymPercent, ch)
}
case '#': case '#':
tk = scanner.makeToken(SymHash, ch) tk = scanner.makeToken(SymHash, ch)
case '@': case '@':
@ -279,18 +265,9 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
if next, _ := scanner.peek(); next == '=' { if next, _ := scanner.peek(); next == '=' {
tk = scanner.moveOn(SymLessOrEqual, ch, next) tk = scanner.moveOn(SymLessOrEqual, ch, next)
} else if next == '<' { } else if next == '<' {
scanner.readChar() tk = scanner.moveOn(SymAppend, ch, next)
next2, _ := scanner.readChar()
scanner.unreadChar()
if next2 == '=' {
tk = scanner.moveOn(SymDoubleLessEqual, ch, next, next2)
} else {
tk = scanner.accept(SymDoubleLess, ch, next)
}
} else if next == '>' { } else if next == '>' {
tk = scanner.moveOn(SymLessGreater, ch, next) tk = scanner.moveOn(SymLessGreater, ch, next)
} else if next == '+' {
tk = scanner.moveOn(SymLessPlus, ch, next)
} else { } else {
tk = scanner.makeToken(SymLess, ch) tk = scanner.makeToken(SymLess, ch)
} }
@ -298,14 +275,7 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
if next, _ := scanner.peek(); next == '=' { if next, _ := scanner.peek(); next == '=' {
tk = scanner.moveOn(SymGreaterOrEqual, ch, next) tk = scanner.moveOn(SymGreaterOrEqual, ch, next)
} else if next == '>' { } else if next == '>' {
scanner.readChar() tk = scanner.moveOn(SymInsert, ch, next)
next2, _ := scanner.readChar()
scanner.unreadChar()
if next2 == '=' {
tk = scanner.moveOn(SymDoubleGreaterEqual, ch, next, next2)
} else {
tk = scanner.accept(SymDoubleGreater, ch, next)
}
} else { } else {
tk = scanner.makeToken(SymGreater, ch) tk = scanner.makeToken(SymGreater, ch)
} }
@ -660,16 +630,9 @@ func (scanner *scanner) translate(sym Symbol) Symbol {
func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) { func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) {
tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars)) tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
// for i := 1; i < len(chars); i++ { for i := 1; i < len(chars); i++ {
if len(chars) > 1 {
scanner.readChar() scanner.readChar()
} }
// }
return
}
func (scanner *scanner) accept(sym Symbol, chars ...byte) (tk *Token) {
tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
return return
} }

View File

@ -14,7 +14,7 @@ type symbolClass int16
const ( const (
symClassOperator symbolClass = iota symClassOperator symbolClass = iota
symClassCommand symClassPostOp
symClassIdentifier symClassIdentifier
symClassDelimiter symClassDelimiter
symClassParenthesis symClassParenthesis
@ -24,87 +24,77 @@ const (
) )
type symbolSpec struct { type symbolSpec struct {
repr string repr string
kind symbolClass kind symbolClass
opType termPosition
} }
func init() { func init() {
symbolMap = map[Symbol]symbolSpec{ symbolMap = map[Symbol]symbolSpec{
SymUnknown: {"<unknown>", symClassOther, posLeaf}, // -1: Unknown symbol SymUnknown: {"<unknown>", symClassOther}, // -1: Unknown symbol
SymNone: {"<null>", symClassOther, posLeaf}, // 0: Null value for variable of type symbol SymNone: {"<null>", symClassOther}, // 0: Null value for variable of type symbol
SymError: {"<error>", symClassOther, posLeaf}, // 1: Error reading from stream SymError: {"<error>", symClassOther}, // 1: Error reading from stream
SymEos: {"<eos>", symClassOther, posLeaf}, // 2: End of stream SymEos: {"<eos>", symClassOther}, // 2: End of stream
SymMinus: {"-", symClassOperator, posInfix}, // 3: '-' SymMinus: {"-", symClassOperator}, // 3: '-'
SymMinusEqual: {"-=", symClassOperator, posInfix}, // 4: '-=' SymMinusEqual: {"-=", symClassOperator}, // 4: '-='
SymDoubleMinus: {"--", symClassOperator, posPostfix}, // 5: '--' SymDoubleMinus: {"--", symClassOperator}, // 5: '--'
SymPlus: {"+", symClassOperator, posInfix}, // 6: '+' SymPlus: {"+", symClassOperator}, // 6: '+'
SymPlusEqual: {"+=", symClassOperator, posInfix}, // 7: '+=' SymPlusEqual: {"+=", symClassOperator}, // 7: '+='
SymDoublePlus: {"++", symClassOperator, posPostfix}, // 8: '++' SymDoublePlus: {"++", symClassOperator}, // 8: '++'
SymStar: {"*", symClassOperator, posInfix}, // 9: '*' SymStar: {"*", symClassOperator}, // 9: '*'
SymDoubleStar: {"**", symClassOperator, posInfix}, // 10: '**' SymDoubleStar: {"**", symClassOperator}, // 10: '**'
SymSlash: {"/", symClassOperator, posInfix}, // 11: '/' SymSlash: {"/", symClassOperator}, // 11: '/'
SymBackSlash: {"\\", symClassOperator, posLeaf}, // 12: '\' SymBackSlash: {"\\", symClassOperator}, // 12: '\'
SymVertBar: {"|", symClassOperator, posInfix}, // 13: '|' SymVertBar: {"|", symClassOperator}, // 13: '|'
SymDoubleVertBar: {"||", symClassOperator, posInfix}, // 14: '||' SymDoubleVertBar: {"||", symClassOperator}, // 14: '||'
SymComma: {",", symClassOperator, posInfix}, // 15: ',' SymComma: {",", symClassOperator}, // 15: ','
SymColon: {":", symClassOperator, posInfix}, // 16: ':' SymColon: {":", symClassOperator}, // 16: ':'
SymSemiColon: {";", symClassOperator, posInfix}, // 17: ';' SymSemiColon: {";", symClassOperator}, // 17: ';'
SymDot: {".", symClassOperator, posInfix}, // 18: '.' SymDot: {".", symClassOperator}, // 18: '.'
SymDotSlash: {"./", symClassOperator, posInfix}, // 19: './' SymDotSlash: {"./", symClassOperator}, // 19: './'
SymQuote: {"'", symClassDelimiter, posLeaf}, // 20: '\'' SymQuote: {"'", symClassDelimiter}, // 20: '\''
SymDoubleQuote: {"\"", symClassDelimiter, posLeaf}, // 21: '"' SymDoubleQuote: {"\"", symClassDelimiter}, // 21: '"'
SymBackTick: {"`", symClassDelimiter, posLeaf}, // 22: '`' SymBackTick: {"`", symClassOperator}, // 22: '`'
SymExclamation: {"!", symClassOperator, posPostfix}, // 23: '!' SymExclamation: {"!", symClassPostOp}, // 23: '!'
SymQuestion: {"?", symClassOperator, posInfix}, // 24: '?' SymQuestion: {"?", symClassOperator}, // 24: '?'
SymAmpersand: {"&", symClassOperator, posInfix}, // 25: '&' SymAmpersand: {"&", symClassOperator}, // 25: '&'
SymDoubleAmpersand: {"&&", symClassOperator, posInfix}, // 26: '&&' SymDoubleAmpersand: {"&&", symClassOperator}, // 26: '&&'
SymPercent: {"%", symClassOperator, posInfix}, // 27: '%' SymPercent: {"%", symClassOperator}, // 27: '%'
SymAt: {"@", symClassOperator, posPrefix}, // 28: '@' SymAt: {"@", symClassOperator}, // 28: '@'
SymUndescore: {"_", symClassIdentifier, posLeaf}, // 29: '_' SymUndescore: {"_", symClassOperator}, // 29: '_'
SymEqual: {"=", symClassOperator, posInfix}, // 30: '=' SymEqual: {"=", symClassOperator}, // 30: '='
SymDoubleEqual: {"==", symClassOperator, posInfix}, // 31: '==' SymDoubleEqual: {"==", symClassOperator}, // 31: '=='
SymLess: {"<", symClassOperator, posInfix}, // 32: '<' SymLess: {"<", symClassOperator}, // 32: '<'
SymLessOrEqual: {"<=", symClassOperator, posInfix}, // 33: '<=' SymLessOrEqual: {"<=", symClassOperator}, // 33: '<='
SymGreater: {">", symClassOperator, posInfix}, // 34: '>' SymGreater: {">", symClassOperator}, // 34: '>'
SymGreaterOrEqual: {">=", symClassOperator, posInfix}, // 35: '>=' SymGreaterOrEqual: {">=", symClassOperator}, // 35: '>='
SymLessGreater: {"<>", symClassOperator, posInfix}, // 36: '<>' SymLessGreater: {"<>", symClassOperator}, // 36: '<>'
SymNotEqual: {"!=", symClassOperator, posInfix}, // 37: '!=' SymNotEqual: {"!=", symClassOperator}, // 37: '!='
SymDollar: {"$", symClassOperator, posPrefix}, // 38: '$' SymDollar: {"$", symClassOperator}, // 38: '$'
SymHash: {"#", symClassOperator, posPrefix}, // 39: '#' SymHash: {"#", symClassOperator}, // 39: '#'
SymOpenRound: {"(", symClassParenthesis, posPrefix}, // 40: '(' SymOpenRound: {"(", symClassParenthesis}, // 40: '('
SymClosedRound: {")", symClassParenthesis, posPostfix}, // 41: ')' SymClosedRound: {")", symClassParenthesis}, // 41: ')'
SymOpenSquare: {"[", symClassParenthesis, posPrefix}, // 42: '[' SymOpenSquare: {"[", symClassParenthesis}, // 42: '['
SymClosedSquare: {"]", symClassParenthesis, posPostfix}, // 43: ']' SymClosedSquare: {"]", symClassParenthesis}, // 43: ']'
SymOpenBrace: {"{", symClassParenthesis, posPrefix}, // 44: '{' SymOpenBrace: {"{", symClassParenthesis}, // 44: '{'
SymClosedBrace: {"}", symClassParenthesis, posPostfix}, // 45: '}' SymClosedBrace: {"}", symClassParenthesis}, // 45: '}'
SymTilde: {"~", symClassOperator, posPrefix}, // 46: '~' SymTilde: {"~", symClassOperator}, // 46: '~'
SymDoubleQuestion: {"??", symClassOperator, posInfix}, // 47: '??' SymDoubleQuestion: {"??", symClassOperator}, // 47: '??'
SymQuestionEqual: {"?=", symClassOperator, posInfix}, // 48: '?=' SymQuestionEqual: {"?=", symClassOperator}, // 48: '?='
SymQuestionExclam: {"?!", symClassOperator, posInfix}, // 49: '?!' SymQuestionExclam: {"?!", symClassOperator}, // 49: '?!'
SymDoubleAt: {"@@", symClassCommand, posLeaf}, // 50: '@@' SymDoubleAt: {"@@", symClassOperator}, // 50: '@@'
SymDoubleColon: {"::", symClassOperator, posInfix}, // 51: '::' SymDoubleColon: {"::", symClassOperator}, // 51: '::'
SymDoubleGreater: {">>", symClassOperator, posInfix}, // 52: '>>' SymInsert: {">>", symClassOperator}, // 52: '>>'
SymDoubleLess: {"<<", symClassOperator, posInfix}, // 53: '<<' SymAppend: {"<<", symClassOperator}, // 53: '<<'
SymCaret: {"^", symClassOperator, posInfix}, // 54: '^' SymCaret: {"^", symClassOperator}, // 54: '^'
SymDollarRound: {"$(", symClassOperator, posPrefix}, // 55: '$(' SymDollarRound: {"$(", symClassOperator}, // 55: '$('
SymOpenClosedRound: {"()", symClassOperator, posPostfix}, // 56: '()' SymOpenClosedRound: {"()", symClassPostOp}, // 56: '()'
SymDoubleDollar: {"$$", symClassCommand, posLeaf}, // 57: '$$' SymDoubleDollar: {"$$", symClassOperator}, // 57: '$$'
SymDoubleDot: {"..", symClassOperator, posInfix}, // 58: '..' SymDoubleDot: {"..", symClassOperator}, // 58: '..'
SymTripleDot: {"...", symClassOperator, posPostfix}, // 59: '...' SymTripleDot: {"...", symClassOperator}, // 59: '...'
SymStarEqual: {"*=", symClassOperator, posInfix}, // 60: '*=' SymStarEqual: {"*=", symClassOperator}, // 60: '*='
SymSlashEqual: {"/=", symClassOperator, posInfix}, // 61: '/=' SymSlashEqual: {"/=", symClassOperator}, // 61: '/='
SymPercEqual: {"%=", symClassOperator, posInfix}, // 62: '%=' SymPercEqual: {"%=", symClassOperator}, // 62: '%='
SymDoubleLessEqual: {"<<=", symClassOperator, posInfix}, // 63: '<<='
SymDoubleGreaterEqual: {">>=", symClassOperator, posInfix}, // 64: '>>='
SymAmpersandEqual: {"&=", symClassOperator, posInfix}, // 65: '&='
SymVertBarEqual: {"|=", symClassOperator, posInfix}, // 65: '|='
SymCaretEqual: {"^=", symClassOperator, posInfix}, // 66: '^='
SymPlusGreater: {"+>", symClassOperator, posInfix}, // 67: '+>'
SymLessPlus: {"<+", symClassOperator, posInfix}, // 68: '<+'
SymPreInc: {"++", symClassOperator, posPrefix}, // : '++'
SymPreDec: {"--", symClassOperator, posPrefix}, // : '--'
// SymChangeSign // SymChangeSign
// SymUnchangeSign // SymUnchangeSign
// SymIdentifier // SymIdentifier
@ -131,17 +121,17 @@ func init() {
// // SymClosedComment // 0: '*/' // // SymClosedComment // 0: '*/'
// // SymOneLineComment // 0: '//' // // SymOneLineComment // 0: '//'
// keywordBase // keywordBase
SymKwAnd: {"and", symClassOperator, posInfix}, SymKwAnd: {"and", symClassOperator},
SymKwNot: {"not", symClassOperator, posInfix}, SymKwNot: {"not", symClassOperator},
SymKwOr: {"or", symClassOperator, posInfix}, SymKwOr: {"or", symClassOperator},
SymKwBut: {"but", symClassOperator, posInfix}, SymKwBut: {"but", symClassOperator},
SymKwFunc: {"func(", symClassDeclaration, posPrefix}, SymKwFunc: {"func(", symClassDeclaration},
SymKwBuiltin: {"builtin", symClassOperator, posPrefix}, SymKwBuiltin: {"builtin", symClassOperator},
SymKwPlugin: {"plugin", symClassOperator, posPrefix}, SymKwPlugin: {"plugin", symClassOperator},
SymKwIn: {"in", symClassOperator, posInfix}, SymKwIn: {"in", symClassOperator},
SymKwInclude: {"include", symClassOperator, posPrefix}, SymKwInclude: {"include", symClassOperator},
SymKwNil: {"nil", symClassValue, posLeaf}, SymKwNil: {"nil", symClassValue},
SymKwUnset: {"unset", symClassOperator, posPrefix}, SymKwUnset: {"unset", symClassOperator},
} }
} }
@ -179,19 +169,12 @@ func StringEndsWithOperator(s string) bool {
} }
func endingOperator(s string) (sym Symbol) { func endingOperator(s string) (sym Symbol) {
var matchLength = 0
sym = SymNone sym = SymNone
lower := strings.TrimRight(strings.ToLower(s), " \t") lower := strings.ToLower(s)
for symbol, spec := range symbolMap { for symbol, spec := range symbolMap {
if strings.HasSuffix(lower, spec.repr) { if spec.kind == symClassOperator && strings.HasSuffix(lower, spec.repr) {
if len(spec.repr) > matchLength { sym = symbol
matchLength = len(spec.repr) break
if spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix) {
sym = symbol
} else {
sym = SymNone
}
}
} }
} }
return return

138
symbol.go
View File

@ -7,82 +7,72 @@ package expr
type Symbol int16 type Symbol int16
const ( const (
SymUnknown Symbol = iota - 1 // -1: Unknown symbol SymUnknown Symbol = iota - 1 // -1: Unknown symbol
SymNone // 0: Null value for variable of type symbol SymNone // 0: Null value for variable of type symbol
SymError // 1: Error reading from stream SymError // 1: Error reading from stream
SymEos // 2: End of stream SymEos // 2: End of stream
SymMinus // 3: '-' SymMinus // 3: '-'
SymMinusEqual // 4: '-=' SymMinusEqual // 4: '-='
SymDoubleMinus // 5: '--' SymDoubleMinus // 5: '--'
SymPlus // 6: '+' SymPlus // 6: '+'
SymPlusEqual // 7: '+=' SymPlusEqual // 7: '+='
SymDoublePlus // 8: '++' SymDoublePlus // 8: '++'
SymStar // 9: '*' SymStar // 9: '*'
SymDoubleStar // 10: '**' SymDoubleStar // 10: '**'
SymSlash // 11: '/' SymSlash // 11: '/'
SymBackSlash // 12: '\' SymBackSlash // 12: '\'
SymVertBar // 13: '|' SymVertBar // 13: '|'
SymDoubleVertBar // 14: '||' SymDoubleVertBar // 14: '||'
SymComma // 15: ',' SymComma // 15: ','
SymColon // 16: ':' SymColon // 16: ':'
SymSemiColon // 17: ';' SymSemiColon // 17: ';'
SymDot // 18: '.' SymDot // 18: '.'
SymDotSlash // 19: './' SymDotSlash // 19: './'
SymQuote // 20: '\'' SymQuote // 20: '\''
SymDoubleQuote // 21: '"' SymDoubleQuote // 21: '"'
SymBackTick // 22: '`' SymBackTick // 22: '`'
SymExclamation // 23: '!' SymExclamation // 23: '!'
SymQuestion // 24: '?' SymQuestion // 24: '?'
SymAmpersand // 25: '&' SymAmpersand // 25: '&'
SymDoubleAmpersand // 26: '&&' SymDoubleAmpersand // 26: '&&'
SymPercent // 27: '%' SymPercent // 27: '%'
SymAt // 28: '@' SymAt // 28: '@'
SymUndescore // 29: '_' SymUndescore // 29: '_'
SymEqual // 30: '=' SymEqual // 30: '='
SymDoubleEqual // 31: '==' SymDoubleEqual // 31: '=='
SymLess // 32: '<' SymLess // 32: '<'
SymLessOrEqual // 33: '<=' SymLessOrEqual // 33: '<='
SymGreater // 34: '>' SymGreater // 34: '>'
SymGreaterOrEqual // 35: '>=' SymGreaterOrEqual // 35: '>='
SymLessGreater // 36: '<>' SymLessGreater // 36: '<>'
SymNotEqual // 37: '!=' SymNotEqual // 37: '!='
SymDollar // 38: '$' SymDollar // 38: '$'
SymHash // 39: '#' SymHash // 39: '#'
SymOpenRound // 40: '(' SymOpenRound // 40: '('
SymClosedRound // 41: ')' SymClosedRound // 41: ')'
SymOpenSquare // 42: '[' SymOpenSquare // 42: '['
SymClosedSquare // 43: ']' SymClosedSquare // 43: ']'
SymOpenBrace // 44: '{' SymOpenBrace // 44: '{'
SymClosedBrace // 45: '}' SymClosedBrace // 45: '}'
SymTilde // 46: '~' SymTilde // 46: '~'
SymDoubleQuestion // 47: '??' SymDoubleQuestion // 47: '??'
SymQuestionEqual // 48: '?=' SymQuestionEqual // 48: '?='
SymQuestionExclam // 49: '?!' SymQuestionExclam // 49: '?!'
SymDoubleAt // 50: '@@' SymDoubleAt // 50: '@@'
SymDoubleColon // 51: '::' SymDoubleColon // 51: '::'
SymDoubleGreater // 52: '>>' SymInsert // 52: '>>'
SymDoubleLess // 53: '<<' SymAppend // 53: '<<'
SymCaret // 54: '^' SymCaret // 54: '^'
SymDollarRound // 55: '$(' SymDollarRound // 55: '$('
SymOpenClosedRound // 56: '()' SymOpenClosedRound // 56: '()'
SymDoubleDollar // 57: '$$' SymDoubleDollar // 57: '$$'
SymDoubleDot // 58: '..' SymDoubleDot // 58: '..'
SymTripleDot // 59: '...' SymTripleDot // 59: '...'
SymStarEqual // 60: '*=' SymStarEqual // 60: '*='
SymSlashEqual // 61: '/=' SymSlashEqual // 61: '/='
SymPercEqual // 62: '%=' SymPercEqual // 62: '%='
SymDoubleLessEqual // 63: '<<='
SymDoubleGreaterEqual // 64: '>>='
SymAmpersandEqual // 65: '&='
SymVertBarEqual // 65: '|='
SymCaretEqual // 66: '^='
SymPlusGreater // 67: '+>'
SymLessPlus // 68: '<+'
SymChangeSign SymChangeSign
SymUnchangeSign SymUnchangeSign
SymDereference
SymPreInc
SymPreDec
SymIdentifier SymIdentifier
SymBool SymBool
SymInteger SymInteger

View File

@ -26,13 +26,12 @@ func TestBool(t *testing.T) {
/* 12 */ {`true or false`, true, nil}, /* 12 */ {`true or false`, true, nil},
/* 13 */ {`true or []`, true, nil}, /* 13 */ {`true or []`, true, nil},
/* 14 */ {`[] or false`, nil, errors.New(`got list as left operand type of 'OR' operator, it must be bool`)}, /* 14 */ {`[] or false`, nil, errors.New(`got list as left operand type of 'OR' operator, it must be bool`)},
/* 15 */ {`!true`, false, nil},
/* 13 */ //{`true or []`, nil, errors.New(`[1:8] left operand 'true' [bool] and right operand '[]' [list] are not compatible with operator "OR"`)}, /* 13 */ //{`true or []`, nil, errors.New(`[1:8] left operand 'true' [bool] and right operand '[]' [list] are not compatible with operator "OR"`)},
} }
// t.Setenv("EXPR_PATH", ".") // t.Setenv("EXPR_PATH", ".")
// runTestSuiteSpec(t, section, inputs, 15) // runTestSuiteSpec(t, section, inputs, 1)
runTestSuite(t, section, inputs) runTestSuite(t, section, inputs)
} }

View File

@ -29,9 +29,7 @@ func TestExpr(t *testing.T) {
/* 15 */ {`a=3; a*=2)+1; a`, nil, `[1:11] unexpected token ")"`}, /* 15 */ {`a=3; a*=2)+1; a`, nil, `[1:11] unexpected token ")"`},
/* 16 */ {`v=[2]; a=1; v[a-=1]=5; v[0]`, int64(5), nil}, /* 16 */ {`v=[2]; a=1; v[a-=1]=5; v[0]`, int64(5), nil},
/* 17 */ {`true ? {"a"} :: {"b"}`, "a", nil}, /* 17 */ {`true ? {"a"} :: {"b"}`, "a", nil},
/* 18 */ {`$$`, NewDict(map[any]any{"variables": NewDict(nil), "functions": NewDict(nil)}), nil}, /* 18 */ {`
///* 19 */ {`$$global`, NewDict(map[any]any{"variables": NewDict(nil), "functions": NewDict(nil)}), nil},
/* 19 */ {`
ds={ ds={
"init":func(@end){@current=0 but true}, "init":func(@end){@current=0 but true},
//"current":func(){current}, //"current":func(){current},
@ -46,6 +44,6 @@ func TestExpr(t *testing.T) {
} }
// t.Setenv("EXPR_PATH", ".") // t.Setenv("EXPR_PATH", ".")
// runTestSuiteSpec(t, section, inputs, 18) // runTestSuiteSpec(t, section, inputs, 6, 7, 8, 9)
runTestSuite(t, section, inputs) runTestSuite(t, section, inputs)
} }

View File

@ -25,7 +25,7 @@ func TestFractionsParser(t *testing.T) {
/* 12 */ {`builtin "math.arith"; add(1:2, 1.0, 2)`, float64(3.5), nil}, /* 12 */ {`builtin "math.arith"; add(1:2, 1.0, 2)`, float64(3.5), nil},
/* 13 */ {`builtin "math.arith"; mul(1:2, 2:3)`, newFraction(2, 6), nil}, /* 13 */ {`builtin "math.arith"; mul(1:2, 2:3)`, newFraction(2, 6), nil},
/* 14 */ {`builtin "math.arith"; mul(1:2, 1.0, 2)`, float64(1.0), nil}, /* 14 */ {`builtin "math.arith"; mul(1:2, 1.0, 2)`, float64(1.0), nil},
/* 15 */ {`1:0`, nil, `[1:3] division by zero`}, /* 15 */ {`1:0`, nil, `division by zero`},
/* 16 */ {`fract(-0.5)`, newFraction(-1, 2), nil}, /* 16 */ {`fract(-0.5)`, newFraction(-1, 2), nil},
/* 17 */ {`fract("")`, (*FractionType)(nil), `bad syntax`}, /* 17 */ {`fract("")`, (*FractionType)(nil), `bad syntax`},
/* 18 */ {`fract("-1")`, newFraction(-1, 1), nil}, /* 18 */ {`fract("-1")`, newFraction(-1, 1), nil},
@ -34,7 +34,7 @@ func TestFractionsParser(t *testing.T) {
/* 21 */ {`fract(1,0)`, nil, `fract(): division by zero`}, /* 21 */ {`fract(1,0)`, nil, `fract(): division by zero`},
/* 22 */ {`string(1:2)`, "1:2", nil}, /* 22 */ {`string(1:2)`, "1:2", nil},
/* 23 */ {`1+1:2+0.5`, float64(2), nil}, /* 23 */ {`1+1:2+0.5`, float64(2), nil},
/* 24 */ {`1:(2-2)`, nil, `[1:3] division by zero`}, /* 24 */ {`1:(2-2)`, nil, `division by zero`},
/* 25 */ {`[0,1][1-1]:1`, newFraction(0, 1), nil}, /* 25 */ {`[0,1][1-1]:1`, newFraction(0, 1), nil},
} }
// runTestSuiteSpec(t, section, inputs, 25) // runTestSuiteSpec(t, section, inputs, 25)

View File

@ -9,10 +9,10 @@ import "testing"
func TestIteratorParser(t *testing.T) { func TestIteratorParser(t *testing.T) {
section := "Iterator" section := "Iterator"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); *it`, int64(0), nil}, /* 1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); ^it`, int64(0), nil},
/* 2 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil}, /* 2 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil},
/* 3 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(3), nil}, /* 3 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(3), nil},
/* 4 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; it.reset; *it`, int64(0), nil}, /* 4 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; it.reset; ^it`, int64(0), nil},
/* 5 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil}, /* 5 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil},
/* 6 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil}, /* 6 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil},
/* 7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); mul(it)`, int64(12000), nil}, /* 7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); mul(it)`, int64(12000), nil},

View File

@ -23,8 +23,8 @@ func TestListParser(t *testing.T) {
/* 9 */ {`mul([1,4,3.0,2])`, float64(24.0), nil}, /* 9 */ {`mul([1,4,3.0,2])`, float64(24.0), nil},
/* 10 */ {`add([1,"hello"])`, nil, `add(): param nr 2 (2 in 1) has wrong type string, number expected`}, /* 10 */ {`add([1,"hello"])`, nil, `add(): param nr 2 (2 in 1) has wrong type string, number expected`},
/* 11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil}, /* 11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil},
/* 12 */ {`[1,2,3] <+ 2+2`, newListA(int64(1), int64(2), int64(3), int64(4)), nil}, /* 12 */ {`[1,2,3] << 2+2`, newListA(int64(1), int64(2), int64(3), int64(4)), nil},
/* 13 */ {`2-1 +> [2,3]`, newListA(int64(1), int64(2), int64(3)), nil}, /* 13 */ {`2-1 >> [2,3]`, newListA(int64(1), int64(2), int64(3)), nil},
/* 14 */ {`[1,2,3][1]`, int64(2), nil}, /* 14 */ {`[1,2,3][1]`, int64(2), nil},
/* 15 */ {`ls=[1,2,3] but ls[1]`, int64(2), nil}, /* 15 */ {`ls=[1,2,3] but ls[1]`, int64(2), nil},
/* 16 */ {`ls=[1,2,3] but ls[-1]`, int64(3), nil}, /* 16 */ {`ls=[1,2,3] but ls[-1]`, int64(3), nil},
@ -33,25 +33,25 @@ func TestListParser(t *testing.T) {
/* 19 */ {`["a", "b", "c"]`, newList([]any{"a", "b", "c"}), nil}, /* 19 */ {`["a", "b", "c"]`, newList([]any{"a", "b", "c"}), nil},
/* 20 */ {`#["a", "b", "c"]`, int64(3), nil}, /* 20 */ {`#["a", "b", "c"]`, int64(3), nil},
/* 21 */ {`"b" in ["a", "b", "c"]`, true, nil}, /* 21 */ {`"b" in ["a", "b", "c"]`, true, nil},
/* 22 */ {`a=[1,2]; (a)<+3`, newListA(int64(1), int64(2), int64(3)), nil}, /* 22 */ {`a=[1,2]; (a)<<3`, newListA(int64(1), int64(2), int64(3)), nil},
/* 23 */ {`a=[1,2]; (a)<+3; a`, newListA(int64(1), int64(2)), nil}, /* 23 */ {`a=[1,2]; (a)<<3; a`, newListA(int64(1), int64(2)), nil},
/* 24 */ {`["a","b","c","d"][1]`, "b", nil}, /* 24 */ {`["a","b","c","d"][1]`, "b", nil},
/* 25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`}, /* 25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`},
/* 26 */ {`[0,1,2,3,4][:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, /* 26 */ {`[0,1,2,3,4][:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
/* 27 */ {`["a", "b", "c"] <+ ;`, nil, `[1:18] infix operator "<+" requires two non-nil operands, got 1`}, /* 27 */ {`["a", "b", "c"] << ;`, nil, `[1:18] infix operator "<<" requires two non-nil operands, got 1`},
/* 28 */ {`2 << 3;`, int64(16), nil}, /* 28 */ {`2 << 3;`, int64(16), nil},
/* 29 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`}, /* 29 */ {`but >> ["a", "b", "c"]`, nil, `[1:6] infix operator ">>" requires two non-nil operands, got 0`},
/* 30 */ {`2 >> 3;`, int64(0), nil}, /* 30 */ {`2 >> 3;`, int64(0), nil},
/* 31 */ {`a=[1,2]; a<+3`, newListA(int64(1), int64(2), int64(3)), nil}, /* 31 */ {`a=[1,2]; a<<3`, newListA(int64(1), int64(2), int64(3)), nil},
/* 32 */ {`a=[1,2]; 5+>a`, newListA(int64(5), int64(1), int64(2)), nil}, /* 33 */ {`a=[1,2]; 5>>a`, newListA(int64(5), int64(1), int64(2)), nil},
/* 33 */ {`L=[1,2]; L[0]=9; L`, newListA(int64(9), int64(2)), nil}, /* 34 */ {`L=[1,2]; L[0]=9; L`, newListA(int64(9), int64(2)), nil},
/* 34 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`}, /* 35 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`},
/* 35 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [list]`}, /* 36 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [list]`},
/* 36 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`}, /* 37 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`},
/* 37 */ {`[0,1,2,3,4][2:3]`, newListA(int64(2)), nil}, /* 38 */ {`[0,1,2,3,4][2:3]`, newListA(int64(2)), nil},
/* 38 */ {`[0,1,2,3,4][3:-1]`, newListA(int64(3)), nil}, /* 39 */ {`[0,1,2,3,4][3:-1]`, newListA(int64(3)), nil},
/* 30 */ {`[0,1,2,3,4][-3:-1]`, newListA(int64(2), int64(3)), nil}, /* 40 */ {`[0,1,2,3,4][-3:-1]`, newListA(int64(2), int64(3)), nil},
/* 40 */ {`[0,1,2,3,4][0:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil}, /* 41 */ {`[0,1,2,3,4][0:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
} }
// t.Setenv("EXPR_PATH", ".") // t.Setenv("EXPR_PATH", ".")

View File

@ -14,29 +14,10 @@ func TestOperator(t *testing.T) {
/* 1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`}, /* 1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`},
/* 2 */ {`a=1; unset ["a", "b"]`, int64(1), nil}, /* 2 */ {`a=1; unset ["a", "b"]`, int64(1), nil},
/* 3 */ {`f=func(){3}; unset "f()"`, int64(1), nil}, /* 3 */ {`f=func(){3}; unset "f()"`, int64(1), nil},
/* 4 */ {`a=1; a<<=1+0`, int64(2), nil},
/* 5 */ {`a=2; a>>=1+0`, int64(1), nil},
/* 6 */ {`1<<1`, int64(2), nil},
/* 7 */ {`1>>1`, int64(0), nil},
/* 8 */ {`1|2`, int64(3), nil},
/* 9 */ {`a=1; a|=2`, int64(3), nil},
/* 10 */ {`3&1`, int64(1), nil},
/* 11 */ {`a=3; a&=1`, int64(1), nil},
/* 12 */ {`~1`, int64(-2), nil},
/* 13 */ {`0x10`, int64(16), nil},
/* 14 */ {`0x1X`, nil, `[1:5] two adjacent operators: "1" and "X"`},
/* 15 */ {`0o10`, int64(8), nil},
/* 16 */ {`0b10`, int64(2), nil},
/* 17 */ {`~true`, nil, `[1:2] prefix/postfix operator "~" do not support operand 'true' [bool]`},
/* 18 */ {`1^2`, int64(3), nil},
/* 19 */ {`3^2`, int64(1), nil},
/* 19 */ {`a=1; a^=2`, int64(3), nil},
/* 20 */ {`a=1; ++a`, int64(2), nil},
/* 21 */ {`a=1; --a`, int64(0), nil},
} }
// t.Setenv("EXPR_PATH", ".") // t.Setenv("EXPR_PATH", ".")
// runTestSuiteSpec(t, section, inputs, 4) //runTestSuiteSpec(t, section, inputs, 3)
runTestSuite(t, section, inputs) runTestSuite(t, section, inputs)
} }

View File

@ -78,8 +78,8 @@ func TestGeneralParser(t *testing.T) {
/* 64 */ {`"1.5" != `, nil, `[1:8] infix operator "!=" requires two non-nil operands, got 1`}, /* 64 */ {`"1.5" != `, nil, `[1:8] infix operator "!=" requires two non-nil operands, got 1`},
/* 65 */ {"+1.5", float64(1.5), nil}, /* 65 */ {"+1.5", float64(1.5), nil},
/* 66 */ {"+", nil, `[1:2] prefix operator "+" requires one non-nil operand`}, /* 66 */ {"+", nil, `[1:2] prefix operator "+" requires one non-nil operand`},
/* 67 */ {"4 / 0", nil, `[1:4] division by zero`}, /* 67 */ {"4 / 0", nil, `division by zero`},
/* 68 */ {"4.0 / 0", nil, `[1:6] division by zero`}, /* 68 */ {"4.0 / 0", nil, `division by zero`},
/* 69 */ {"4.0 / \n2", float64(2.0), nil}, /* 69 */ {"4.0 / \n2", float64(2.0), nil},
/* 70 */ {`123`, int64(123), nil}, /* 70 */ {`123`, int64(123), nil},
/* 71 */ {`1.`, float64(1.0), nil}, /* 71 */ {`1.`, float64(1.0), nil},
@ -142,6 +142,6 @@ func TestGeneralParser(t *testing.T) {
} }
// t.Setenv("EXPR_PATH", ".") // t.Setenv("EXPR_PATH", ".")
// runTestSuiteSpec(t, section, inputs, 114) //runTestSuiteSpec(t, section, inputs, 130)
runTestSuite(t, section, inputs) runTestSuite(t, section, inputs)
} }

View File

@ -9,7 +9,6 @@ import (
) )
func TestStringsParser(t *testing.T) { func TestStringsParser(t *testing.T) {
section := "String"
inputs := []inputType{ inputs := []inputType{
/* 1 */ {`"uno" + "due"`, `unodue`, nil}, /* 1 */ {`"uno" + "due"`, `unodue`, nil},
/* 2 */ {`"uno" + 2`, `uno2`, nil}, /* 2 */ {`"uno" + 2`, `uno2`, nil},
@ -17,12 +16,6 @@ func TestStringsParser(t *testing.T) {
/* 4 */ {`"uno" * (2+1)`, `unounouno`, nil}, /* 4 */ {`"uno" * (2+1)`, `unounouno`, nil},
/* 5 */ {`"abc"[1]`, `b`, nil}, /* 5 */ {`"abc"[1]`, `b`, nil},
/* 6 */ {`#"abc"`, int64(3), nil}, /* 6 */ {`#"abc"`, int64(3), nil},
/* 7 */ {`"192.168.0.240" / "."`, newListA("192", "168", "0", "240"), nil},
/* 8 */ {`("192.168.0.240" / ".")[1]`, "168", nil},
/* 9 */ {`"AF3B0Dz" / 2`, newListA("AF", "3B", "0D", "z"), nil},
/* 10 */ {`"AF3B0Dz" / 0`, nil, "[1:12] division by zero"},
} }
runTestSuite(t, "String", inputs)
// runTestSuiteSpec(t, section, inputs, 8)
runTestSuite(t, section, inputs)
} }

11
term.go
View File

@ -15,26 +15,21 @@ const (
priRange priRange
priBut priBut
priAssign priAssign
priInsert
priOr priOr
priAnd priAnd
priNot priNot
priRelational priRelational
priBitwiseOr priBinary
priBitwiseAnd
priBitwiseNot
priSum priSum
priProduct priProduct
priFraction priFraction
priSelector priSelector
priBinShift
priSign priSign
priFact priFact
priIterValue priIterValue
priDefault priDefault
priIncDec priIncDec
priDot priDot
priDereference
priValue priValue
) )
@ -204,10 +199,6 @@ func (term *term) errIncompatibleType(value any) error {
term.source(), value, TypeName(value)) term.source(), value, TypeName(value))
} }
func (term *term) errDivisionByZero() error {
return term.tk.Errorf("division by zero")
}
func (term *term) Errorf(template string, args ...any) (err error) { func (term *term) Errorf(template string, args ...any) (err error) {
err = term.tk.Errorf(template, args...) err = term.tk.Errorf(template, args...)
return return

View File

@ -79,10 +79,6 @@ func (tk *Token) IsSymbol(sym Symbol) bool {
return tk.Sym == sym return tk.Sym == sym
} }
func (tk *Token) SetSymbol(sym Symbol) {
tk.Sym = sym
}
func (tk *Token) Errorf(template string, args ...any) (err error) { func (tk *Token) Errorf(template string, args ...any) (err error) {
err = fmt.Errorf(fmt.Sprintf("[%d:%d] ", tk.row, tk.col)+template, args...) err = fmt.Errorf(fmt.Sprintf("[%d:%d] ", tk.row, tk.col)+template, args...)
return return