Compare commits
17 Commits
Author | SHA1 | Date | |
---|---|---|---|
5ecf81412e | |||
ff4db34f7b | |||
0f848071c2 | |||
6b3351b324 | |||
760c1ee6da | |||
5ab6876ea1 | |||
6268abda8c | |||
d25bd325b7 | |||
01c04feea5 | |||
6fc689c46c | |||
eccb0c4dc9 | |||
e43823740f | |||
526982a564 | |||
252514943e | |||
32686fac62 | |||
52a627c747 | |||
d91e7eb979 |
@ -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 wi a call to NewDict()
|
// TODO Change with 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))
|
||||||
|
@ -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,14 +735,17 @@ 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="^2,^2,^2,^5,^6"]
|
[cols="^3,^2,^2,^5,^6"]
|
||||||
|===
|
|===
|
||||||
| Priority | Operators | Position | Operation | Operands and results
|
| Priority | Operator | 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_
|
||||||
.2+|*INC*| [blue]`++` | _Postfix_ | _Post increment_| _integer-variable_ `++` -> _integer_
|
.5+|*INC/DEC*| [blue]`++` | _Postfix_ | _Iterator next item_ | _iterator_ `++` -> _any_
|
||||||
| [blue]`++` | _Postfix_ | _Next item_ | _iterator_ `++` -> _any_
|
| [blue]`++` | _Postfix_ | _Post increment_| _integer-variable_ `++` -> _integer_
|
||||||
|
| [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_
|
||||||
@ -751,13 +754,17 @@ 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_
|
||||||
.5+|*PROD*| [blue]`*` | _Infix_ | _Product_ | _number_ `*` _number_ -> _number_
|
.7+|*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_
|
||||||
@ -765,9 +772,10 @@ 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_
|
||||||
.3+|*BINARY*| [blue]`&` | _Infix_ | _Binary And_ | _number_ `&` _number_ -> _number_
|
.1+|*BITWISE NOT*| [blue]`~` | _Prefix_ | _Binary Not_ | `~` _integer_ -> _integer_
|
||||||
| [blue]`\|` | _Infix_ | _Binary Or_ | _number_ `\|` _number_ -> _number_
|
.1+|*BITWISE AND*| [blue]`&` | _Infix_ | _Binary And_ | _integer_ `&` _integer_ -> _integer_
|
||||||
| [blue]`~` | _Prefix_ | _Binary Not_ | `~` _number_ -> _number_
|
.2+|*BITWISE OR*| [blue]`\|` | _Infix_ | _Binary Or_ | _integer_ `\|` _integer_ -> _integer_
|
||||||
|
| [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_
|
||||||
@ -776,20 +784,54 @@ 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+|*NOT*| [blue]`not` | _Prefix_ | _Not_ | `not` _boolean_ -> _boolean_
|
.1+|*LOGIC NOT*| [blue]`not` | _Prefix_ | _Not_ | `not` _boolean_ -> _boolean_
|
||||||
.2+|*AND*| [blue]`and` | _Infix_ | _And_ | _boolean_ `and` _boolean_ -> _boolean_
|
.2+|*LOGIC AND*| [blue]`and` | _Infix_ | _And_ | _boolean_ `and` _boolean_ -> _boolean_
|
||||||
| [blue]`&&` | _Infix_ | _And_ | _boolean_ `&&` _boolean_ -> _boolean_
|
| [blue]`&&` | _Infix_ | _And_ | _boolean_ `&&` _boolean_ -> _boolean_
|
||||||
.2+|*OR*| [blue]`or` | _Infix_ | _Or_ | _boolean_ `or` _boolean_ -> _boolean_
|
.2+|*LOGIC OR*| [blue]`or` | _Infix_ | _Or_ | _boolean_ `or` _boolean_ -> _boolean_
|
||||||
| [blue]`\|\|` | _Infix_ | _Or_ | _boolean_ `\|\|` _boolean_ -> _boolean_
|
| [blue]`\|\|` | _Infix_ | _Or_ | _boolean_ `\|\|` _boolean_ -> _boolean_
|
||||||
.3+|*ASSIGN*| [blue]`=` | _Infix_ | _Assignment_ | _identifier_ `=` _any_ -> _any_
|
.2+|*INSERT*| [blue]`+>` | _Infix_ | _Prepend_ | _any_ `+>` _list_ -> _list_
|
||||||
| [blue]`>>` | _Infix_ | _Front-insert_ | _any_ `>>` _list_ -> _list_
|
| [blue]`<+` | _Infix_ | _Append_ | _list_ `<+` _any_ -> _list_
|
||||||
| [blue]`<<` | _Infix_ | _Back-insert_ | _list_ `<<` _any_ -> _list_
|
.2+|*ASSIGN*| [blue]`=` | _Infix_ | _Assignment_ | _identifier_ `=` _any_ -> _any_
|
||||||
|
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_.
|
||||||
@ -840,7 +882,7 @@ _param-name_ = _identifier_
|
|||||||
|
|
||||||
|
|
||||||
=== _Golang_ function definition
|
=== _Golang_ function definition
|
||||||
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.
|
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.
|
||||||
|
|
||||||
=== 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.
|
||||||
|
226
doc/Expr.html
226
doc/Expr.html
@ -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> → <em>[1,3]</em></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2,3] - [2]</code> → <em>[1,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>
|
||||||
<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 >> [1,2]</code> → <em>[0,1,2]</em></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">0 +> [1,2]</code> → <em>[0,1,2]</em></p></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><<</code></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><+</code></p></td>
|
||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>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] << 3</code> → <em>[1,2,3]</em></p></td>
|
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2] <+ 3</code> → <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: 11.7647%;">
|
<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: 29.4117%;">
|
<col style="width: 27.7777%;">
|
||||||
<col style="width: 35.2942%;">
|
<col style="width: 33.3335%;">
|
||||||
</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">Operators</th>
|
<th class="tableblock halign-center valign-top">Operator</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,7 +1930,13 @@ 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> → <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> → <em>any</em></p></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>INC</strong></p></td>
|
<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"><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> → <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>
|
||||||
@ -1938,9 +1944,21 @@ 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> → <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>Next item</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>iterator</em> <code>++</code> → <em>any</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer-variable</em> <code>--</code> → <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>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> → <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>
|
||||||
@ -1988,6 +2006,19 @@ 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> → <em>integer</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>#</code> <em>iterator</em> → <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"><<</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><<</code> <em>integer</em> → <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>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>>></code> <em>iterator</em> → <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>
|
||||||
@ -2008,7 +2039,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> → <em>fraction</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>:</code> <em>integer</em> → <em>fraction</em></p></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-center valign-top" rowspan="5"><p class="tableblock"><strong>PROD</strong></p></td>
|
<td class="tableblock halign-center valign-top" rowspan="7"><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>
|
||||||
@ -2033,6 +2064,18 @@ 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> → <em>float</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>./</code> <em>number</em> → <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> → <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 → <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>
|
||||||
@ -2076,23 +2119,31 @@ 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> → <em>list</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code>-</code> <em>list</em> → <em>list</em></p></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<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"><strong>BITWISE NOT</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>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>number</em> <code>&</code> <em>number</em> → <em>number</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>Binary Or</em></p></td>
|
|
||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>|</code> <em>number</em> → <em>number</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>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>Binary Not</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>number</em> → <em>number</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>~</code> <em>integer</em> → <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">&</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>Binary And</em></p></td>
|
||||||
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>&</code> <em>integer</em> → <em>integer</em></p></td>
|
||||||
|
</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"><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>integer</em> <code>|</code> <em>integer</em> → <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>Infix</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>integer</em> <code>^</code> <em>integer</em> → <em>integer</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>
|
||||||
@ -2144,14 +2195,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> → <em>boolean</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>in</code> <em>dict</em> → <em>boolean</em></p></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<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"><strong>LOGIC 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> → <em>boolean</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>not</code> <em>boolean</em> → <em>boolean</em></p></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>AND</strong></p></td>
|
<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"><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>
|
||||||
@ -2164,7 +2215,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>&&</code> <em>boolean</em> → <em>boolean</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>&&</code> <em>boolean</em> → <em>boolean</em></p></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>OR</strong></p></td>
|
<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"><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>
|
||||||
@ -2177,23 +2228,27 @@ 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> → <em>boolean</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>||</code> <em>boolean</em> → <em>boolean</em></p></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>ASSIGN</strong></p></td>
|
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>INSERT</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>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>+></code> <em>list</em> → <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>Append</em></p></td>
|
||||||
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code><+</code> <em>any</em> → <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> → <em>any</em></p></td>
|
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>identifier</em> <code>=</code> <em>any</em> → <em>any</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" 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"><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>>></code> <em>list</em> → <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>Back-insert</em></p></td>
|
|
||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code><<</code> <em>any</em> → <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>
|
||||||
@ -2211,6 +2266,89 @@ 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 & 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 & 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 & 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 & 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 & 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>Bitwise and & 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>Bitwise or & 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>Left shift & 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>Right shift & 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>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sect1">
|
<div class="sect1">
|
||||||
@ -2282,7 +2420,7 @@ These operators have a high priority, in particular higher than the operator <co
|
|||||||
<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 Golan functions and how to bind them to <em>Expr</em> are topics treated in another document that I’ll write, one day, maybe.</p>
|
<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’ll write, one day, maybe.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sect2">
|
<div class="sect2">
|
||||||
@ -2461,7 +2599,7 @@ g(@p):any{}`
|
|||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div id="footer-text">
|
<div id="footer-text">
|
||||||
Last updated 2024-12-23 07:20:48 +0100
|
Last updated 2025-01-05 12:15:58 +0100
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -183,6 +183,16 @@ 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())
|
||||||
}
|
}
|
||||||
@ -201,4 +211,10 @@ 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)
|
||||||
}
|
}
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
// 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)
|
|
||||||
}
|
|
154
operator-bitwise.go
Normal file
154
operator-bitwise.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
@ -7,7 +7,6 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -41,7 +40,7 @@ func evalFraction(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if den == 0 {
|
if den == 0 {
|
||||||
err = errors.New("division by zero")
|
err = opTerm.errDivisionByZero()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,15 +4,15 @@
|
|||||||
// operator-insert.go
|
// operator-insert.go
|
||||||
package expr
|
package expr
|
||||||
|
|
||||||
//-------- insert term
|
//-------- prepend term
|
||||||
|
|
||||||
func newInsertTerm(tk *Token) (inst *term) {
|
func newPrependTerm(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: priAssign,
|
priority: priInsert,
|
||||||
evalFunc: evalInsert,
|
evalFunc: evalPrepend,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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: priAssign,
|
priority: priInsert,
|
||||||
evalFunc: evalAppend,
|
evalFunc: evalAppend,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalInsert(ctx ExprContext, opTerm *term) (v any, err error) {
|
func evalPrepend(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,10 +40,6 @@ func evalInsert(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)
|
||||||
}
|
}
|
||||||
@ -64,10 +60,6 @@ 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)
|
||||||
}
|
}
|
||||||
@ -94,6 +86,6 @@ func evalAppend(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
|
|
||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
registerTermConstructor(SymInsert, newInsertTerm)
|
registerTermConstructor(SymPlusGreater, newPrependTerm)
|
||||||
registerTermConstructor(SymAppend, newAppendTerm)
|
registerTermConstructor(SymLessPlus, newAppendTerm)
|
||||||
}
|
}
|
||||||
|
@ -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: priIterValue,
|
priority: priDereference,
|
||||||
evalFunc: evalIterValue,
|
evalFunc: evalIterValue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,5 +34,5 @@ func evalIterValue(ctx ExprContext, opTerm *term) (v any, err error) {
|
|||||||
// init
|
// init
|
||||||
func init() {
|
func init() {
|
||||||
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
|
// registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
|
||||||
registerTermConstructor(SymCaret, newIterValueTerm)
|
registerTermConstructor(SymDereference, newIterValueTerm)
|
||||||
}
|
}
|
||||||
|
@ -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.go
|
// operator-post-inc-dec.go
|
||||||
package expr
|
package expr
|
||||||
|
|
||||||
// -------- post increment term
|
// -------- post increment term
|
69
operator-pre-inc-dec.go
Normal file
69
operator-pre-inc-dec.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
@ -5,7 +5,6 @@
|
|||||||
package expr
|
package expr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,7 +68,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 = errors.New("division by zero")
|
err = opTerm.errDivisionByZero()
|
||||||
} else {
|
} else {
|
||||||
v = numAsFloat(leftValue) / d
|
v = numAsFloat(leftValue) / d
|
||||||
}
|
}
|
||||||
@ -78,11 +77,36 @@ 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 = errors.New("division by zero")
|
err = opTerm.errDivisionByZero()
|
||||||
} 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)
|
||||||
}
|
}
|
||||||
@ -121,7 +145,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 = errors.New("division by zero")
|
err = floatDivTerm.errDivisionByZero()
|
||||||
} else {
|
} else {
|
||||||
v = numAsFloat(leftValue) / d
|
v = numAsFloat(leftValue) / d
|
||||||
}
|
}
|
||||||
@ -146,7 +170,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 = errors.New("division by zero")
|
err = opTerm.errDivisionByZero()
|
||||||
} else {
|
} else {
|
||||||
leftInt, _ := leftValue.(int64)
|
leftInt, _ := leftValue.(int64)
|
||||||
v = leftInt % rightInt
|
v = leftInt % rightInt
|
||||||
|
77
operator-shift.go
Normal file
77
operator-shift.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
51
parser.go
51
parser.go
@ -409,6 +409,23 @@ 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
|
||||||
@ -437,14 +454,16 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
|||||||
|
|
||||||
//fmt.Println("Token:", tk)
|
//fmt.Println("Token:", tk)
|
||||||
if firstToken {
|
if firstToken {
|
||||||
if tk.Sym == SymMinus {
|
changePrefix(tk)
|
||||||
tk.Sym = SymChangeSign
|
// if tk.Sym == SymMinus {
|
||||||
} else if tk.Sym == SymPlus {
|
// tk.Sym = SymChangeSign
|
||||||
tk.Sym = SymUnchangeSign
|
// } else if tk.Sym == SymPlus {
|
||||||
} else if tk.IsSymbol(SymExclamation) {
|
// tk.Sym = SymUnchangeSign
|
||||||
err = tk.Errorf("postfix opertor %q requires an operand on its left", tk)
|
// } else if tk.IsSymbol(SymStar) {
|
||||||
break
|
// tk.SetSymbol(SymDereference)
|
||||||
}
|
// } else if tk.IsSymbol(SymExclamation) {
|
||||||
|
// tk.SetSymbol(SymNot)
|
||||||
|
// }
|
||||||
firstToken = false
|
firstToken = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,9 +471,12 @@ 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 {
|
||||||
subTree.root.priority = priValue
|
exprTerm := newExprTerm(subTree.root)
|
||||||
err = tree.addTerm(newExprTerm(subTree.root))
|
err = tree.addTerm(exprTerm)
|
||||||
currentTerm = subTree.root
|
currentTerm = exprTerm
|
||||||
|
// subTree.root.priority = priValue
|
||||||
|
// err = tree.addTerm(newExprTerm(subTree.root))
|
||||||
|
// currentTerm = subTree.root
|
||||||
}
|
}
|
||||||
case SymFuncCall:
|
case SymFuncCall:
|
||||||
var funcCallTerm *term
|
var funcCallTerm *term
|
||||||
@ -478,7 +500,7 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
|||||||
currentTerm = mapTerm
|
currentTerm = mapTerm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual:
|
case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual, SymAmpersandEqual, SymVertBarEqual, SymDoubleLessEqual, SymDoubleGreaterEqual, SymCaretEqual:
|
||||||
currentTerm, err = tree.addToken(tk)
|
currentTerm, err = tree.addToken(tk)
|
||||||
firstToken = true
|
firstToken = true
|
||||||
case SymFuncDef:
|
case SymFuncDef:
|
||||||
@ -515,15 +537,12 @@ 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) {
|
if tk.IsOneOfA(SymColon, SymRange) {
|
||||||
// Colon outside a selector term acts like a separator
|
// Colon outside a selector term acts like a separator
|
||||||
firstToken = true
|
firstToken = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
currentTerm, err = tree.addToken(tk)
|
currentTerm, err = tree.addToken(tk)
|
||||||
}
|
}
|
||||||
|
43
scanner.go
43
scanner.go
@ -124,6 +124,8 @@ 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)
|
||||||
}
|
}
|
||||||
@ -167,13 +169,19 @@ 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.moveOn(SymCaretEqual, ch, next)
|
||||||
|
} else {
|
||||||
tk = scanner.makeToken(SymCaret, ch)
|
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)
|
||||||
@ -232,11 +240,17 @@ 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.moveOn(SymPercEqual, ch, next)
|
||||||
|
} else {
|
||||||
tk = scanner.makeToken(SymPercent, ch)
|
tk = scanner.makeToken(SymPercent, ch)
|
||||||
|
}
|
||||||
case '#':
|
case '#':
|
||||||
tk = scanner.makeToken(SymHash, ch)
|
tk = scanner.makeToken(SymHash, ch)
|
||||||
case '@':
|
case '@':
|
||||||
@ -265,9 +279,18 @@ 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 == '<' {
|
||||||
tk = scanner.moveOn(SymAppend, ch, next)
|
scanner.readChar()
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
@ -275,7 +298,14 @@ 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 == '>' {
|
||||||
tk = scanner.moveOn(SymInsert, ch, next)
|
scanner.readChar()
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
@ -630,9 +660,16 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
175
symbol-map.go
175
symbol-map.go
@ -14,7 +14,7 @@ type symbolClass int16
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
symClassOperator symbolClass = iota
|
symClassOperator symbolClass = iota
|
||||||
symClassPostOp
|
symClassCommand
|
||||||
symClassIdentifier
|
symClassIdentifier
|
||||||
symClassDelimiter
|
symClassDelimiter
|
||||||
symClassParenthesis
|
symClassParenthesis
|
||||||
@ -26,75 +26,85 @@ 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}, // -1: Unknown symbol
|
SymUnknown: {"<unknown>", symClassOther, posLeaf}, // -1: Unknown symbol
|
||||||
SymNone: {"<null>", symClassOther}, // 0: Null value for variable of type symbol
|
SymNone: {"<null>", symClassOther, posLeaf}, // 0: Null value for variable of type symbol
|
||||||
SymError: {"<error>", symClassOther}, // 1: Error reading from stream
|
SymError: {"<error>", symClassOther, posLeaf}, // 1: Error reading from stream
|
||||||
SymEos: {"<eos>", symClassOther}, // 2: End of stream
|
SymEos: {"<eos>", symClassOther, posLeaf}, // 2: End of stream
|
||||||
SymMinus: {"-", symClassOperator}, // 3: '-'
|
SymMinus: {"-", symClassOperator, posInfix}, // 3: '-'
|
||||||
SymMinusEqual: {"-=", symClassOperator}, // 4: '-='
|
SymMinusEqual: {"-=", symClassOperator, posInfix}, // 4: '-='
|
||||||
SymDoubleMinus: {"--", symClassOperator}, // 5: '--'
|
SymDoubleMinus: {"--", symClassOperator, posPostfix}, // 5: '--'
|
||||||
SymPlus: {"+", symClassOperator}, // 6: '+'
|
SymPlus: {"+", symClassOperator, posInfix}, // 6: '+'
|
||||||
SymPlusEqual: {"+=", symClassOperator}, // 7: '+='
|
SymPlusEqual: {"+=", symClassOperator, posInfix}, // 7: '+='
|
||||||
SymDoublePlus: {"++", symClassOperator}, // 8: '++'
|
SymDoublePlus: {"++", symClassOperator, posPostfix}, // 8: '++'
|
||||||
SymStar: {"*", symClassOperator}, // 9: '*'
|
SymStar: {"*", symClassOperator, posInfix}, // 9: '*'
|
||||||
SymDoubleStar: {"**", symClassOperator}, // 10: '**'
|
SymDoubleStar: {"**", symClassOperator, posInfix}, // 10: '**'
|
||||||
SymSlash: {"/", symClassOperator}, // 11: '/'
|
SymSlash: {"/", symClassOperator, posInfix}, // 11: '/'
|
||||||
SymBackSlash: {"\\", symClassOperator}, // 12: '\'
|
SymBackSlash: {"\\", symClassOperator, posLeaf}, // 12: '\'
|
||||||
SymVertBar: {"|", symClassOperator}, // 13: '|'
|
SymVertBar: {"|", symClassOperator, posInfix}, // 13: '|'
|
||||||
SymDoubleVertBar: {"||", symClassOperator}, // 14: '||'
|
SymDoubleVertBar: {"||", symClassOperator, posInfix}, // 14: '||'
|
||||||
SymComma: {",", symClassOperator}, // 15: ','
|
SymComma: {",", symClassOperator, posInfix}, // 15: ','
|
||||||
SymColon: {":", symClassOperator}, // 16: ':'
|
SymColon: {":", symClassOperator, posInfix}, // 16: ':'
|
||||||
SymSemiColon: {";", symClassOperator}, // 17: ';'
|
SymSemiColon: {";", symClassOperator, posInfix}, // 17: ';'
|
||||||
SymDot: {".", symClassOperator}, // 18: '.'
|
SymDot: {".", symClassOperator, posInfix}, // 18: '.'
|
||||||
SymDotSlash: {"./", symClassOperator}, // 19: './'
|
SymDotSlash: {"./", symClassOperator, posInfix}, // 19: './'
|
||||||
SymQuote: {"'", symClassDelimiter}, // 20: '\''
|
SymQuote: {"'", symClassDelimiter, posLeaf}, // 20: '\''
|
||||||
SymDoubleQuote: {"\"", symClassDelimiter}, // 21: '"'
|
SymDoubleQuote: {"\"", symClassDelimiter, posLeaf}, // 21: '"'
|
||||||
SymBackTick: {"`", symClassOperator}, // 22: '`'
|
SymBackTick: {"`", symClassDelimiter, posLeaf}, // 22: '`'
|
||||||
SymExclamation: {"!", symClassPostOp}, // 23: '!'
|
SymExclamation: {"!", symClassOperator, posPostfix}, // 23: '!'
|
||||||
SymQuestion: {"?", symClassOperator}, // 24: '?'
|
SymQuestion: {"?", symClassOperator, posInfix}, // 24: '?'
|
||||||
SymAmpersand: {"&", symClassOperator}, // 25: '&'
|
SymAmpersand: {"&", symClassOperator, posInfix}, // 25: '&'
|
||||||
SymDoubleAmpersand: {"&&", symClassOperator}, // 26: '&&'
|
SymDoubleAmpersand: {"&&", symClassOperator, posInfix}, // 26: '&&'
|
||||||
SymPercent: {"%", symClassOperator}, // 27: '%'
|
SymPercent: {"%", symClassOperator, posInfix}, // 27: '%'
|
||||||
SymAt: {"@", symClassOperator}, // 28: '@'
|
SymAt: {"@", symClassOperator, posPrefix}, // 28: '@'
|
||||||
SymUndescore: {"_", symClassOperator}, // 29: '_'
|
SymUndescore: {"_", symClassIdentifier, posLeaf}, // 29: '_'
|
||||||
SymEqual: {"=", symClassOperator}, // 30: '='
|
SymEqual: {"=", symClassOperator, posInfix}, // 30: '='
|
||||||
SymDoubleEqual: {"==", symClassOperator}, // 31: '=='
|
SymDoubleEqual: {"==", symClassOperator, posInfix}, // 31: '=='
|
||||||
SymLess: {"<", symClassOperator}, // 32: '<'
|
SymLess: {"<", symClassOperator, posInfix}, // 32: '<'
|
||||||
SymLessOrEqual: {"<=", symClassOperator}, // 33: '<='
|
SymLessOrEqual: {"<=", symClassOperator, posInfix}, // 33: '<='
|
||||||
SymGreater: {">", symClassOperator}, // 34: '>'
|
SymGreater: {">", symClassOperator, posInfix}, // 34: '>'
|
||||||
SymGreaterOrEqual: {">=", symClassOperator}, // 35: '>='
|
SymGreaterOrEqual: {">=", symClassOperator, posInfix}, // 35: '>='
|
||||||
SymLessGreater: {"<>", symClassOperator}, // 36: '<>'
|
SymLessGreater: {"<>", symClassOperator, posInfix}, // 36: '<>'
|
||||||
SymNotEqual: {"!=", symClassOperator}, // 37: '!='
|
SymNotEqual: {"!=", symClassOperator, posInfix}, // 37: '!='
|
||||||
SymDollar: {"$", symClassOperator}, // 38: '$'
|
SymDollar: {"$", symClassOperator, posPrefix}, // 38: '$'
|
||||||
SymHash: {"#", symClassOperator}, // 39: '#'
|
SymHash: {"#", symClassOperator, posPrefix}, // 39: '#'
|
||||||
SymOpenRound: {"(", symClassParenthesis}, // 40: '('
|
SymOpenRound: {"(", symClassParenthesis, posPrefix}, // 40: '('
|
||||||
SymClosedRound: {")", symClassParenthesis}, // 41: ')'
|
SymClosedRound: {")", symClassParenthesis, posPostfix}, // 41: ')'
|
||||||
SymOpenSquare: {"[", symClassParenthesis}, // 42: '['
|
SymOpenSquare: {"[", symClassParenthesis, posPrefix}, // 42: '['
|
||||||
SymClosedSquare: {"]", symClassParenthesis}, // 43: ']'
|
SymClosedSquare: {"]", symClassParenthesis, posPostfix}, // 43: ']'
|
||||||
SymOpenBrace: {"{", symClassParenthesis}, // 44: '{'
|
SymOpenBrace: {"{", symClassParenthesis, posPrefix}, // 44: '{'
|
||||||
SymClosedBrace: {"}", symClassParenthesis}, // 45: '}'
|
SymClosedBrace: {"}", symClassParenthesis, posPostfix}, // 45: '}'
|
||||||
SymTilde: {"~", symClassOperator}, // 46: '~'
|
SymTilde: {"~", symClassOperator, posPrefix}, // 46: '~'
|
||||||
SymDoubleQuestion: {"??", symClassOperator}, // 47: '??'
|
SymDoubleQuestion: {"??", symClassOperator, posInfix}, // 47: '??'
|
||||||
SymQuestionEqual: {"?=", symClassOperator}, // 48: '?='
|
SymQuestionEqual: {"?=", symClassOperator, posInfix}, // 48: '?='
|
||||||
SymQuestionExclam: {"?!", symClassOperator}, // 49: '?!'
|
SymQuestionExclam: {"?!", symClassOperator, posInfix}, // 49: '?!'
|
||||||
SymDoubleAt: {"@@", symClassOperator}, // 50: '@@'
|
SymDoubleAt: {"@@", symClassCommand, posLeaf}, // 50: '@@'
|
||||||
SymDoubleColon: {"::", symClassOperator}, // 51: '::'
|
SymDoubleColon: {"::", symClassOperator, posInfix}, // 51: '::'
|
||||||
SymInsert: {">>", symClassOperator}, // 52: '>>'
|
SymDoubleGreater: {">>", symClassOperator, posInfix}, // 52: '>>'
|
||||||
SymAppend: {"<<", symClassOperator}, // 53: '<<'
|
SymDoubleLess: {"<<", symClassOperator, posInfix}, // 53: '<<'
|
||||||
SymCaret: {"^", symClassOperator}, // 54: '^'
|
SymCaret: {"^", symClassOperator, posInfix}, // 54: '^'
|
||||||
SymDollarRound: {"$(", symClassOperator}, // 55: '$('
|
SymDollarRound: {"$(", symClassOperator, posPrefix}, // 55: '$('
|
||||||
SymOpenClosedRound: {"()", symClassPostOp}, // 56: '()'
|
SymOpenClosedRound: {"()", symClassOperator, posPostfix}, // 56: '()'
|
||||||
SymDoubleDollar: {"$$", symClassOperator}, // 57: '$$'
|
SymDoubleDollar: {"$$", symClassCommand, posLeaf}, // 57: '$$'
|
||||||
SymDoubleDot: {"..", symClassOperator}, // 58: '..'
|
SymDoubleDot: {"..", symClassOperator, posInfix}, // 58: '..'
|
||||||
SymTripleDot: {"...", symClassOperator}, // 59: '...'
|
SymTripleDot: {"...", symClassOperator, posPostfix}, // 59: '...'
|
||||||
SymStarEqual: {"*=", symClassOperator}, // 60: '*='
|
SymStarEqual: {"*=", symClassOperator, posInfix}, // 60: '*='
|
||||||
SymSlashEqual: {"/=", symClassOperator}, // 61: '/='
|
SymSlashEqual: {"/=", symClassOperator, posInfix}, // 61: '/='
|
||||||
SymPercEqual: {"%=", symClassOperator}, // 62: '%='
|
SymPercEqual: {"%=", symClassOperator, posInfix}, // 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
|
||||||
@ -121,17 +131,17 @@ func init() {
|
|||||||
// // SymClosedComment // 0: '*/'
|
// // SymClosedComment // 0: '*/'
|
||||||
// // SymOneLineComment // 0: '//'
|
// // SymOneLineComment // 0: '//'
|
||||||
// keywordBase
|
// keywordBase
|
||||||
SymKwAnd: {"and", symClassOperator},
|
SymKwAnd: {"and", symClassOperator, posInfix},
|
||||||
SymKwNot: {"not", symClassOperator},
|
SymKwNot: {"not", symClassOperator, posInfix},
|
||||||
SymKwOr: {"or", symClassOperator},
|
SymKwOr: {"or", symClassOperator, posInfix},
|
||||||
SymKwBut: {"but", symClassOperator},
|
SymKwBut: {"but", symClassOperator, posInfix},
|
||||||
SymKwFunc: {"func(", symClassDeclaration},
|
SymKwFunc: {"func(", symClassDeclaration, posPrefix},
|
||||||
SymKwBuiltin: {"builtin", symClassOperator},
|
SymKwBuiltin: {"builtin", symClassOperator, posPrefix},
|
||||||
SymKwPlugin: {"plugin", symClassOperator},
|
SymKwPlugin: {"plugin", symClassOperator, posPrefix},
|
||||||
SymKwIn: {"in", symClassOperator},
|
SymKwIn: {"in", symClassOperator, posInfix},
|
||||||
SymKwInclude: {"include", symClassOperator},
|
SymKwInclude: {"include", symClassOperator, posPrefix},
|
||||||
SymKwNil: {"nil", symClassValue},
|
SymKwNil: {"nil", symClassValue, posLeaf},
|
||||||
SymKwUnset: {"unset", symClassOperator},
|
SymKwUnset: {"unset", symClassOperator, posPrefix},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,12 +179,19 @@ 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.ToLower(s)
|
lower := strings.TrimRight(strings.ToLower(s), " \t")
|
||||||
for symbol, spec := range symbolMap {
|
for symbol, spec := range symbolMap {
|
||||||
if spec.kind == symClassOperator && strings.HasSuffix(lower, spec.repr) {
|
if strings.HasSuffix(lower, spec.repr) {
|
||||||
|
if len(spec.repr) > matchLength {
|
||||||
|
matchLength = len(spec.repr)
|
||||||
|
if spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix) {
|
||||||
sym = symbol
|
sym = symbol
|
||||||
break
|
} else {
|
||||||
|
sym = SymNone
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
14
symbol.go
14
symbol.go
@ -60,8 +60,8 @@ const (
|
|||||||
SymQuestionExclam // 49: '?!'
|
SymQuestionExclam // 49: '?!'
|
||||||
SymDoubleAt // 50: '@@'
|
SymDoubleAt // 50: '@@'
|
||||||
SymDoubleColon // 51: '::'
|
SymDoubleColon // 51: '::'
|
||||||
SymInsert // 52: '>>'
|
SymDoubleGreater // 52: '>>'
|
||||||
SymAppend // 53: '<<'
|
SymDoubleLess // 53: '<<'
|
||||||
SymCaret // 54: '^'
|
SymCaret // 54: '^'
|
||||||
SymDollarRound // 55: '$('
|
SymDollarRound // 55: '$('
|
||||||
SymOpenClosedRound // 56: '()'
|
SymOpenClosedRound // 56: '()'
|
||||||
@ -71,8 +71,18 @@ const (
|
|||||||
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
|
||||||
|
@ -26,12 +26,13 @@ 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, 1)
|
// runTestSuiteSpec(t, section, inputs, 15)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@ 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 */ {`
|
/* 18 */ {`$$`, NewDict(map[any]any{"variables": NewDict(nil), "functions": NewDict(nil)}), nil},
|
||||||
|
///* 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},
|
||||||
@ -44,6 +46,6 @@ func TestExpr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// t.Setenv("EXPR_PATH", ".")
|
// t.Setenv("EXPR_PATH", ".")
|
||||||
|
|
||||||
// runTestSuiteSpec(t, section, inputs, 6, 7, 8, 9)
|
// runTestSuiteSpec(t, section, inputs, 18)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
@ -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, `division by zero`},
|
/* 15 */ {`1:0`, nil, `[1:3] 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, `division by zero`},
|
/* 24 */ {`1:(2-2)`, nil, `[1:3] 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)
|
||||||
|
@ -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},
|
||||||
|
@ -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},
|
||||||
/* 33 */ {`a=[1,2]; 5>>a`, newListA(int64(5), int64(1), int64(2)), nil},
|
/* 32 */ {`a=[1,2]; 5+>a`, newListA(int64(5), int64(1), int64(2)), nil},
|
||||||
/* 34 */ {`L=[1,2]; L[0]=9; L`, newListA(int64(9), int64(2)), nil},
|
/* 33 */ {`L=[1,2]; L[0]=9; L`, newListA(int64(9), int64(2)), nil},
|
||||||
/* 35 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`},
|
/* 34 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`},
|
||||||
/* 36 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [list]`},
|
/* 35 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [list]`},
|
||||||
/* 37 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`},
|
/* 36 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`},
|
||||||
/* 38 */ {`[0,1,2,3,4][2:3]`, newListA(int64(2)), nil},
|
/* 37 */ {`[0,1,2,3,4][2:3]`, newListA(int64(2)), nil},
|
||||||
/* 39 */ {`[0,1,2,3,4][3:-1]`, newListA(int64(3)), nil},
|
/* 38 */ {`[0,1,2,3,4][3:-1]`, newListA(int64(3)), nil},
|
||||||
/* 40 */ {`[0,1,2,3,4][-3:-1]`, newListA(int64(2), int64(3)), nil},
|
/* 30 */ {`[0,1,2,3,4][-3:-1]`, newListA(int64(2), int64(3)), nil},
|
||||||
/* 41 */ {`[0,1,2,3,4][0:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
|
/* 40 */ {`[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", ".")
|
||||||
|
@ -14,10 +14,29 @@ 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, 3)
|
// runTestSuiteSpec(t, section, inputs, 4)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
@ -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, `division by zero`},
|
/* 67 */ {"4 / 0", nil, `[1:4] division by zero`},
|
||||||
/* 68 */ {"4.0 / 0", nil, `division by zero`},
|
/* 68 */ {"4.0 / 0", nil, `[1:6] 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, 130)
|
// runTestSuiteSpec(t, section, inputs, 114)
|
||||||
runTestSuite(t, section, inputs)
|
runTestSuite(t, section, inputs)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ 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},
|
||||||
@ -16,6 +17,12 @@ 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
11
term.go
@ -15,21 +15,26 @@ const (
|
|||||||
priRange
|
priRange
|
||||||
priBut
|
priBut
|
||||||
priAssign
|
priAssign
|
||||||
|
priInsert
|
||||||
priOr
|
priOr
|
||||||
priAnd
|
priAnd
|
||||||
priNot
|
priNot
|
||||||
priRelational
|
priRelational
|
||||||
priBinary
|
priBitwiseOr
|
||||||
|
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
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -199,6 +204,10 @@ 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
|
||||||
|
4
token.go
4
token.go
@ -79,6 +79,10 @@ 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
|
||||||
|
Loading…
Reference in New Issue
Block a user