loxxy 0.3.01 → 0.4.01
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +24 -0
- data/CHANGELOG.md +42 -0
- data/README.md +63 -5
- data/lib/loxxy/ast/ast_builder.rb +55 -91
- data/lib/loxxy/ast/ast_visitor.rb +0 -2
- data/lib/loxxy/ast/lox_class_stmt.rb +8 -5
- data/lib/loxxy/ast/lox_fun_stmt.rb +12 -5
- data/lib/loxxy/ast/lox_node.rb +1 -1
- data/lib/loxxy/ast/lox_set_expr.rb +5 -2
- data/lib/loxxy/back_end/engine.rb +147 -50
- data/lib/loxxy/back_end/environment.rb +4 -0
- data/lib/loxxy/back_end/lox_class.rb +6 -8
- data/lib/loxxy/back_end/lox_function.rb +13 -7
- data/lib/loxxy/back_end/lox_instance.rb +14 -2
- data/lib/loxxy/back_end/resolver.rb +6 -0
- data/lib/loxxy/datatype/lx_string.rb +2 -3
- data/lib/loxxy/front_end/grammar.rb +16 -39
- data/lib/loxxy/front_end/scanner.rb +54 -28
- data/lib/loxxy/version.rb +1 -1
- data/loxxy.gemspec +2 -2
- data/spec/back_end/engine_spec.rb +13 -3
- data/spec/front_end/parser_spec.rb +4 -4
- data/spec/front_end/raw_parser_spec.rb +10 -3
- data/spec/front_end/scanner_spec.rb +13 -10
- data/spec/interpreter_spec.rb +44 -0
- data/spec/spec_helper.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03ef0a6b112537abbb890f56a5746a22be8aa9373451ce57a25d33ffd4cfe2be
|
4
|
+
data.tar.gz: 3abea4f9bfd799de85840c93a91aa37d0f9676b5e1d9af6a68bef7d189843470
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74a279e2033090d6f4df08f30e4e71cf3c34c29dff2d2400a066528b68e73b2019345a84cabfad59f0342f8ba0a0d2ebf47ce87ac2195223a9c68886febb6a72
|
7
|
+
data.tar.gz: 9e1c5ba2b8e88af10c198bcefdc8a791be2900df2ee71127df560f1bcbfa18f03bc4cf86d149cc475cf5392938e4d74bb769d4a80630c9a5c82e0da90c936135
|
data/.rubocop.yml
CHANGED
@@ -50,6 +50,9 @@ Layout/IndentationConsistency:
|
|
50
50
|
Layout/HeredocIndentation:
|
51
51
|
Enabled: false
|
52
52
|
|
53
|
+
Layout/LineEndStringConcatenationIndentation:
|
54
|
+
Enabled: true
|
55
|
+
|
53
56
|
Layout/MultilineHashBraceLayout:
|
54
57
|
Enabled: true
|
55
58
|
|
@@ -81,6 +84,9 @@ Layout/TrailingWhitespace:
|
|
81
84
|
Lint/AmbiguousAssignment:
|
82
85
|
Enabled: true
|
83
86
|
|
87
|
+
Lint/AmbiguousRange:
|
88
|
+
Enabled: true
|
89
|
+
|
84
90
|
Lint/DeprecatedConstants:
|
85
91
|
Enabled: true
|
86
92
|
|
@@ -96,6 +102,9 @@ Lint/EmptyBlock:
|
|
96
102
|
Lint/EmptyClass:
|
97
103
|
Enabled: false
|
98
104
|
|
105
|
+
Lint/EmptyInPattern:
|
106
|
+
Enabled: true
|
107
|
+
|
99
108
|
Lint/LambdaWithoutLiteralBlock:
|
100
109
|
Enabled: true
|
101
110
|
|
@@ -192,6 +201,9 @@ Naming/ClassAndModuleCamelCase:
|
|
192
201
|
Naming/BlockParameterName:
|
193
202
|
Enabled: true
|
194
203
|
|
204
|
+
Naming/InclusiveLanguage:
|
205
|
+
Enabled: true
|
206
|
+
|
195
207
|
Naming/MethodParameterName:
|
196
208
|
Enabled: false
|
197
209
|
|
@@ -273,11 +285,17 @@ Style/HashTransformValues:
|
|
273
285
|
Style/IfUnlessModifier:
|
274
286
|
Enabled: false
|
275
287
|
|
288
|
+
Style/InPatternThen:
|
289
|
+
Enabled: true
|
290
|
+
|
276
291
|
Style/InverseMethods:
|
277
292
|
Enabled: false
|
278
293
|
|
279
294
|
Style/MissingRespondToMissing:
|
280
295
|
Enabled: false
|
296
|
+
|
297
|
+
Style/MultilineInPatternThen:
|
298
|
+
Enabled: true
|
281
299
|
|
282
300
|
Style/NegatedIfElseCondition:
|
283
301
|
Enabled: true
|
@@ -290,6 +308,9 @@ Style/NilLambda:
|
|
290
308
|
|
291
309
|
Style/NumericLiterals:
|
292
310
|
Enabled: false
|
311
|
+
|
312
|
+
Style/QuotedSymbols:
|
313
|
+
Enabled: true
|
293
314
|
|
294
315
|
Style/RaiseArgs:
|
295
316
|
Enabled: true
|
@@ -302,6 +323,9 @@ Style/RedundantReturn:
|
|
302
323
|
|
303
324
|
Style/RedundantSelf:
|
304
325
|
Enabled: true
|
326
|
+
|
327
|
+
Style/RedundantSelfAssignmentBranch:
|
328
|
+
Enabled: true
|
305
329
|
|
306
330
|
Style/RegexpLiteral:
|
307
331
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,45 @@
|
|
1
|
+
## [0.4.01] - 2021-08-22
|
2
|
+
- Grammar and AST::AstBuilder adapted to take profit of extended grammar notiation in Rley 0.8.01
|
3
|
+
|
4
|
+
### Changed
|
5
|
+
- Class `Ast::ASTBuilder` removal of methods made redundant with new Rley version
|
6
|
+
- File `.rubocop.yml` added config for new cops
|
7
|
+
- File `grammar.rb` changed rules to use new extended rule syntax in Rley
|
8
|
+
|
9
|
+
## [0.4.00] - 2021-05-24
|
10
|
+
- Version bump. `Loxxy` is capable to run the LoxLox interpreter, an interpreter written in `Lox`.
|
11
|
+
|
12
|
+
### New
|
13
|
+
- Method `BackEnd::LoxInstance#falsey?` added
|
14
|
+
- Method `BackEnd::LoxInstance#truthy?` added
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
- Method `BackEnd::Engine#after_variable_expr` the error message `Undefined variable` nows gives the location of the offending variable.
|
18
|
+
- Class `Ast::LoxClassStmt`is now a subclass of `LoxNode`
|
19
|
+
|
20
|
+
- File `README.md` added an explanation on how to run `LoxLox`interpreter.
|
21
|
+
|
22
|
+
### Fixed
|
23
|
+
- Method `Ast::LoxClassStmt#initialize` fixed inconsistencies in its Yard/RDoc documentation.
|
24
|
+
- Method `Ast::LoxFunStmt#initialize` fixed inconsistencies in its Yard/RDoc documentation.
|
25
|
+
- Method `BackEnd::Engine#native_getc` now returns -1 when its reaches EOF.
|
26
|
+
- Method `BackEnd::Resolver#after_logical_expr` was missing and this caused the lack of resultation in the second operand.
|
27
|
+
|
28
|
+
## [0.3.02] - 2021-05-22
|
29
|
+
- New built-in expressions `getc`, `chr`, `exit` and `print_eeror` , fixes with deeply nested returns, set expressions
|
30
|
+
|
31
|
+
### New
|
32
|
+
- Class `BackEnd::Engine` new built-in functions `getc`, `chr`, `exit`, and `print_error`
|
33
|
+
|
34
|
+
### Changed
|
35
|
+
- Class `Ast::LoxSetExpr` value to assign is now a distinct atrrbute instead of a subnode
|
36
|
+
- Class `BackEnd::Engine` two distinct stacks: one of expression evaluation, another for argument passing
|
37
|
+
|
38
|
+
### Fixed
|
39
|
+
- Class `BackEnd::LoxClass`: in some contexts the init method returned twice 'this'.
|
40
|
+
- Method `LoxFunction#call` mismatch between deeply nested returns and environments
|
41
|
+
|
42
|
+
|
1
43
|
## [0.3.01] - 2021-05-08
|
2
44
|
- Fix in `Scanner` class, added more tests in test suite.
|
3
45
|
|
data/README.md
CHANGED
@@ -19,7 +19,8 @@ Although __Lox__ is fairly simple, it is far from being a toy language:
|
|
19
19
|
### Loxxy gem features
|
20
20
|
- Complete tree-walking interpreter including lexer, parser and resolver
|
21
21
|
- 100% pure Ruby with clean design (not a port from some other language)
|
22
|
-
- Passes the `jox` (THE reference `Lox` implementation) test suite
|
22
|
+
- Passes the `jox` (THE reference `Lox` implementation) test suite
|
23
|
+
- Can run a Lox imterpreter implemented in ... `Lox` [LoxLox](https://github.com/benhoyt/loxlox),
|
23
24
|
- Minimal runtime dependency (Rley gem). Won't drag a bunch of gems...
|
24
25
|
- Ruby API for integrating a Lox interpreter with your code.
|
25
26
|
- A command-line interpreter `loxxy`
|
@@ -53,6 +54,7 @@ And then execute:
|
|
53
54
|
### 2. Your first `Lox` program
|
54
55
|
Create a text file and enter the following lines:
|
55
56
|
```javascript
|
57
|
+
// hello.lox
|
56
58
|
// Your firs Lox program
|
57
59
|
print "Hello, world.";
|
58
60
|
```
|
@@ -75,6 +77,7 @@ Let's admit it, the hello world example was unimpressive.
|
|
75
77
|
To a get a taste of `Lox` object-oriented capabilities, let's try another `Hello world` variant:
|
76
78
|
|
77
79
|
```javascript
|
80
|
+
// oo_hello.lox
|
78
81
|
// Object-oriented hello world
|
79
82
|
class Greeter {
|
80
83
|
// in Lox, initializers/constructors are named `init`
|
@@ -98,6 +101,7 @@ Our next assignment: compute the first 20 elements of the Fibbonacci sequence.
|
|
98
101
|
Here's an answer using the `while` loop construct:
|
99
102
|
|
100
103
|
```javascript
|
104
|
+
// fibbonacci.lox
|
101
105
|
// Compute the first 20 elements from the Fibbonacci sequence
|
102
106
|
|
103
107
|
var a = 0; // Use the var keyword to declare a new variable
|
@@ -127,6 +131,7 @@ Fans of `for` loops will be pleased to find their favorite looping construct.
|
|
127
131
|
Here again, the Fibbonacci sequence refactored with a `for` loop:
|
128
132
|
|
129
133
|
```javascript
|
134
|
+
// fibbonacci_v2.lox
|
130
135
|
// Fibbonacci sequence - version 2
|
131
136
|
var a = 0;
|
132
137
|
var b = 1;
|
@@ -169,13 +174,69 @@ for (var i = 0; i < count; i = i + 1) {
|
|
169
174
|
}
|
170
175
|
```
|
171
176
|
|
177
|
+
### Loxxy goes meta...
|
178
|
+
The `Loxxy` is able to run the `LoxLox` interpreter.
|
179
|
+
[LoxLox](https://github.com/benhoyt/loxlox) is a Lox interpreter written in Lox by Ben Hoyt.
|
180
|
+
This interpreter with over 1900 lines long is (one of) the longest Lox pragram.
|
181
|
+
As such, it is a good testbed for any Lox interpreter.
|
182
|
+
|
183
|
+
Executing a lox program with the LoxLox interpreter that is itself running on top of Loxxy.
|
184
|
+
#### Step 1 Download `lox.lox´ file
|
185
|
+
Download the [LoxLox](https://github.com/benhoyt/loxlox) source file in Github.
|
186
|
+
|
187
|
+
#### Step 2 (alternative a): running from the command line
|
188
|
+
|
189
|
+
```
|
190
|
+
$ loxxy lox.lox
|
191
|
+
```
|
192
|
+
|
193
|
+
Once loxxy CLI starts its interpreter that, in turn, executes the LoxLox interpreter.
|
194
|
+
This may take a couple of seconds.
|
195
|
+
Don't be surprised, if the program seems unresponsive: it is waiting for you input.
|
196
|
+
Enter a line like this:
|
197
|
+
```
|
198
|
+
print "Hello, world!";
|
199
|
+
```
|
200
|
+
Then terminate with an end of file (crtl-D on Linuxes, crtl-z on Windows) followed by an enter key.
|
201
|
+
You should see the famous greeting.
|
202
|
+
|
203
|
+
#### Step 2 (alternative b): launching the interpreter from Ruby snippet
|
204
|
+
The following snippet executes the LoxLox interpreter and feeds to it the
|
205
|
+
input text. That input text is made available through a StringIO that replaces
|
206
|
+
the `$stdio` device.
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
require 'stringio'
|
210
|
+
require 'loxxy'
|
211
|
+
|
212
|
+
# Place your Lox pragram within the heredoc
|
213
|
+
program = <<-LOX_END
|
214
|
+
print "Hello, world!";
|
215
|
+
LOX_END
|
216
|
+
|
217
|
+
lox_filename = 'lox.lox'
|
218
|
+
File.open(lox_filename, 'r') do |f|
|
219
|
+
source = f.read
|
220
|
+
cfg = { istream: StringIO.new(program, 'r')}
|
221
|
+
lox = Loxxy::Interpreter.new(cfg)
|
222
|
+
lox.evaluate(source)
|
223
|
+
end
|
224
|
+
```
|
225
|
+
|
226
|
+
Save this snippet as a Ruby file, launch Ruby with this file in command line.
|
227
|
+
After a couple of seconds, you'll see the Ruby interpreter that executes the
|
228
|
+
Loxxy interpreter that itself executes the LoxLox interpreter written in Lox.
|
229
|
+
That last interpreter is the one that run the hello world line.
|
230
|
+
|
231
|
+
That's definitively meta...
|
232
|
+
|
172
233
|
This completes our quick tour of `Lox`, to learn more about the language,
|
173
234
|
check the online book [Crafting Interpreters](https://craftinginterpreters.com/ )
|
174
235
|
|
175
236
|
## What's the fuss about Lox?
|
176
237
|
... Nothing...
|
177
238
|
Bob Nystrom designed a language __simple__ enough so that he could present
|
178
|
-
two implementations (
|
239
|
+
two interpreter implementations (a tree-walking one, then a bytecode one) in one single book.
|
179
240
|
|
180
241
|
In other words, __Lox__ contains interesting features found in most general-purpose
|
181
242
|
languages. In addition to that, there are [numerous implementations](https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations) in different languages
|
@@ -202,14 +263,11 @@ There are already a number of programming languages derived from `Lox`...
|
|
202
263
|
### Purpose of this project:
|
203
264
|
- To deliver an open source example of a programming language fully implemented in Ruby
|
204
265
|
(from the scanner and parser to an interpreter).
|
205
|
-
- The implementation should be mature enough to run [LoxLox](https://github.com/benhoyt/loxlox),
|
206
|
-
a Lox interpreter written in Lox.
|
207
266
|
|
208
267
|
### Roadmap
|
209
268
|
- Extend the test suite
|
210
269
|
- Improve the error handling
|
211
270
|
- Improve the documentation
|
212
|
-
- Ability run the LoxLox interpreter
|
213
271
|
|
214
272
|
## Hello world example
|
215
273
|
The next examples show how to use the interpreter directly from Ruby code.
|
@@ -143,63 +143,36 @@ module Loxxy
|
|
143
143
|
# SEMANTIC ACTIONS
|
144
144
|
#####################################
|
145
145
|
|
146
|
-
# rule('program' => 'EOF').as '
|
147
|
-
def reduce_null_program(_production, _range, _tokens, _theChildren)
|
148
|
-
Ast::LoxNoopExpr.new(tokens[0].position)
|
149
|
-
end
|
150
|
-
|
151
|
-
# rule('program' => 'declaration_plus EOF').as ''
|
146
|
+
# rule('program' => 'declaration+ EOF').as ''
|
152
147
|
def reduce_lox_program(_production, _range, tokens, theChildren)
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
theChildren[0] << theChildren[1]
|
159
|
-
end
|
160
|
-
|
161
|
-
# rule('declaration_plus' => 'declaration')
|
162
|
-
def reduce_declaration_plus_end(_production, _range, _tokens, theChildren)
|
163
|
-
[theChildren[0]]
|
148
|
+
if theChildren[0].empty?
|
149
|
+
Ast::LoxNoopExpr.new(tokens[0].position)
|
150
|
+
else
|
151
|
+
LoxSeqDecl.new(tokens[0].position, theChildren[0])
|
152
|
+
end
|
164
153
|
end
|
165
154
|
|
166
155
|
# rule('classDecl' => 'CLASS classNaming class_body')
|
167
156
|
def reduce_class_decl(_production, _range, _tokens, theChildren)
|
168
|
-
|
169
|
-
|
170
|
-
parent = theChildren[1].last
|
171
|
-
else
|
172
|
-
name = theChildren[1]
|
173
|
-
parent = nil
|
174
|
-
end
|
157
|
+
name = theChildren[1].first
|
158
|
+
parent = theChildren[1].last
|
175
159
|
Ast::LoxClassStmt.new(tokens[1].position, name, parent, theChildren[2])
|
176
160
|
end
|
177
161
|
|
178
|
-
# rule('classNaming' => 'IDENTIFIER')
|
179
|
-
def
|
180
|
-
theChildren[
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
super_var = LoxVariableExpr.new(super_token.position, super_token.lexeme)
|
162
|
+
# rule('classNaming' => 'IDENTIFIER (LESS IDENTIFIER)?')
|
163
|
+
def reduce_class_naming(_production, _range, _tokens, theChildren)
|
164
|
+
if theChildren[1].nil?
|
165
|
+
super_var = nil
|
166
|
+
else
|
167
|
+
super_token = theChildren[1].subnodes[1].token
|
168
|
+
super_var = LoxVariableExpr.new(super_token.position, super_token.lexeme)
|
169
|
+
end
|
187
170
|
[theChildren[0].token.lexeme, super_var]
|
188
171
|
end
|
189
172
|
|
190
|
-
# rule('class_body' => 'LEFT_BRACE
|
173
|
+
# rule('class_body' => 'LEFT_BRACE function* RIGHT_BRACE')
|
191
174
|
def reduce_class_body(_production, _range, _tokens, theChildren)
|
192
|
-
theChildren[1]
|
193
|
-
end
|
194
|
-
|
195
|
-
# rule('method_plus' => 'method_plus function')
|
196
|
-
def reduce_method_plus_more(_production, _range, _tokens, theChildren)
|
197
|
-
theChildren[0] << theChildren[1]
|
198
|
-
end
|
199
|
-
|
200
|
-
# rule('method_plus' => 'function')
|
201
|
-
def reduce_method_plus_end(_production, _range, _tokens, theChildren)
|
202
|
-
theChildren
|
175
|
+
theChildren[1]
|
203
176
|
end
|
204
177
|
|
205
178
|
# rule('funDecl' => 'FUN function')
|
@@ -212,16 +185,11 @@ module Loxxy
|
|
212
185
|
return_first_child(range, tokens, theChildren) # Discard the semicolon
|
213
186
|
end
|
214
187
|
|
215
|
-
# rule('varDecl' => 'VAR IDENTIFIER SEMICOLON')
|
188
|
+
# rule('varDecl' => 'VAR IDENTIFIER (EQUAL expression)? SEMICOLON')
|
216
189
|
def reduce_var_declaration(_production, _range, tokens, theChildren)
|
217
190
|
var_name = theChildren[1].token.lexeme.dup
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
# rule('varDecl' => 'VAR IDENTIFIER EQUAL expression SEMICOLON')
|
222
|
-
def reduce_var_initialization(_production, _range, tokens, theChildren)
|
223
|
-
var_name = theChildren[1].token.lexeme.dup
|
224
|
-
Ast::LoxVarStmt.new(tokens[1].position, var_name, theChildren[3])
|
191
|
+
init_val = theChildren[2] ? theChildren[2].subnodes[1] : nil
|
192
|
+
Ast::LoxVarStmt.new(tokens[1].position, var_name, init_val)
|
225
193
|
end
|
226
194
|
|
227
195
|
# rule('forStmt' => 'FOR LEFT_PAREN forControl RIGHT_PAREN statement')
|
@@ -248,7 +216,7 @@ module Loxxy
|
|
248
216
|
for_stmt
|
249
217
|
end
|
250
218
|
|
251
|
-
# rule('forControl' => 'forInitialization forTest
|
219
|
+
# rule('forControl' => 'forInitialization forTest expression?')
|
252
220
|
def reduce_for_control(_production, _range, tokens, theChildren)
|
253
221
|
(init, test, update) = theChildren
|
254
222
|
if test.nil? && update
|
@@ -265,7 +233,7 @@ module Loxxy
|
|
265
233
|
nil
|
266
234
|
end
|
267
235
|
|
268
|
-
# rule('forTest' => '
|
236
|
+
# rule('forTest' => 'expression? SEMICOLON')
|
269
237
|
def reduce_for_test(_production, range, tokens, theChildren)
|
270
238
|
return_first_child(range, tokens, theChildren)
|
271
239
|
end
|
@@ -292,7 +260,7 @@ module Loxxy
|
|
292
260
|
Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
|
293
261
|
end
|
294
262
|
|
295
|
-
# rule('returnStmt' => 'RETURN
|
263
|
+
# rule('returnStmt' => 'RETURN expression? SEMICOLON')
|
296
264
|
def reduce_return_stmt(_production, _range, tokens, theChildren)
|
297
265
|
Ast::LoxReturnStmt.new(tokens[1].position, theChildren[1])
|
298
266
|
end
|
@@ -302,34 +270,31 @@ module Loxxy
|
|
302
270
|
Ast::LoxWhileStmt.new(tokens[1].position, theChildren[2], theChildren[4])
|
303
271
|
end
|
304
272
|
|
305
|
-
# rule('block' => 'LEFT_BRACE
|
273
|
+
# rule('block' => 'LEFT_BRACE declaration* RIGHT_BRACE')
|
306
274
|
def reduce_block_stmt(_production, _range, tokens, theChildren)
|
307
|
-
decls =
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
275
|
+
decls = nil
|
276
|
+
if theChildren[1]
|
277
|
+
pos = tokens[1].position
|
278
|
+
decls = LoxSeqDecl.new(tokens[1].position, theChildren[1])
|
279
|
+
else
|
280
|
+
pos = tokens[0].position
|
281
|
+
end
|
282
|
+
Ast::LoxBlockStmt.new(pos, decls)
|
314
283
|
end
|
315
284
|
|
316
|
-
# rule('assignment' => '
|
285
|
+
# rule('assignment' => '(call DOT)? IDENTIFIER EQUAL assignment')
|
317
286
|
def reduce_assign_expr(_production, _range, tokens, theChildren)
|
318
287
|
name_assignee = theChildren[1].token.lexeme.dup
|
319
|
-
if theChildren[0]
|
320
|
-
theChildren[0].
|
321
|
-
|
322
|
-
theChildren[
|
288
|
+
if theChildren[0]
|
289
|
+
set_expr = Ast::LoxSetExpr.new(tokens[1].position, theChildren[0].subnodes[0])
|
290
|
+
set_expr.property = name_assignee
|
291
|
+
set_expr.value = theChildren[3]
|
292
|
+
set_expr
|
323
293
|
else
|
324
294
|
Ast::LoxAssignExpr.new(tokens[1].position, name_assignee, theChildren[3])
|
325
295
|
end
|
326
296
|
end
|
327
297
|
|
328
|
-
# rule('owner_opt' => 'call DOT')
|
329
|
-
def reduce_set_expr(_production, _range, tokens, theChildren)
|
330
|
-
Ast::LoxSetExpr.new(tokens[1].position, theChildren[0])
|
331
|
-
end
|
332
|
-
|
333
298
|
|
334
299
|
# rule('comparisonTest_plus' => 'comparisonTest_plus comparisonTest term').as 'comparison_t_plus_more'
|
335
300
|
# TODO: is it meaningful to implement this rule?
|
@@ -343,6 +308,7 @@ module Loxxy
|
|
343
308
|
|
344
309
|
# rule('call' => 'primary refinement_plus').as 'call_expr'
|
345
310
|
def reduce_call_expr(_production, _range, _tokens, theChildren)
|
311
|
+
# return theChildren[0] unless theChildren[1]
|
346
312
|
members = theChildren.flatten
|
347
313
|
call_expr = nil
|
348
314
|
loop do
|
@@ -365,7 +331,7 @@ module Loxxy
|
|
365
331
|
theChildren
|
366
332
|
end
|
367
333
|
|
368
|
-
# rule('refinement' => 'LEFT_PAREN
|
334
|
+
# rule('refinement' => 'LEFT_PAREN arguments? RIGHT_PAREN')
|
369
335
|
def reduce_call_arglist(_production, _range, tokens, theChildren)
|
370
336
|
args = theChildren[1] || []
|
371
337
|
if args.size > 255
|
@@ -395,9 +361,10 @@ module Loxxy
|
|
395
361
|
end
|
396
362
|
|
397
363
|
# rule('primary' => 'IDENTIFIER')
|
398
|
-
def reduce_variable_expr(_production, _range,
|
364
|
+
def reduce_variable_expr(_production, _range, _tokens, theChildren)
|
399
365
|
var_name = theChildren[0].token.lexeme
|
400
|
-
|
366
|
+
pos = theChildren[0].token.position
|
367
|
+
LoxVariableExpr.new(pos, var_name)
|
401
368
|
end
|
402
369
|
|
403
370
|
# rule('primary' => 'THIS')
|
@@ -421,24 +388,21 @@ module Loxxy
|
|
421
388
|
LoxFunStmt.new(pos, first_child.token.lexeme, theChildren[2], theChildren[4])
|
422
389
|
end
|
423
390
|
|
424
|
-
# rule('parameters' => '
|
425
|
-
def
|
426
|
-
|
427
|
-
|
391
|
+
# rule('parameters' => 'IDENTIFIER (COMMA IDENTIFIER)*').as 'parameters'
|
392
|
+
def reduce_parameters(_production, _range, _tokens, theChildren)
|
393
|
+
first_lexeme = theChildren[0].token.lexeme
|
394
|
+
return [first_lexeme] unless theChildren[1]
|
428
395
|
|
429
|
-
|
430
|
-
|
431
|
-
[theChildren[0].token.lexeme]
|
396
|
+
successors = theChildren[1].map { |seq_node| seq_node.subnodes[1].token.lexeme }
|
397
|
+
successors.unshift(first_lexeme)
|
432
398
|
end
|
433
399
|
|
434
|
-
# rule('arguments' => '
|
435
|
-
def
|
436
|
-
theChildren[0]
|
437
|
-
end
|
400
|
+
# rule('arguments' => 'expression (COMMA expression)*')
|
401
|
+
def reduce_arguments(_production, _range, _tokens, theChildren)
|
402
|
+
return [theChildren[0]] unless theChildren[1]
|
438
403
|
|
439
|
-
|
440
|
-
|
441
|
-
theChildren
|
404
|
+
successors = theChildren[1].map { |seq_node| seq_node.subnodes[1] }
|
405
|
+
successors.unshift(theChildren[0])
|
442
406
|
end
|
443
407
|
end # class
|
444
408
|
end # module
|