loxxy 0.0.16 → 0.0.21
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 +60 -1
- data/README.md +155 -52
- data/lib/loxxy/ast/all_lox_nodes.rb +7 -1
- data/lib/loxxy/ast/ast_builder.rb +57 -3
- data/lib/loxxy/ast/ast_visitor.rb +62 -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/ast/lox_var_stmt.rb +28 -0
- data/lib/loxxy/back_end/engine.rb +71 -4
- data/lib/loxxy/back_end/entry.rb +41 -0
- data/lib/loxxy/back_end/environment.rb +66 -0
- data/lib/loxxy/back_end/symbol_table.rb +135 -0
- data/lib/loxxy/back_end/variable.rb +25 -0
- data/lib/loxxy/datatype/builtin_datatype.rb +55 -0
- data/lib/loxxy/datatype/false.rb +14 -8
- data/lib/loxxy/datatype/lx_string.rb +0 -14
- data/lib/loxxy/datatype/nil.rb +12 -6
- data/lib/loxxy/datatype/number.rb +44 -6
- data/lib/loxxy/datatype/true.rb +1 -9
- data/lib/loxxy/front_end/grammar.rb +7 -7
- data/lib/loxxy/interpreter.rb +1 -1
- data/lib/loxxy/version.rb +1 -1
- data/spec/back_end/engine_spec.rb +8 -0
- data/spec/back_end/environment_spec.rb +74 -0
- data/spec/back_end/symbol_table_spec.rb +142 -0
- data/spec/back_end/variable_spec.rb +79 -0
- data/spec/front_end/parser_spec.rb +4 -4
- data/spec/interpreter_spec.rb +152 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fd4cbf32f4ee44a60c45630a76318425850dc35b4d9f6129274cefcbf4e91fcc
|
4
|
+
data.tar.gz: 711e0ae07d2a0b3a080c2fe408d9adf4f7b96bb070af686d66dd3f9dbae8391d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 131f6fe3b23dc0a84b063efe70744b02ecc9edb68742540799964311298f35494a0d48db75bb18a240ddeed039286ab08ba2ef99e2ae4857d2b4d5dc4403d5ba
|
7
|
+
data.tar.gz: b46c18f54147fd01f9819e3ad06564ee78fe72de5c91d6ef8a5bef5945d9f1ad622cad848c4d521ae66f00c91b7825d01e57c831b2a097da830bec0d99f2cf06
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,62 @@
|
|
1
|
+
## [0.0.21] - 2021-01-1x
|
2
|
+
- The interpreter supports the declaration global variables.
|
3
|
+
|
4
|
+
## Added
|
5
|
+
- Class `BackEnd::Entry`, mixin module for objects put in the symbol table
|
6
|
+
- Class `BackEnd::Environment` that keeps track of variables in a given context.
|
7
|
+
- Class `BackEnd::SymbolTable` that keeps track of environments.
|
8
|
+
- Class `BackEnd::Variable` internal representation of a `Lox` variable
|
9
|
+
- Method `Ast::ASTBuilder#reduce_var_declaration` and `Ast::ASTBuilder#reduce_var_declaration`
|
10
|
+
- Method `Ast::ASTVisitor#visit_var_stmt` for visiting `LoxVarStmt` nodes
|
11
|
+
- Attribute `Engine::symbol_table`for keeping track of variables
|
12
|
+
- Method `Engine::after_var_stmt` for the implementation of variable declarations
|
13
|
+
|
14
|
+
## [0.0.20] - 2021-01-15
|
15
|
+
- The interpreter supports the `if` ... `else` statement.
|
16
|
+
|
17
|
+
## Added
|
18
|
+
- Class `Ast::LoxItStmt`, AST node specific for `if` `else` statements
|
19
|
+
- Method `Ast::ASTBuilder#reduce_if_stmt` as semantic action for if ... else
|
20
|
+
- Method `Ast::ASTVisitor#visit_if_stmt` for visiting `LoxIfStmt` nodes
|
21
|
+
- Method `Engine::after_if_stmt` implementation of the control flow
|
22
|
+
|
23
|
+
## [0.0.19] - 2021-01-14
|
24
|
+
- The interpreter supports expressions between parentheses (grouping).
|
25
|
+
|
26
|
+
## Added
|
27
|
+
- Class `Ast::LoxLogicalExpr`
|
28
|
+
- Method `Ast::ASTBuilder#reduce_grouping_expr` as semantic action for grouping expression
|
29
|
+
- Method `Ast::ASTVisitor#visit_grouping_expr` for visiting grouping expressions
|
30
|
+
- Method `Engine::after_grouping_expr`for the evaluation of grouping expressions
|
31
|
+
|
32
|
+
## Changed
|
33
|
+
- File `grammar.rb` rules for if ... else were given names in order to activate semantic actions.
|
34
|
+
- File `README.md` updated with little `if ... else` documentation.
|
35
|
+
|
36
|
+
## [0.0.18] - 2021-01-13
|
37
|
+
- The interpreter can evaluate `and`, `or`expressions.
|
38
|
+
|
39
|
+
## Added
|
40
|
+
- Class `Ast::LoxLogicalExpr`
|
41
|
+
- Method `Ast::ASTBuilder#reduce_logical_expr` for the semantic action require for `and`, `or`
|
42
|
+
- Method `Ast::ASTVisitor#visit_logical_expr` for visiting logical expressions
|
43
|
+
- Method `Backend::Engine#after_logical_expr` implements the evaluation of the logical expressions
|
44
|
+
|
45
|
+
## [0.0.17] - 2021-01-12
|
46
|
+
- The interpreter can evaluate all arithmetic and comparison operations.
|
47
|
+
- It implements `==`, `!=` and the unary operations `!`, `-`
|
48
|
+
|
49
|
+
## Added
|
50
|
+
- Class `Ast::LoxUnaryExpr`
|
51
|
+
- Method `Ast::ASTBuilder#reduce_unary_expr` to support the evaluation of `!` and ``-@`
|
52
|
+
- Method `Ast::ASTVisitor#visit_unnary_expr` for visiting unary expressions
|
53
|
+
- Method `Backend::Engine#after_unary_expr` evaluating an unary expression
|
54
|
+
- In class `Datatype::BuiltinDatatype` the methods `falsey?`, `truthy?`, `!`, `!=`
|
55
|
+
- In class `Datatype::Number`the methods `<`, `<=`, ´>´, `>=` and `-@`
|
56
|
+
|
57
|
+
## Changed
|
58
|
+
- File `README.md` updated.
|
59
|
+
|
1
60
|
## [0.0.16] - 2021-01-11
|
2
61
|
- The interpreter can evaluate product and division of two numbers.
|
3
62
|
- It also implements equality `==` and inequality `!=` operators
|
@@ -36,7 +95,7 @@
|
|
36
95
|
- The interpreter can evaluate addition of numbers and string concatenation
|
37
96
|
|
38
97
|
## Added
|
39
|
-
- Method `Ast::ASTVisitor
|
98
|
+
- Method `Ast::ASTVisitor#visit_binary_expr` for visiting binary expressions
|
40
99
|
- Method `Ast::LoxBinaryExpr#accept` for visitor pattern
|
41
100
|
- Method `BackEnd::Engine#after_binary_expr` to trigger execution of binary operator
|
42
101
|
- `Boolean` class hierarchy: added methos `true?` and `false?` to ease spec test writing
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ a simple language used in Bob Nystrom's online book [Crafting Interpreters](http
|
|
8
8
|
|
9
9
|
### Purpose of this project:
|
10
10
|
- To deliver an open source example of a programming language fully implemented in Ruby
|
11
|
-
(from the scanner
|
11
|
+
(from the scanner and parser to an interpreter).
|
12
12
|
- The implementation should be mature enough to run [LoxLox](https://github.com/benhoyt/loxlox),
|
13
13
|
a Lox interpreter written in Lox.
|
14
14
|
|
@@ -128,16 +128,22 @@ 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
|
+
- [Variable declarations](#var-statement)
|
145
|
+
- [If Statement](#if-statement)
|
146
|
+
- [Print Statement](#print-statement)
|
141
147
|
|
142
148
|
### Comments
|
143
149
|
|
@@ -148,41 +154,10 @@ Loxxy supports single line C-style comments.
|
|
148
154
|
```
|
149
155
|
|
150
156
|
### Keywords
|
151
|
-
|
152
|
-
The parser knows all the __Lox__ reserved keywords:
|
157
|
+
Loxxy implements the following __Lox__ reserved keywords:
|
153
158
|
```lang-none
|
154
|
-
and,
|
155
|
-
print, return, super, this, true, var, while
|
159
|
+
and, false, nil, or, print, true
|
156
160
|
```
|
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
|
-
`*` (product of two numbers)
|
170
|
-
`/` (division of two number)
|
171
|
-
`==` and `!=` (in)equality testing of two Lox values
|
172
|
-
|
173
|
-
#### Delimiters
|
174
|
-
The parser knows all the __Lox__ grouping delimiters:
|
175
|
-
(`, ), `{`, `}`
|
176
|
-
|
177
|
-
These aren't yet implemented in the interpreter.
|
178
|
-
|
179
|
-
The other characters that have a special meaning in __Lox__ are:
|
180
|
-
- `,` Used in parameter list
|
181
|
-
- `.` For the dot notation (i.e. calling a method)
|
182
|
-
- `;` The semicolon is used to terminates expressions
|
183
|
-
- `=` Assignment
|
184
|
-
|
185
|
-
The parser recognizes them all but the interpreter accepts the semicolons only.
|
186
161
|
|
187
162
|
### Datatypes
|
188
163
|
|
@@ -192,22 +167,150 @@ loxxy supports all the standard __Lox__ datatypes:
|
|
192
167
|
- `String`: Sequence of characters surrounded by `"`. For example: `"Hello!"`
|
193
168
|
- `Nil`: Used to define a null value, denoted by the `nil` keyword
|
194
169
|
|
195
|
-
|
196
|
-
|
197
|
-
Loxxy
|
198
|
-
-
|
199
|
-
-
|
200
|
-
-
|
201
|
-
- (
|
170
|
+
### Statements
|
171
|
+
|
172
|
+
Loxxy supports the following statements:
|
173
|
+
- [Expressions](#expressions)
|
174
|
+
-[Arithmetic expressions](#arithmetic-expressions)
|
175
|
+
-[String concatenation](#string-concatenation)
|
176
|
+
-[Comparison expressions](#comparison-expressions)
|
177
|
+
-[Logical expressions](#logical-expressions)
|
178
|
+
-[Grouping expressions](#grouping-expressions)
|
179
|
+
|
180
|
+
-[Variable declarations](#var-statement)
|
181
|
+
-[If Statement](#if-statement)
|
182
|
+
-[Print Statement](#print-statement)
|
183
|
+
|
184
|
+
#### Expressions
|
185
|
+
|
186
|
+
##### Arithmetic expressions
|
187
|
+
Loxxy supports the following operators for arithmetic expressions:
|
188
|
+
|
189
|
+
- `+`: Adds of two numbers. Both operands must be of the type Number
|
190
|
+
E.g. `37 + 5; // => 42`
|
191
|
+
`7 + -3; // => 4`
|
192
|
+
- `-`: (Binary) Subtracts right operand from left operand. Both operands must be numbers.
|
193
|
+
E.g. `47 - 5; // => 42`
|
194
|
+
- `-`: (Unary) Negates (= changes the sign) of the given number operand.
|
195
|
+
E.g. `- -3; // => 3`
|
196
|
+
- `*`: Multiplies two numbers
|
197
|
+
E.g. `2 * 3; // => 6`
|
198
|
+
- `/`: Divides two numbers
|
199
|
+
E.g. `8 / 2; // => 4`
|
200
|
+
`5 / 2; // => 2.5`
|
201
|
+
|
202
|
+
##### String concatenation
|
203
|
+
- `+`: Concatenates two strings. Both operands must be of the String type.
|
204
|
+
E.g. `"Hello" + ", " + "world! // => "Hello, world!"`
|
205
|
+
|
206
|
+
##### Comparison expressions
|
207
|
+
|
208
|
+
- `==`: Returns `true` if left operand is equal to right operand, otherwise `false`
|
209
|
+
E.g. `false == false; // => true`
|
210
|
+
`5 + 2 == 3 + 4; // => true`
|
211
|
+
`"" == ""; // => true`
|
212
|
+
- `!=`: Returns `true` if left operand is not equal to right operand, otherwise `false`
|
213
|
+
E.g. `false != "false"; // => true`
|
214
|
+
`5 + 2 != 4 + 3; // => false`
|
215
|
+
- `<`: Returns `true` if left operand is less than right operand, otherwise `false`. Both operands must be numbers
|
216
|
+
E.g. `1 < 3; // => true`
|
217
|
+
`1 < 0; // => false`
|
218
|
+
`2 < 2; // => false`
|
219
|
+
- `<=`: Returns `true` if left operand is equal to right operand, otherwise `false`. Both operands must be numbers
|
220
|
+
E.g. `1 <= 3; // => true`
|
221
|
+
`1 <= 0; // => false`
|
222
|
+
`2 <= 2; // => true`
|
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
|
+
- `>=`: Returns `true` if left operand is equal to right operand, otherwise `false`. Both operands must be numbers
|
228
|
+
E.g. `1 > 3; // => false`
|
229
|
+
`1 > 0; // => true`
|
230
|
+
`2 > 2; // => false`
|
231
|
+
|
232
|
+
##### Logical expressions
|
233
|
+
|
234
|
+
REMINDER: In __Lox__, `false` and `nil` are considered falsey, everything else is truthy.
|
235
|
+
|
236
|
+
- `and`: When both operands are booleans, then returns `true` if both left and right operands are truthy, otherwise `false`.
|
237
|
+
If at least one operand isn't a boolean then returns first falsey operand else (both operands are truthy) returns the second operand.
|
238
|
+
truthy returns the second operand.
|
239
|
+
E.g. `false and true; // => false`
|
240
|
+
`true and nil; // => nil`
|
241
|
+
`0 and true and ""; // => ""`
|
242
|
+
- `or`: When both operands are booleans, then returns `true` if left or right operands are truthy, otherwise `false`.
|
243
|
+
If at least one operand isn't a boolean then returns first truthy operand else (both operands are truthy) returns the second operand.
|
244
|
+
E.g. `false or true; // => true`
|
245
|
+
`true or nil; // => nil`
|
246
|
+
`false or nil; // => nil`
|
247
|
+
`0 or true or ""; // => 0`
|
248
|
+
- `!`: Performs a logical negation on its operand
|
249
|
+
E.g. `!false; // => true`
|
250
|
+
`!!true; // => true`
|
251
|
+
`!0; // => false`
|
252
|
+
|
253
|
+
#### Grouping expressions
|
254
|
+
Use parentheses `(` `)` for a better control in expression/operator precedence.
|
255
|
+
|
256
|
+
``` javascript
|
257
|
+
print 3 + 4 * 5; // => 23
|
258
|
+
print (3 + 4) * 5; // => 35
|
259
|
+
```
|
260
|
+
|
261
|
+
#### Variable declarations
|
262
|
+
``` javascript
|
263
|
+
var iAmAVariable = "my-initial-value";
|
264
|
+
var iAmNil; // __Lox__ initializes variables to nil by default;
|
265
|
+
```
|
202
266
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
267
|
+
Warning: current version cannot retrieve the value of a variable.
|
268
|
+
Expect this capability to be implemented in the coming days.
|
269
|
+
|
270
|
+
|
271
|
+
#### If statement
|
272
|
+
|
273
|
+
Based on a given condition, an if statement executes one of two statements:
|
274
|
+
``` javascript
|
275
|
+
if (condition) {
|
276
|
+
print "then-branch";
|
277
|
+
} else {
|
278
|
+
print "else-branch";
|
279
|
+
}
|
280
|
+
```
|
281
|
+
|
282
|
+
As for other languages, the `else` part is optional.
|
283
|
+
##### Warning: nested `if`...`else`
|
284
|
+
Call it a bug ... Nested `if` `else` control flow structure aren't yet supported by __Loxxy__.
|
285
|
+
The culprit has a name: [the dangling else](https://en.wikipedia.org/wiki/Dangling_else).
|
286
|
+
|
287
|
+
The problem in a nutshell: in a nested if ... else ... statement like this:
|
288
|
+
``` javascript
|
289
|
+
'if (true) if (false) print "bad"; else print "good";
|
290
|
+
```
|
291
|
+
... there is an ambiguity. Indeed, according to the __Lox__ grammar, the `else` could be bound
|
292
|
+
either to the first `if` or to the second one.
|
293
|
+
This ambiguity is usually lifted by applying an ad-hoc rule: an `else` is aways bound to the most
|
294
|
+
recent (rightmost) `if`.
|
295
|
+
Being a generic parsing library, `Rley` doesn't apply any of these supplemental rules.
|
296
|
+
As a consequence,it complains about the found ambiguity and stops the parsing...
|
297
|
+
Although `Rley` can cope with ambiguities, this requires the use of an advanced data structure
|
298
|
+
called `Shared Packed Parse Forest (SPPF)`.
|
299
|
+
SPPF are much more complex to handle than the `common` parse trees present in most compiler or interpreter books.
|
300
|
+
Therefore, a future version of `Rley` will incorporate the capability to define disambuiguation rules.
|
301
|
+
|
302
|
+
In the meantime, the `Loxxy` will progress on other __Lox__ features like:
|
303
|
+
- Variables,
|
304
|
+
- Block structures...
|
305
|
+
|
306
|
+
|
307
|
+
#### Print Statement
|
308
|
+
|
309
|
+
The statement print + expression + ; prints the result of the expression to stdout.
|
310
|
+
|
311
|
+
``` javascript
|
312
|
+
print "Hello, world!"; // Output: Hello, world!
|
207
313
|
|
208
|
-
```javascript
|
209
|
-
// Print statement with nested concatenation
|
210
|
-
print "Hello" + ", " + "world!";
|
211
314
|
```
|
212
315
|
|
213
316
|
## Installation
|
@@ -1,5 +1,11 @@
|
|
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'
|
11
|
+
require_relative 'lox_var_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,27 @@ module Loxxy
|
|
138
158
|
return_first_child(range, tokens, theChildren) # Discard the semicolon
|
139
159
|
end
|
140
160
|
|
161
|
+
# rule('varDecl' => 'VAR IDENTIFIER SEMICOLON')
|
162
|
+
def reduce_var_declaration(_production, _range, tokens, theChildren)
|
163
|
+
var_name = theChildren[1].token.lexeme.dup
|
164
|
+
Ast::LoxVarStmt.new(tokens[1].position, var_name, nil)
|
165
|
+
end
|
166
|
+
|
167
|
+
# rule('varDecl' => 'VAR IDENTIFIER EQUAL expression SEMICOLON')
|
168
|
+
def reduce_var_initialization(_production, _range, tokens, theChildren)
|
169
|
+
var_name = theChildren[1].token.lexeme.dup
|
170
|
+
Ast::LoxVarStmt.new(tokens[1].position, var_name, theChildren[3])
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
# rule('ifStmt' => 'IF ifCondition statement elsePart_opt')
|
175
|
+
def reduce_if_stmt(_production, _range, tokens, theChildren)
|
176
|
+
condition = theChildren[1]
|
177
|
+
then_stmt = theChildren[2]
|
178
|
+
else_stmt = theChildren[3]
|
179
|
+
LoxIfStmt.new(tokens[0].position, condition, then_stmt, else_stmt)
|
180
|
+
end
|
181
|
+
|
141
182
|
# rule('printStmt' => 'PRINT expression SEMICOLON')
|
142
183
|
def reduce_print_stmt(_production, _range, tokens, theChildren)
|
143
184
|
Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
|
@@ -145,7 +186,7 @@ module Loxxy
|
|
145
186
|
|
146
187
|
# rule('logic_or' => 'logic_and disjunct_plus')
|
147
188
|
def reduce_logic_or_plus(production, range, tokens, theChildren)
|
148
|
-
|
189
|
+
reduce_logical_expr(production, range, tokens, theChildren)
|
149
190
|
end
|
150
191
|
|
151
192
|
# rule('disjunct_plus' => 'disjunct_plus OR logic_and')
|
@@ -160,7 +201,7 @@ module Loxxy
|
|
160
201
|
|
161
202
|
# rule('logic_and' => 'equality conjunct_plus')
|
162
203
|
def reduce_logic_and_plus(production, range, tokens, theChildren)
|
163
|
-
|
204
|
+
reduce_logical_expr(production, range, tokens, theChildren)
|
164
205
|
end
|
165
206
|
|
166
207
|
# rule('conjunct_plus' => 'conjunct_plus AND equality')
|
@@ -231,6 +272,19 @@ module Loxxy
|
|
231
272
|
reduce_binary_plus_end(production, range, tokens, theChildren)
|
232
273
|
end
|
233
274
|
|
275
|
+
# rule('unary' => 'unaryOp unary')
|
276
|
+
def reduce_unary_expr(_production, _range, tokens, theChildren)
|
277
|
+
operator = Name2unary[theChildren[0].symbol.name].to_sym
|
278
|
+
operand = theChildren[1]
|
279
|
+
LoxUnaryExpr.new(tokens[0].position, operator, operand)
|
280
|
+
end
|
281
|
+
|
282
|
+
# rule('primary' => 'LEFT_PAREN expression RIGHT_PAREN')
|
283
|
+
def reduce_grouping_expr(_production, _range, tokens, theChildren)
|
284
|
+
subexpr = theChildren[1]
|
285
|
+
LoxGroupingExpr.new(tokens[0].position, subexpr)
|
286
|
+
end
|
287
|
+
|
234
288
|
# rule('primary' => 'FALSE' | TRUE').as 'literal_expr'
|
235
289
|
def reduce_literal_expr(_production, _range, _tokens, theChildren)
|
236
290
|
first_child = theChildren.first
|