loxxy 0.0.15 → 0.0.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +69 -1
- data/README.md +140 -48
- data/lib/loxxy/ast/all_lox_nodes.rb +6 -1
- data/lib/loxxy/ast/ast_builder.rb +44 -3
- data/lib/loxxy/ast/ast_visitor.rb +54 -2
- data/lib/loxxy/ast/lox_binary_expr.rb +1 -1
- data/lib/loxxy/ast/lox_grouping_expr.rb +23 -0
- data/lib/loxxy/ast/lox_if_stmt.rb +35 -0
- data/lib/loxxy/ast/lox_logical_expr.rb +28 -0
- data/lib/loxxy/ast/lox_unary_expr.rb +27 -0
- data/lib/loxxy/back_end/engine.rb +60 -3
- data/lib/loxxy/datatype/builtin_datatype.rb +55 -0
- data/lib/loxxy/datatype/false.rb +22 -0
- data/lib/loxxy/datatype/lx_string.rb +3 -4
- data/lib/loxxy/datatype/nil.rb +22 -0
- data/lib/loxxy/datatype/number.rb +98 -15
- data/lib/loxxy/datatype/true.rb +8 -0
- data/lib/loxxy/front_end/grammar.rb +5 -5
- data/lib/loxxy/version.rb +1 -1
- data/spec/front_end/parser_spec.rb +4 -4
- data/spec/interpreter_spec.rb +208 -9
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6628d902c258d0aa2d589fd0960ab812addbfe8f0fbf162cfb627a90fbc1a40
|
4
|
+
data.tar.gz: c1fe1f5ce4b3dc7109c70783b78953fd72ffbbd837d58f8350d2a03615f80222
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 301160cc1a00e819cc13cfb3273985b6af1ddadd94b236e4e7be0b346744355327be69d3b2d338ece3b6148a905d10a91dc3f6ef828912b7750efcdb0f4e5238
|
7
|
+
data.tar.gz: cc5bb436b6e487d7752180d42d046d5a09a6817878428d757b65b26f2955133985598b55e7d63c13d249ebef110914a3a2b8292777a2857b15dcba885c74c106
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,71 @@
|
|
1
|
+
## [0.0.20] - 2021-01-15
|
2
|
+
- The interpreter supports the `if` ... `else` statement.
|
3
|
+
|
4
|
+
## Added
|
5
|
+
- Class `Ast::LoxItStmt`, AST node specific for `if` `else` statements
|
6
|
+
- Method `Ast::ASTBuilder#reduce_if_stmt` as semantic action for if ... else
|
7
|
+
- Method `Ast::ASTVisitor#visit_if_stmt` for visiting `LoxIfStmt` nodes
|
8
|
+
- Method `Engine::after_if_stmt` implementation of the control flow
|
9
|
+
|
10
|
+
## [0.0.19] - 2021-01-14
|
11
|
+
- The interpreter supports expressions between parentheses (grouping).
|
12
|
+
|
13
|
+
## Added
|
14
|
+
- Class `Ast::LoxLogicalExpr`
|
15
|
+
- Method `Ast::ASTBuilder#reduce_grouping_expr` as semantic action for grouping expression
|
16
|
+
- Method `Ast::ASTVisitor#visit_grouping_expr` for visiting grouping expressions
|
17
|
+
- Method `Engine::after_grouping_expr`for the evaluation of grouping expressions
|
18
|
+
|
19
|
+
## Changed
|
20
|
+
- File `grammar.rb` rules for if ... else were given names in order to activate semantic actions.
|
21
|
+
- File `README.md` updated with little `if ... else` documentation.
|
22
|
+
|
23
|
+
## [0.0.18] - 2021-01-13
|
24
|
+
- The interpreter can evaluate `and`, `or`expressions.
|
25
|
+
|
26
|
+
## Added
|
27
|
+
- Class `Ast::LoxLogicalExpr`
|
28
|
+
- Method `Ast::ASTBuilder#reduce_logical_expr` for the semantic action require for `and`, `or`
|
29
|
+
- Method `Ast::ASTVisitor#visit_logical_expr` for visiting logical expressions
|
30
|
+
- Method `Backend::Engine#after_logical_expr` implements the evaluation of the logical expressions
|
31
|
+
|
32
|
+
## [0.0.17] - 2021-01-12
|
33
|
+
- The interpreter can evaluate all arithmetic and comparison operations.
|
34
|
+
- It implements `==`, `!=` and the unary operations `!`, `-`
|
35
|
+
|
36
|
+
## Added
|
37
|
+
- Class `Ast::LoxUnaryExpr`
|
38
|
+
- Method `Ast::ASTBuilder#reduce_unary_expr` to support the evaluation of `!` and ``-@`
|
39
|
+
- Method `Ast::ASTVisitor#visit_unnary_expr` for visiting unary expressions
|
40
|
+
- Method `Backend::Engine#after_unary_expr` evaluating an unary expression
|
41
|
+
- In class `Datatype::BuiltinDatatype` the methods `falsey?`, `truthy?`, `!`, `!=`
|
42
|
+
- In class `Datatype::Number`the methods `<`, `<=`, ´>´, `>=` and `-@`
|
43
|
+
|
44
|
+
## Changed
|
45
|
+
- File `README.md` updated.
|
46
|
+
|
47
|
+
## [0.0.16] - 2021-01-11
|
48
|
+
- The interpreter can evaluate product and division of two numbers.
|
49
|
+
- It also implements equality `==` and inequality `!=` operators
|
50
|
+
|
51
|
+
## Added
|
52
|
+
- Method `Datatype::False#==` for equality testing
|
53
|
+
- Method `Datatype::False#!=` for inequality testing
|
54
|
+
- Method `Datatype::LXString#==` for equality testing
|
55
|
+
- Method `Datatype::LXString#!=` for inequality testing
|
56
|
+
- Method `Datatype::Nil#==` for equality testing
|
57
|
+
- Method `Datatype::Nil#!=` for inequality testing
|
58
|
+
- Method `Datatype::Number#==` for equality testing
|
59
|
+
- Method `Datatype::Number#!=` for inequality testing
|
60
|
+
- Method `Datatype::Number#*` for multiply operator
|
61
|
+
- Method `Datatype::Number#/` for divide operator
|
62
|
+
- Method `Datatype::True#==` for equality testing
|
63
|
+
- Method `Datatype::True#!=` for inequality testing
|
64
|
+
|
65
|
+
## Changed
|
66
|
+
- Method `BackEnd::Engine#after_binary_expr` to allow `*`, `/`, `==`, `!=` operators
|
67
|
+
- File `README.md` updated for the newly implemented operators
|
68
|
+
|
1
69
|
## [0.0.15] - 2021-01-11
|
2
70
|
- The interpreter can evaluate substraction between two numbers.
|
3
71
|
|
@@ -14,7 +82,7 @@
|
|
14
82
|
- The interpreter can evaluate addition of numbers and string concatenation
|
15
83
|
|
16
84
|
## Added
|
17
|
-
- Method `Ast::ASTVisitor
|
85
|
+
- Method `Ast::ASTVisitor#visit_binary_expr` for visiting binary expressions
|
18
86
|
- Method `Ast::LoxBinaryExpr#accept` for visitor pattern
|
19
87
|
- Method `BackEnd::Engine#after_binary_expr` to trigger execution of binary operator
|
20
88
|
- `Boolean` class hierarchy: added methos `true?` and `false?` to ease spec test writing
|
data/README.md
CHANGED
@@ -128,16 +128,20 @@ program
|
|
128
128
|
```
|
129
129
|
|
130
130
|
## Suppported Lox language features
|
131
|
-
|
132
|
-
|
131
|
+
On one hand, the parser covers the complete Lox grammar and should therefore, in principle,
|
132
|
+
parse any valid Lox program.
|
133
|
+
|
134
|
+
On the other hand, the interpreter is under development and currently it can evaluate only a tiny subset of __Lox__.
|
135
|
+
But the situation is changing almost daily, stay tuned...
|
133
136
|
|
134
137
|
Here are the language features currently supported by the interpreter:
|
135
138
|
|
136
139
|
- [Comments](#comments)
|
137
140
|
- [Keywords](#keywords)
|
138
|
-
- [Operators and Special Chars](#operators-and-special-chars)
|
139
141
|
- [Datatypes](#datatypes)
|
140
|
-
- [Statements](#statements)
|
142
|
+
- [Statements](#statements)
|
143
|
+
-[Expressions](#expressions)
|
144
|
+
-[Print Statement](#print-statement)
|
141
145
|
|
142
146
|
### Comments
|
143
147
|
|
@@ -148,38 +152,10 @@ Loxxy supports single line C-style comments.
|
|
148
152
|
```
|
149
153
|
|
150
154
|
### Keywords
|
151
|
-
|
152
|
-
The parser knows all the __Lox__ reserved keywords:
|
155
|
+
Loxxy implements the following __Lox__ reserved keywords:
|
153
156
|
```lang-none
|
154
|
-
and,
|
155
|
-
print, return, super, this, true, var, while
|
157
|
+
and, false, nil, or, print, true
|
156
158
|
```
|
157
|
-
Of these, the interpreter implements: `false`, `nil`, `true`
|
158
|
-
|
159
|
-
### Operators and Special Chars
|
160
|
-
#### Operators
|
161
|
-
The parser recognizes all the __Lox__ operators, delimiters and separators:
|
162
|
-
- Arithmetic operators: `+`, `-`, `*`, `/`
|
163
|
-
- Comparison operators: `>`, `>=`, `<`, `<=`
|
164
|
-
- Equality operators: `==`, `!=`
|
165
|
-
|
166
|
-
Of these, the interpreter implements:
|
167
|
-
`+` (addition of two numbers or string concatenation)
|
168
|
-
`-` (difference between two numbers)
|
169
|
-
|
170
|
-
#### Delimiters
|
171
|
-
The parser knows all the __Lox__ grouping delimiters:
|
172
|
-
(`, ), `{`, `}`
|
173
|
-
|
174
|
-
These aren't yet implemented in the interpreter.
|
175
|
-
|
176
|
-
The other characters that have a special meaning in __Lox__ are:
|
177
|
-
- `,` Used in parameter list
|
178
|
-
- `.` For the dot notation (i.e. calling a method)
|
179
|
-
- `;` The semicolon is used to terminates expressions
|
180
|
-
- `=` Assignment
|
181
|
-
|
182
|
-
The parser recognizes them all but the interpreter accepts the semicolons only.
|
183
159
|
|
184
160
|
### Datatypes
|
185
161
|
|
@@ -189,22 +165,138 @@ loxxy supports all the standard __Lox__ datatypes:
|
|
189
165
|
- `String`: Sequence of characters surrounded by `"`. For example: `"Hello!"`
|
190
166
|
- `Nil`: Used to define a null value, denoted by the `nil` keyword
|
191
167
|
|
192
|
-
|
193
|
-
|
194
|
-
Loxxy
|
195
|
-
-
|
196
|
-
-
|
197
|
-
-
|
198
|
-
-
|
168
|
+
### Statements
|
169
|
+
|
170
|
+
Loxxy supports the following statements:
|
171
|
+
-[Expressions](#expressions)
|
172
|
+
-[Arithmetic expressions](#arithmetic-expressions)
|
173
|
+
-[String concatenation](#string-concatenation)
|
174
|
+
-[Comparison expressions](#comparison-expressions)
|
175
|
+
-[Logical expressions](#logical-expressions)
|
176
|
+
-[Grouping expressions](#grouping-expressions)
|
177
|
+
-[If Statement](#if-statement)
|
178
|
+
-[Print Statement](#print-statement)
|
179
|
+
|
180
|
+
#### Expressions
|
181
|
+
|
182
|
+
##### Arithmetic expressions
|
183
|
+
Loxxy supports the following operators for arithmetic expressions:
|
184
|
+
|
185
|
+
- `+`: Adds of two numbers. Both operands must be of the type Number
|
186
|
+
E.g. `37 + 5; // => 42`
|
187
|
+
`7 + -3; // => 4`
|
188
|
+
- `-`: (Binary) Subtracts right operand from left operand. Both operands must be numbers.
|
189
|
+
E.g. `47 - 5; // => 42`
|
190
|
+
- `-`: (Unary) Negates (= changes the sign) of the given number operand.
|
191
|
+
E.g. `- -3; // => 3`
|
192
|
+
- `*`: Multiplies two numbers
|
193
|
+
E.g. `2 * 3; // => 6`
|
194
|
+
- `/`: Divides two numbers
|
195
|
+
E.g. `8 / 2; // => 4`
|
196
|
+
`5 / 2; // => 2.5`
|
197
|
+
|
198
|
+
##### String concatenation
|
199
|
+
- `+`: Concatenates two strings. Both operands must be of the String type.
|
200
|
+
E.g. `"Hello" + ", " + "world! // => "Hello, world!"`
|
201
|
+
|
202
|
+
##### Comparison expressions
|
203
|
+
|
204
|
+
- `==`: Returns `true` if left operand is equal to right operand, otherwise `false`
|
205
|
+
E.g. `false == false; // => true`
|
206
|
+
`5 + 2 == 3 + 4; // => true`
|
207
|
+
`"" == ""; // => true`
|
208
|
+
- `!=`: Returns `true` if left operand is not equal to right operand, otherwise `false`
|
209
|
+
E.g. `false != "false"; // => true`
|
210
|
+
`5 + 2 != 4 + 3; // => false`
|
211
|
+
- `<`: Returns `true` if left operand is less than right operand, otherwise `false`. Both operands must be numbers
|
212
|
+
E.g. `1 < 3; // => true`
|
213
|
+
`1 < 0; // => false`
|
214
|
+
`2 < 2; // => false`
|
215
|
+
- `<=`: Returns `true` if left operand is equal to right operand, otherwise `false`. Both operands must be numbers
|
216
|
+
E.g. `1 <= 3; // => true`
|
217
|
+
`1 <= 0; // => false`
|
218
|
+
`2 <= 2; // => true`
|
219
|
+
- `>`: Returns `true` if left operand is equal to right operand, otherwise `false`. Both operands must be numbers
|
220
|
+
E.g. `1 > 3; // => false`
|
221
|
+
`1 > 0; // => true`
|
222
|
+
`2 > 2; // => false`
|
223
|
+
- `>=`: Returns `true` if left operand is equal to right operand, otherwise `false`. Both operands must be numbers
|
224
|
+
E.g. `1 > 3; // => false`
|
225
|
+
`1 > 0; // => true`
|
226
|
+
`2 > 2; // => false`
|
227
|
+
|
228
|
+
##### Logical expressions
|
229
|
+
|
230
|
+
REMINDER: In __Lox__, `false` and `nil` are considered falsey, everything else is truthy.
|
231
|
+
|
232
|
+
- `and`: When both operands are booleans, then returns `true` if both left and right operands are truthy, otherwise `false`.
|
233
|
+
If at least one operand isn't a boolean then returns first falsey operand else (both operands are truthy) returns the second operand.
|
234
|
+
truthy returns the second operand.
|
235
|
+
E.g. `false and true; // => false`
|
236
|
+
`true and nil; // => nil`
|
237
|
+
`0 and true and ""; // => ""`
|
238
|
+
- `or`: When both operands are booleans, then returns `true` if left or right operands are truthy, otherwise `false`.
|
239
|
+
If at least one operand isn't a boolean then returns first truthy operand else (both operands are truthy) returns the second operand.
|
240
|
+
E.g. `false or true; // => true`
|
241
|
+
`true or nil; // => nil`
|
242
|
+
`false or nil; // => nil`
|
243
|
+
`0 or true or ""; // => 0`
|
244
|
+
- `!`: Performs a logical negation on its operand
|
245
|
+
E.g. `!false; // => true`
|
246
|
+
`!!true; // => true`
|
247
|
+
`!0; // => false`
|
248
|
+
|
249
|
+
#### Grouping expressions
|
250
|
+
Use parentheses `(` `)` for a better control in expression/operator precedence.
|
251
|
+
|
252
|
+
``` javascript
|
253
|
+
print 3 + 4 * 5; // => 23
|
254
|
+
print (3 + 4) * 5; // => 35
|
255
|
+
```
|
199
256
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
257
|
+
#### If statement
|
258
|
+
|
259
|
+
Based on a given condition, an if statement executes one of two statements:
|
260
|
+
``` javascript
|
261
|
+
if (condition) {
|
262
|
+
print "then-branch";
|
263
|
+
} else {
|
264
|
+
print "else-branch";
|
265
|
+
}
|
266
|
+
```
|
267
|
+
|
268
|
+
As for other languages, the `else` part is optional.
|
269
|
+
##### Warning: nested `if`...`else`
|
270
|
+
Call it a bug ... Nested `if` `else` control flow structure aren't yet supported by __Loxxy__.
|
271
|
+
The culprit has a name: [the dangling else](https://en.wikipedia.org/wiki/Dangling_else).
|
272
|
+
|
273
|
+
The problem in a nutshell: in a nested if ... else ... statement like this:
|
274
|
+
``` javascript
|
275
|
+
'if (true) if (false) print "bad"; else print "good";
|
276
|
+
```
|
277
|
+
... there is an ambiguity. Indeed, according to the __Lox__ grammar, the `else` could be bound
|
278
|
+
either to the first `if` or to the second one.
|
279
|
+
This ambiguity is usually lifted by applying an ad-hoc rule: an `else` is aways bound to the most
|
280
|
+
recent (rightmost) `if`.
|
281
|
+
Being a generic parsing library, `Rley` doesn't apply any of these supplemental rules.
|
282
|
+
As a consequence,it complains about the found ambiguity and stops the parsing...
|
283
|
+
Although `Rley` can cope with ambiguities, this requires the use of an advanced data structure
|
284
|
+
called `Shared Packed Parse Forest (SPPF)`.
|
285
|
+
SPPF are much more complex to handle than the `common` parse trees present in most compiler or interpreter books.
|
286
|
+
Therefore, a future version of `Rley` will incorporate the capability to define disambuiguation rules.
|
287
|
+
|
288
|
+
In the meantime, the `Loxxy` will progress on other __Lox__ features like:
|
289
|
+
- Variables,
|
290
|
+
- Block structures...
|
291
|
+
|
292
|
+
|
293
|
+
#### Print Statement
|
294
|
+
|
295
|
+
The statement print + expression + ; prints the result of the expression to stdout.
|
296
|
+
|
297
|
+
``` javascript
|
298
|
+
print "Hello, world!"; // Output: Hello, world!
|
204
299
|
|
205
|
-
```javascript
|
206
|
-
// Print statement with nested concatenation
|
207
|
-
print "Hello" + ", " + "world!";
|
208
300
|
```
|
209
301
|
|
210
302
|
## Installation
|
@@ -1,5 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'lox_print_stmt'
|
4
3
|
require_relative 'lox_literal_expr'
|
5
4
|
require_relative 'lox_noop_expr'
|
5
|
+
require_relative 'lox_grouping_expr'
|
6
|
+
require_relative 'lox_unary_expr'
|
7
|
+
require_relative 'lox_binary_expr'
|
8
|
+
require_relative 'lox_logical_expr'
|
9
|
+
require_relative 'lox_print_stmt'
|
10
|
+
require_relative 'lox_if_stmt'
|
@@ -15,7 +15,6 @@ module Loxxy
|
|
15
15
|
# @return [Hash{String => String}]
|
16
16
|
Name2special = {
|
17
17
|
'AND' => 'and',
|
18
|
-
'BANG' => '!',
|
19
18
|
'BANG_EQUAL' => '!=',
|
20
19
|
'COMMA' => ',',
|
21
20
|
'DOT' => '.',
|
@@ -36,6 +35,11 @@ module Loxxy
|
|
36
35
|
'SLASH' => '/',
|
37
36
|
'STAR' => '*'
|
38
37
|
}.freeze
|
38
|
+
|
39
|
+
Name2unary = {
|
40
|
+
'BANG' => '!',
|
41
|
+
'MINUS' => '-@'
|
42
|
+
}.freeze
|
39
43
|
end # defined
|
40
44
|
|
41
45
|
attr_reader :strict
|
@@ -92,6 +96,17 @@ module Loxxy
|
|
92
96
|
node
|
93
97
|
end
|
94
98
|
|
99
|
+
def reduce_logical_expr(_production, _range, tokens, theChildren)
|
100
|
+
operand1 = theChildren[0]
|
101
|
+
|
102
|
+
# Second child is array with couples [operator, operand2]
|
103
|
+
theChildren[1].each do |(operator, operand2)|
|
104
|
+
operand1 = LoxLogicalExpr.new(tokens[0].position, operator, operand1, operand2)
|
105
|
+
end
|
106
|
+
|
107
|
+
operand1
|
108
|
+
end
|
109
|
+
|
95
110
|
# rule('lhs' => 'nonterm_i nonterm_k_plus')
|
96
111
|
def reduce_binary_operator(_production, _range, tokens, theChildren)
|
97
112
|
operand1 = theChildren[0]
|
@@ -119,6 +134,11 @@ module Loxxy
|
|
119
134
|
[[operator, operand2]]
|
120
135
|
end
|
121
136
|
|
137
|
+
# Return the AST node corresponding to the second symbol in the rhs
|
138
|
+
def reduce_keep_symbol2(_production, _range, _tokens, theChildren)
|
139
|
+
theChildren[1]
|
140
|
+
end
|
141
|
+
|
122
142
|
#####################################
|
123
143
|
# SEMANTIC ACTIONS
|
124
144
|
#####################################
|
@@ -138,6 +158,14 @@ module Loxxy
|
|
138
158
|
return_first_child(range, tokens, theChildren) # Discard the semicolon
|
139
159
|
end
|
140
160
|
|
161
|
+
# rule('ifStmt' => 'IF ifCondition statement elsePart_opt')
|
162
|
+
def reduce_if_stmt(_production, _range, tokens, theChildren)
|
163
|
+
condition = theChildren[1]
|
164
|
+
then_stmt = theChildren[2]
|
165
|
+
else_stmt = theChildren[3]
|
166
|
+
LoxIfStmt.new(tokens[0].position, condition, then_stmt, else_stmt)
|
167
|
+
end
|
168
|
+
|
141
169
|
# rule('printStmt' => 'PRINT expression SEMICOLON')
|
142
170
|
def reduce_print_stmt(_production, _range, tokens, theChildren)
|
143
171
|
Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
|
@@ -145,7 +173,7 @@ module Loxxy
|
|
145
173
|
|
146
174
|
# rule('logic_or' => 'logic_and disjunct_plus')
|
147
175
|
def reduce_logic_or_plus(production, range, tokens, theChildren)
|
148
|
-
|
176
|
+
reduce_logical_expr(production, range, tokens, theChildren)
|
149
177
|
end
|
150
178
|
|
151
179
|
# rule('disjunct_plus' => 'disjunct_plus OR logic_and')
|
@@ -160,7 +188,7 @@ module Loxxy
|
|
160
188
|
|
161
189
|
# rule('logic_and' => 'equality conjunct_plus')
|
162
190
|
def reduce_logic_and_plus(production, range, tokens, theChildren)
|
163
|
-
|
191
|
+
reduce_logical_expr(production, range, tokens, theChildren)
|
164
192
|
end
|
165
193
|
|
166
194
|
# rule('conjunct_plus' => 'conjunct_plus AND equality')
|
@@ -231,6 +259,19 @@ module Loxxy
|
|
231
259
|
reduce_binary_plus_end(production, range, tokens, theChildren)
|
232
260
|
end
|
233
261
|
|
262
|
+
# rule('unary' => 'unaryOp unary')
|
263
|
+
def reduce_unary_expr(_production, _range, tokens, theChildren)
|
264
|
+
operator = Name2unary[theChildren[0].symbol.name].to_sym
|
265
|
+
operand = theChildren[1]
|
266
|
+
LoxUnaryExpr.new(tokens[0].position, operator, operand)
|
267
|
+
end
|
268
|
+
|
269
|
+
# rule('primary' => 'LEFT_PAREN expression RIGHT_PAREN')
|
270
|
+
def reduce_grouping_expr(_production, _range, tokens, theChildren)
|
271
|
+
subexpr = theChildren[1]
|
272
|
+
LoxGroupingExpr.new(tokens[0].position, subexpr)
|
273
|
+
end
|
274
|
+
|
234
275
|
# rule('primary' => 'FALSE' | TRUE').as 'literal_expr'
|
235
276
|
def reduce_literal_expr(_production, _range, _tokens, theChildren)
|
236
277
|
first_child = theChildren.first
|
@@ -51,7 +51,15 @@ module Loxxy
|
|
51
51
|
broadcast(:after_ptree, aParseTree)
|
52
52
|
end
|
53
53
|
|
54
|
-
# Visit event. The visitor is about to visit a
|
54
|
+
# Visit event. The visitor is about to visit a if statement.
|
55
|
+
# @param anIfStmt [AST::LOXIfStmt] the if statement node to visit
|
56
|
+
def visit_if_stmt(anIfStmt)
|
57
|
+
broadcast(:before_if_stmt, anIfStmt)
|
58
|
+
traverse_subnodes(anIfStmt) # The condition is visited/evaluated here...
|
59
|
+
broadcast(:after_if_stmt, anIfStmt, self)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Visit event. The visitor is about to visit a print statement.
|
55
63
|
# @param aPrintStmt [AST::LOXPrintStmt] the print statement node to visit
|
56
64
|
def visit_print_stmt(aPrintStmt)
|
57
65
|
broadcast(:before_print_stmt, aPrintStmt)
|
@@ -59,7 +67,21 @@ module Loxxy
|
|
59
67
|
broadcast(:after_print_stmt, aPrintStmt)
|
60
68
|
end
|
61
69
|
|
62
|
-
# Visit event. The visitor is about to visit a
|
70
|
+
# Visit event. The visitor is about to visit a logical expression.
|
71
|
+
# Since logical expressions may take shorcuts by not evaluating all their
|
72
|
+
# sub-expressiosns, they are responsible for visiting or not their children.
|
73
|
+
# @param aBinaryExpr [AST::LOXBinaryExpr] the logical expression node to visit
|
74
|
+
def visit_logical_expr(aLogicalExpr)
|
75
|
+
broadcast(:before_logical_expr, aLogicalExpr)
|
76
|
+
|
77
|
+
# As logical connectors may take a shortcut only the first argument is visited
|
78
|
+
traverse_given_subnode(aLogicalExpr, 0)
|
79
|
+
|
80
|
+
# The second child could be visited: this action is deferred in handler
|
81
|
+
broadcast(:after_logical_expr, aLogicalExpr, self)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Visit event. The visitor is about to visit a binary expression.
|
63
85
|
# @param aBinaryExpr [AST::LOXBinaryExpr] the binary expression node to visit
|
64
86
|
def visit_binary_expr(aBinaryExpr)
|
65
87
|
broadcast(:before_binary_expr, aBinaryExpr)
|
@@ -67,6 +89,22 @@ module Loxxy
|
|
67
89
|
broadcast(:after_binary_expr, aBinaryExpr)
|
68
90
|
end
|
69
91
|
|
92
|
+
# Visit event. The visitor is about to visit an unary expression.
|
93
|
+
# @param anUnaryExpr [AST::anUnaryExpr] unary expression node to visit
|
94
|
+
def visit_unary_expr(anUnaryExpr)
|
95
|
+
broadcast(:before_unary_expr, anUnaryExpr)
|
96
|
+
traverse_subnodes(anUnaryExpr)
|
97
|
+
broadcast(:after_unary_expr, anUnaryExpr)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Visit event. The visitor is about to visit a grouping expression.
|
101
|
+
# @param aGroupingExpr [AST::LoxGroupingExpr] grouping expression to visit
|
102
|
+
def visit_grouping_expr(aGroupingExpr)
|
103
|
+
broadcast(:before_grouping_expr, aGroupingExpr)
|
104
|
+
traverse_subnodes(aGroupingExpr)
|
105
|
+
broadcast(:after_grouping_expr, aGroupingExpr)
|
106
|
+
end
|
107
|
+
|
70
108
|
# Visit event. The visitor is visiting the
|
71
109
|
# given terminal node containing a datatype object.
|
72
110
|
# @param aLiteralExpr [AST::LoxLiteralExpr] the leaf node to visit.
|
@@ -98,6 +136,20 @@ module Loxxy
|
|
98
136
|
broadcast(:after_subnodes, aParentNode, subnodes)
|
99
137
|
end
|
100
138
|
|
139
|
+
# Visit event. The visitor is about to visit one given subnode of a non
|
140
|
+
# terminal node.
|
141
|
+
# @param aParentNode [Ast::LocCompoundExpr] the parent node.
|
142
|
+
# @param index [integer] index of child subnode
|
143
|
+
def traverse_given_subnode(aParentNode, index)
|
144
|
+
subnode = aParentNode.subnodes[index]
|
145
|
+
broadcast(:before_given_subnode, aParentNode, subnode)
|
146
|
+
|
147
|
+
# Now, let's proceed with the visit of that subnode
|
148
|
+
subnode.accept(self)
|
149
|
+
|
150
|
+
broadcast(:after_given_subnode, aParentNode, subnode)
|
151
|
+
end
|
152
|
+
|
101
153
|
# Send a notification to all subscribers.
|
102
154
|
# @param msg [Symbol] event to notify
|
103
155
|
# @param args [Array] arguments of the notification.
|