loxxy 0.0.7 → 0.0.12
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/CHANGELOG.md +53 -0
- data/README.md +37 -20
- data/lib/loxxy.rb +23 -2
- data/lib/loxxy/ast/all_lox_nodes.rb +5 -0
- data/lib/loxxy/ast/ast_builder.rb +158 -17
- data/lib/loxxy/ast/ast_visitor.rb +36 -56
- data/lib/loxxy/ast/lox_compound_expr.rb +1 -1
- data/lib/loxxy/ast/lox_node.rb +5 -0
- data/lib/loxxy/ast/lox_noop_expr.rb +16 -0
- data/lib/loxxy/ast/lox_print_stmt.rb +22 -0
- data/lib/loxxy/back_end/engine.rb +48 -0
- data/lib/loxxy/datatype/builtin_datatype.rb +6 -0
- data/lib/loxxy/datatype/lx_string.rb +6 -0
- data/lib/loxxy/datatype/nil.rb +6 -0
- data/lib/loxxy/front_end/grammar.rb +21 -21
- data/lib/loxxy/interpreter.rb +38 -0
- data/lib/loxxy/version.rb +1 -1
- data/spec/back_end/engine_spec.rb +43 -0
- data/spec/datatype/boolean_spec.rb +31 -0
- data/spec/datatype/lx_string_spec.rb +4 -0
- data/spec/datatype/nil_spec.rb +26 -0
- data/spec/datatype/number_spec.rb +31 -0
- data/spec/front_end/parser_spec.rb +223 -27
- data/spec/front_end/scanner_spec.rb +12 -0
- data/spec/interpreter_spec.rb +37 -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: 7274fd2d139354b984962f9317cae890344e528540f2f157772e7395cdfd7d33
|
4
|
+
data.tar.gz: c1b38a4dfcb441c00604926cbaf397ab555624270ca647448d9cc4d4f463f500
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27d5de6532213d1a995f86da84ccbd41a11b5f85c305e57a62f64637ad17852e622685e4261b1c62deb31c924bb8f8c29c4edd97e9776fabf7e0d06e5c302534
|
7
|
+
data.tar.gz: dab4a9e391c120c159a63e316f90065faf1415b54c9aa4c6f349f6be8e95de1289a2478f395e6b9e19b2e6f09482ae4db49a70e0d5d857eb5475cecad0590c69
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,56 @@
|
|
1
|
+
## [0.0.12] - 2021-01-09
|
2
|
+
- Initial interpreter capable of evaluating a tiny subset of Lox language.
|
3
|
+
|
4
|
+
## Added
|
5
|
+
- Class `AST::LoxNoopExpr`
|
6
|
+
- Class `AST::LoxPrintStmt`
|
7
|
+
- Class `BackEnd::Engine` implementation of the print statement logic
|
8
|
+
- Class `Interpreter`
|
9
|
+
|
10
|
+
## Changed
|
11
|
+
- Class `Ast::ASTVisitor` Added visit method
|
12
|
+
- File `README.md` added Hello world example.
|
13
|
+
|
14
|
+
## [0.0.11] - 2021-01-08
|
15
|
+
- AST node generation for logical expression (and, or).
|
16
|
+
|
17
|
+
## Changed
|
18
|
+
- Class `AST::ASTBuilder` added `reduce_` methods for logical operations.
|
19
|
+
- File `grammar.rb`added name to logical expression rules
|
20
|
+
- File `README.md` added gem version and license badges, expanded roadmap section.
|
21
|
+
|
22
|
+
## Fixed
|
23
|
+
- File `grammar.rb`: a rule had incomplete non-terminal name `conjunct_` in its lhs.
|
24
|
+
|
25
|
+
|
26
|
+
## [0.0.10] - 2021-01-08
|
27
|
+
- AST node generation for equality expression.
|
28
|
+
|
29
|
+
## Changed
|
30
|
+
- Class `AST::ASTBuilder` refactoring and added `reduce_` methods for equality operations.
|
31
|
+
- File `grammar.rb`added name to equality rules
|
32
|
+
- File `README.md` added gem version and license badges, expanded roadmap section.
|
33
|
+
|
34
|
+
## Fixed
|
35
|
+
- File `grammar.rb`: a rule had still the discarded non-terminal `equalityTest_star` in its lhs.
|
36
|
+
|
37
|
+
## [0.0.9] - 2021-01-07
|
38
|
+
- AST node generation for comparison expression.
|
39
|
+
|
40
|
+
## Changed
|
41
|
+
- Class `AST::ASTBuilder` added `reduce_` methods for comparison operations.
|
42
|
+
- File `grammar.rb`added name to comparison rules
|
43
|
+
|
44
|
+
## [0.0.8] - 2021-01-07
|
45
|
+
- AST node generation for arithmetic operations of number literals.
|
46
|
+
|
47
|
+
## Changed
|
48
|
+
- Class `AST::ASTBuilder` added `reduce_` methods for arithmetic operations.
|
49
|
+
- File `grammar.rb`added name to arithmetic rules
|
50
|
+
|
51
|
+
## Fixed
|
52
|
+
- File `grammar.rb`: second rule for `factor` had a missing member in rhs.
|
53
|
+
|
1
54
|
## [0.0.7] - 2021-01-06
|
2
55
|
- Lox grammar reworked, initial AST classes created.
|
3
56
|
|
data/README.md
CHANGED
@@ -1,4 +1,7 @@
|
|
1
|
-
#
|
1
|
+
# loxxy
|
2
|
+
[](https://badge.fury.io/rb/loxxy)
|
3
|
+
[](https://github.com/famished-tiger/loxxy/blob/main/LICENSE.txt)
|
4
|
+
|
2
5
|
|
3
6
|
A Ruby implementation of the [Lox programming language](https://craftinginterpreters.com/the-lox-language.html ),
|
4
7
|
a simple language used in Bob Nystrom's online book [Crafting Interpreters](https://craftinginterpreters.com/ ).
|
@@ -6,25 +9,30 @@ a simple language used in Bob Nystrom's online book [Crafting Interpreters](http
|
|
6
9
|
## Purpose of this project:
|
7
10
|
- To deliver an open source example of a programming language fully implemented in Ruby
|
8
11
|
(from the scanner, parser, code generation).
|
9
|
-
- The implementation should be mature enough to run (
|
12
|
+
- The implementation should be mature enough to run [LoxLox](https://github.com/benhoyt/loxlox),
|
10
13
|
a Lox interpreter written in Lox.
|
11
14
|
|
12
|
-
##
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
15
|
+
## Current status
|
16
|
+
The project is still in inception and the interpreter is being implemented...
|
17
|
+
Currently it can execute a very limited subset of __Lox__ language.
|
18
|
+
|
19
|
+
The __loxxy__ gem also a parser class `RawPaser` that can, in principle, any valid Lox input.
|
20
|
+
|
21
|
+
## Hello world example
|
22
|
+
```ruby
|
23
|
+
require 'loxxy'
|
24
|
+
|
25
|
+
lox_program = <<LOX_END
|
26
|
+
// Your first Lox program!
|
27
|
+
print "Hello, world!";
|
28
|
+
LOX_END
|
29
|
+
|
30
|
+
lox = Loxxy::Interpreter.new
|
31
|
+
lox.evaluate(lox_program) # => Hello, world!
|
32
|
+
```
|
33
|
+
|
34
|
+
## Example using RawParser class
|
35
|
+
|
28
36
|
```ruby
|
29
37
|
require 'loxxy'
|
30
38
|
|
@@ -69,6 +77,15 @@ program
|
|
69
77
|
+-- EOF: ''
|
70
78
|
```
|
71
79
|
|
80
|
+
## Suppported Lox language features
|
81
|
+
Although the interpreter should parse almost any valid Lox program,
|
82
|
+
it currently can evaluate a tiny set of AST node (AST = Abstract Syntax Tree).
|
83
|
+
|
84
|
+
Here are the language features supported by the interpreter:
|
85
|
+
- Line comments,
|
86
|
+
- All the Lox literals (booleans, numbers, strings and nil),
|
87
|
+
- `print` statement.
|
88
|
+
|
72
89
|
|
73
90
|
## Installation
|
74
91
|
|
@@ -91,9 +108,9 @@ Or install it yourself as:
|
|
91
108
|
TODO: Write usage instructions here
|
92
109
|
|
93
110
|
## Other Lox implementations in Ruby
|
94
|
-
An impressive list of Lox implementations can be found [here](https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations
|
111
|
+
An impressive list of Lox implementations can be found [here](https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations)
|
95
112
|
|
96
|
-
For Ruby,
|
113
|
+
For Ruby, there is the [lox](https://github.com/rdodson41/ruby-lox) gem.
|
97
114
|
There are other Ruby-based projects as well:
|
98
115
|
- [SlowLox](https://github.com/ArminKleinert/SlowLox), described as a "1-to-1 conversion of JLox to Ruby"
|
99
116
|
- [rulox](https://github.com/LevitatingBusinessMan/rulox)
|
data/lib/loxxy.rb
CHANGED
@@ -1,10 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'loxxy/version'
|
4
|
+
require_relative 'loxxy/interpreter'
|
4
5
|
require_relative 'loxxy/front_end/raw_parser'
|
5
|
-
require_relative 'loxxy/front_end/parser'
|
6
6
|
|
7
|
+
# Namespace for all classes and constants of __loxxy__ gem.
|
7
8
|
module Loxxy
|
8
9
|
class Error < StandardError; end
|
9
|
-
|
10
|
+
|
11
|
+
# Shorthand method. Returns the sole object that represents
|
12
|
+
# a Lox false literal.
|
13
|
+
# @return [Loxxy::Datatype::False]
|
14
|
+
def self.lox_false
|
15
|
+
Datatype::False.instance
|
16
|
+
end
|
17
|
+
|
18
|
+
# Shorthand method. Returns the sole object that represents
|
19
|
+
# a Lox nil literal.
|
20
|
+
# @return [Loxxy::Datatype::Nil]
|
21
|
+
def self.lox_nil
|
22
|
+
Datatype::Nil.instance
|
23
|
+
end
|
24
|
+
|
25
|
+
# Shorthand method. Returns the sole object that represents
|
26
|
+
# a Lox true literal.
|
27
|
+
# @return [Loxxy::Datatype::True]
|
28
|
+
def self.lox_true
|
29
|
+
Datatype::False.instance
|
30
|
+
end
|
10
31
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../datatype/all_datatypes'
|
4
|
-
require_relative '
|
4
|
+
require_relative 'all_lox_nodes'
|
5
5
|
require_relative 'lox_binary_expr'
|
6
6
|
|
7
7
|
module Loxxy
|
@@ -10,13 +10,33 @@ module Loxxy
|
|
10
10
|
# (Abstract Syntax Tree) from a sequence of input tokens and
|
11
11
|
# visit events produced by walking over a GFGParsing object.
|
12
12
|
class ASTBuilder < Rley::ParseRep::ASTBaseBuilder
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
unless defined?(Name2special)
|
14
|
+
# Mapping Token name => operator | separator | delimiter characters
|
15
|
+
# @return [Hash{String => String}]
|
16
|
+
Name2special = {
|
17
|
+
'AND' => 'and',
|
18
|
+
'BANG' => '!',
|
19
|
+
'BANG_EQUAL' => '!=',
|
20
|
+
'COMMA' => ',',
|
21
|
+
'DOT' => '.',
|
22
|
+
'EQUAL' => '=',
|
23
|
+
'EQUAL_EQUAL' => '==',
|
24
|
+
'GREATER' => '>',
|
25
|
+
'GREATER_EQUAL' => '>=',
|
26
|
+
'LEFT_BRACE' => '{',
|
27
|
+
'LEFT_PAREN' => '(',
|
28
|
+
'LESS' => '<',
|
29
|
+
'LESS_EQUAL' => '<=',
|
30
|
+
'MINUS' => '-',
|
31
|
+
'OR' => 'or',
|
32
|
+
'PLUS' => '+',
|
33
|
+
'RIGHT_BRACE' => '}',
|
34
|
+
'RIGHT_PAREN' => ')',
|
35
|
+
'SEMICOLON' => ';',
|
36
|
+
'SLASH' => '/',
|
37
|
+
'STAR' => '*'
|
38
|
+
}.freeze
|
39
|
+
end # defined
|
20
40
|
|
21
41
|
attr_reader :strict
|
22
42
|
|
@@ -72,18 +92,139 @@ module Loxxy
|
|
72
92
|
node
|
73
93
|
end
|
74
94
|
|
95
|
+
# rule('lhs' => 'nonterm_i nonterm_k_plus')
|
96
|
+
def reduce_binary_operator(_production, _range, tokens, theChildren)
|
97
|
+
operand1 = theChildren[0]
|
98
|
+
|
99
|
+
# Second child is array with couples [operator, operand2]
|
100
|
+
theChildren[1].each do |(operator, operand2)|
|
101
|
+
operand1 = LoxBinaryExpr.new(tokens[0].position, operator, operand1, operand2)
|
102
|
+
end
|
103
|
+
|
104
|
+
operand1
|
105
|
+
end
|
106
|
+
|
107
|
+
# rule('something_plus' => 'something_plus operator symbol')
|
108
|
+
def reduce_binary_plus_more(_production, _range, _tokens, theChildren)
|
109
|
+
result = theChildren[0]
|
110
|
+
operator = Name2special[theChildren[1].symbol.name].to_sym
|
111
|
+
operand2 = theChildren[2]
|
112
|
+
result << [operator, operand2]
|
113
|
+
end
|
114
|
+
|
115
|
+
# rule('something_plus' => 'something_plus symbol')
|
116
|
+
def reduce_binary_plus_end(_production, _range, _tokens, theChildren)
|
117
|
+
operator = Name2special[theChildren[0].symbol.name].to_sym
|
118
|
+
operand2 = theChildren[1]
|
119
|
+
[[operator, operand2]]
|
120
|
+
end
|
121
|
+
|
122
|
+
#####################################
|
123
|
+
# SEMANTIC ACTIONS
|
124
|
+
#####################################
|
125
|
+
|
126
|
+
# rule('program' => 'EOF').as 'null_program'
|
127
|
+
def reduce_null_program(_production, range, _tokens, _theChildren)
|
128
|
+
Ast::LoxNoopExpr.new(tokens[0].position)
|
129
|
+
end
|
130
|
+
|
131
|
+
# rule('program' => 'declaration_plus EOF').as ''
|
132
|
+
def reduce_lox_program(_production, range, tokens, theChildren)
|
133
|
+
return_first_child(range, tokens, theChildren)
|
134
|
+
end
|
135
|
+
|
136
|
+
# rule('printStmt' => 'PRINT expression SEMICOLON')
|
137
|
+
def reduce_print_stmt(_production, _range, tokens, theChildren)
|
138
|
+
Ast::LoxPrintStmt.new(tokens[1].position, theChildren[1])
|
139
|
+
end
|
140
|
+
|
141
|
+
# rule('logic_or' => 'logic_and disjunct_plus')
|
142
|
+
def reduce_logic_or_plus(production, range, tokens, theChildren)
|
143
|
+
reduce_binary_operator(production, range, tokens, theChildren)
|
144
|
+
end
|
145
|
+
|
146
|
+
# rule('disjunct_plus' => 'disjunct_plus OR logic_and')
|
147
|
+
def reduce_logic_or_plus_more(production, range, tokens, theChildren)
|
148
|
+
reduce_binary_plus_more(production, range, tokens, theChildren)
|
149
|
+
end
|
150
|
+
|
151
|
+
# rule('disjunct_plus' => 'OR logic_and')
|
152
|
+
def reduce_logic_or_plus_end(production, range, tokens, theChildren)
|
153
|
+
reduce_binary_plus_end(production, range, tokens, theChildren)
|
154
|
+
end
|
155
|
+
|
156
|
+
# rule('logic_and' => 'equality conjunct_plus')
|
157
|
+
def reduce_logic_and_plus(production, range, tokens, theChildren)
|
158
|
+
reduce_binary_operator(production, range, tokens, theChildren)
|
159
|
+
end
|
160
|
+
|
161
|
+
# rule('conjunct_plus' => 'conjunct_plus AND equality')
|
162
|
+
def reduce_logic_and_plus_more(production, range, tokens, theChildren)
|
163
|
+
reduce_binary_plus_more(production, range, tokens, theChildren)
|
164
|
+
end
|
165
|
+
|
166
|
+
# rule('conjunct_plus' => 'AND equality')
|
167
|
+
def reduce_logic_and_plus_end(production, range, tokens, theChildren)
|
168
|
+
reduce_binary_plus_end(production, range, tokens, theChildren)
|
169
|
+
end
|
170
|
+
|
171
|
+
# rule('equality' => 'comparison equalityTest_plus')
|
172
|
+
def reduce_equality_plus(production, range, tokens, theChildren)
|
173
|
+
reduce_binary_operator(production, range, tokens, theChildren)
|
174
|
+
end
|
175
|
+
|
176
|
+
# rule('equalityTest_plus' => 'equalityTest_plus equalityTest comparison')
|
177
|
+
def reduce_equality_t_plus_more(production, range, tokens, theChildren)
|
178
|
+
reduce_binary_plus_more(production, range, tokens, theChildren)
|
179
|
+
end
|
180
|
+
|
181
|
+
# rule('equalityTest_star' => 'equalityTest comparison')
|
182
|
+
def reduce_equality_t_plus_end(production, range, tokens, theChildren)
|
183
|
+
reduce_binary_plus_end(production, range, tokens, theChildren)
|
184
|
+
end
|
185
|
+
|
186
|
+
# rule('comparison' => 'term comparisonTest_plus')
|
187
|
+
def reduce_comparison_plus(production, range, tokens, theChildren)
|
188
|
+
reduce_binary_operator(production, range, tokens, theChildren)
|
189
|
+
end
|
190
|
+
|
191
|
+
# rule('comparisonTest_plus' => 'comparisonTest_plus comparisonTest term').as 'comparison_t_plus_more'
|
192
|
+
# TODO: is it meaningful to implement this rule?
|
193
|
+
|
194
|
+
# rule('comparisonTest_plus' => 'comparisonTest term')
|
195
|
+
def reduce_comparison_t_plus_end(production, range, tokens, theChildren)
|
196
|
+
reduce_binary_plus_end(production, range, tokens, theChildren)
|
197
|
+
end
|
198
|
+
|
199
|
+
# rule('term' => 'factor additive_plus')
|
200
|
+
def reduce_term_additive(production, range, tokens, theChildren)
|
201
|
+
reduce_binary_operator(production, range, tokens, theChildren)
|
202
|
+
end
|
203
|
+
|
75
204
|
# rule('additive_star' => 'additive_star additionOp factor').as 'additionOp_expr'
|
76
|
-
def
|
77
|
-
(
|
78
|
-
|
79
|
-
|
205
|
+
def reduce_additive_plus_more(production, range, tokens, theChildren)
|
206
|
+
reduce_binary_plus_more(production, range, tokens, theChildren)
|
207
|
+
end
|
208
|
+
|
209
|
+
# rule('additive_plus' => 'additionOp factor')
|
210
|
+
def reduce_additive_plus_end(production, range, tokens, theChildren)
|
211
|
+
reduce_binary_plus_end(production, range, tokens, theChildren)
|
212
|
+
end
|
213
|
+
|
214
|
+
# rule('factor' => 'multiplicative_plus')
|
215
|
+
def reduce_factor_multiplicative(production, range, tokens, theChildren)
|
216
|
+
reduce_binary_operator(production, range, tokens, theChildren)
|
80
217
|
end
|
81
218
|
|
82
|
-
# rule('
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
219
|
+
# rule('multiplicative_plus' => 'multiplicative_plus multOp unary')
|
220
|
+
def reduce_multiplicative_plus_more(production, range, tokens, theChildren)
|
221
|
+
reduce_binary_plus_more(production, range, tokens, theChildren)
|
222
|
+
end
|
223
|
+
|
224
|
+
# rule('multiplicative_plus' => 'multOp unary')
|
225
|
+
def reduce_multiplicative_plus_end(production, range, tokens, theChildren)
|
226
|
+
reduce_binary_plus_end(production, range, tokens, theChildren)
|
227
|
+
end
|
87
228
|
|
88
229
|
# rule('primary' => 'FALSE' | TRUE').as 'literal_expr'
|
89
230
|
def reduce_literal_expr(_production, _range, _tokens, theChildren)
|
@@ -39,75 +39,55 @@ module Loxxy
|
|
39
39
|
top.accept(self)
|
40
40
|
end
|
41
41
|
|
42
|
-
# Visit event. The visitor is
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
broadcast(:before_literal_expr, aLiteralExpr)
|
47
|
-
broadcast(:after_literal_expr, aLiteralExpr)
|
42
|
+
# Visit event. The visitor is about to visit the ptree.
|
43
|
+
# @param aParseTree [Rley::PTre::ParseTree] the ptree to visit.
|
44
|
+
def start_visit_ptree(aParseTree)
|
45
|
+
broadcast(:before_ptree, aParseTree)
|
48
46
|
end
|
49
47
|
|
50
|
-
|
51
|
-
|
48
|
+
# Visit event. The visitor has completed the visit of the ptree.
|
49
|
+
# @param aParseTree [Rley::PTre::ParseTree] the visited ptree.
|
50
|
+
def end_visit_ptree(aParseTree)
|
51
|
+
broadcast(:after_ptree, aParseTree)
|
52
|
+
end
|
52
53
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
broadcast(:
|
54
|
+
# Visit event. The visitor is about to visit a print statement expression.
|
55
|
+
# @param aPrintStmt [AST::LOXPrintStmt] the print statement node to visit
|
56
|
+
def visit_print_stmt(aPrintStmt)
|
57
|
+
broadcast(:before_print_stmt, aPrintStmt)
|
58
|
+
traverse_subnodes(aPrintStmt)
|
59
|
+
broadcast(:after_print_stmt, aPrintStmt)
|
57
60
|
end
|
58
61
|
|
59
62
|
# Visit event. The visitor is visiting the
|
60
|
-
# given
|
61
|
-
# @param
|
62
|
-
def
|
63
|
-
broadcast(:
|
64
|
-
broadcast(:
|
63
|
+
# given terminal node containing a datatype object.
|
64
|
+
# @param aLiteralExpr [AST::LoxLiteralExpr] the leaf node to visit.
|
65
|
+
def visit_literal_expr(aLiteralExpr)
|
66
|
+
broadcast(:before_literal_expr, aLiteralExpr)
|
67
|
+
broadcast(:after_literal_expr, aLiteralExpr)
|
65
68
|
end
|
66
69
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
=begin
|
74
|
-
# Visit event. The visitor is about to visit the given non terminal node.
|
75
|
-
# @param aNonTerminalNode [NonTerminalNode] the node to visit.
|
76
|
-
def visit_nonterminal(aNonTerminalNode)
|
77
|
-
if @traversal == :post_order
|
78
|
-
broadcast(:before_non_terminal, aNonTerminalNode)
|
79
|
-
traverse_subnodes(aNonTerminalNode)
|
80
|
-
else
|
81
|
-
traverse_subnodes(aNonTerminalNode)
|
82
|
-
broadcast(:before_non_terminal, aNonTerminalNode)
|
70
|
+
# Visit event. The visitor is about to visit the given non terminal node.
|
71
|
+
# @param aNonTerminalNode [Rley::PTre::NonTerminalNode] the node to visit.
|
72
|
+
def visit_nonterminal(_non_terminal_node)
|
73
|
+
# Loxxy interpreter encountered a CST node (Concrete Syntax Tree)
|
74
|
+
# that it cannot handle.
|
75
|
+
raise NotImplementedError, 'Loxxy cannot execute this code yet.'
|
83
76
|
end
|
84
|
-
broadcast(:after_non_terminal, aNonTerminalNode)
|
85
|
-
end
|
86
|
-
=end
|
87
77
|
|
88
78
|
private
|
89
79
|
|
90
|
-
|
91
|
-
|
92
|
-
|
80
|
+
# Visit event. The visitor is about to visit the subnodes of a non
|
81
|
+
# terminal node.
|
82
|
+
# @param aParentNode [Ast::LocCompoundExpr] the parent node.
|
83
|
+
def traverse_subnodes(aParentNode)
|
84
|
+
subnodes = aParentNode.subnodes
|
85
|
+
broadcast(:before_subnodes, aParentNode, subnodes)
|
93
86
|
|
94
|
-
# Let's proceed with the visit of
|
95
|
-
|
87
|
+
# Let's proceed with the visit of subnodes
|
88
|
+
subnodes.each { |a_node| a_node.accept(self) }
|
96
89
|
|
97
|
-
broadcast(:
|
98
|
-
end
|
99
|
-
|
100
|
-
def traverse_car_cdr(aPair)
|
101
|
-
if aPair.car
|
102
|
-
broadcast(:before_car, aPair, aPair.car)
|
103
|
-
aPair.car.accept(self)
|
104
|
-
broadcast(:after_car, aPair, aPair.car)
|
105
|
-
end
|
106
|
-
if aPair.cdr
|
107
|
-
broadcast(:before_cdr, aPair, aPair.cdr)
|
108
|
-
aPair.cdr.accept(self)
|
109
|
-
broadcast(:after_cdr, aPair, aPair.cdr)
|
110
|
-
end
|
90
|
+
broadcast(:after_subnodes, aParentNode, subnodes)
|
111
91
|
end
|
112
92
|
|
113
93
|
# Send a notification to all subscribers.
|
@@ -117,7 +97,7 @@ module Loxxy
|
|
117
97
|
subscribers.each do |subscr|
|
118
98
|
next unless subscr.respond_to?(msg) || subscr.respond_to?(:accept_all)
|
119
99
|
|
120
|
-
subscr.send(msg,
|
100
|
+
subscr.send(msg, *args)
|
121
101
|
end
|
122
102
|
end
|
123
103
|
end # class
|