loxxy 0.0.7 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d1b591e9ed6ae88b4b4232c01c4f08fd4453fb499a665c368cd64ce2135a6718
4
- data.tar.gz: 6bc1f01f9f0a963a2781271c46391e2c2801b61cc1b076e0b79be30450bee2af
3
+ metadata.gz: ed8bad2906a9ffd76c81a1fe14d89088f913f84996f0a6d98e7f104e0eccfdc9
4
+ data.tar.gz: 40ee48dc0f4d7e0ce1028820b9c5cf56d0c78d9853916f3bf9e5f32a7106887a
5
5
  SHA512:
6
- metadata.gz: 5dd208921fc139eb5f48b182abbe64b919c514904dfab073b09c4a9656989db5c95a5e1bd6f72733a46af8351dc6f95ab94612d8016c22e13dbcedd4637db90b
7
- data.tar.gz: 63ac04a1cd79335daf5dbb38de2615e89044c49ec74fd174200149ef24d829861c3af0e7bf62862cbffc03940b955a6c9336344696d432e4efaa83d2dc1e9d35
6
+ metadata.gz: 69c3c6e6b2a60c3f27284be820ac8f2687de0073c28719bd9414578ab37ac59de267dc1e69897966fef33d4ba725597587fe991b8e20ce6d40ec1587f3aa53c4
7
+ data.tar.gz: c296dcedcf97fe7426a59cfb2df2144685f2809c64becb18483e62a5aea536c2ca3ae2ab697b865c0945456e191a0a011f01123d34160acfa554761b8a2f917e
@@ -1,3 +1,12 @@
1
+ ## [0.0.8] - 2021-01-07
2
+ - AST node generation for arithmetic operations of number literals.
3
+
4
+ ## Changed
5
+ - Class `AST::ASTBuilder` added `reduce_` methods for arithmetic operations.
6
+
7
+ ## Fixed
8
+ - File `grammar.rb`: second rule for `factor` had a missing member in rhs.
9
+
1
10
  ## [0.0.7] - 2021-01-06
2
11
  - Lox grammar reworked, initial AST classes created.
3
12
 
data/README.md CHANGED
@@ -9,6 +9,14 @@ a simple language used in Bob Nystrom's online book [Crafting Interpreters](http
9
9
  - The implementation should be mature enough to run (LoxLox)[https://github.com/benhoyt/loxlox],
10
10
  a Lox interpreter written in Lox.
11
11
 
12
+ ## Current status
13
+ The __loxxy__ gem hosts two distinct parsers classes (`RawParser` and `Parser`).
14
+ - A `RawParser` instance is able to recognize valid Lox input and to generate
15
+ a concrete parse tree from it.
16
+ - A `Parser` instance can also parse Lox source code but will generate an AST
17
+ (Abstract Syntax Tree) that will be used by the future tree-walking interpreter.
18
+ Currently it generates AST for arithmetic expressions with literal numbers only.
19
+
12
20
  ## Roadmap
13
21
  - [DONE] Scanner (tokenizer)
14
22
  - [DONE] Raw parser. It parses Lox programs and generates a parse tree.
@@ -17,14 +25,7 @@ a simple language used in Bob Nystrom's online book [Crafting Interpreters](http
17
25
  - [STARTED] Hierarchy classes for representing Lox expressions in AST
18
26
  - [TODO] Interpreter or transpiler
19
27
 
20
- ## Example
21
- The __loxxy__ hosts two distinct parsers classes (`RawParser` and `Parser`).
22
- - A `RawParser` instance is able to recognize Lox input and to generate
23
- a concrete parse tree from it.
24
- - A `Parser` instance can also parse Lox source code but will generate an AST
25
- (Abstract Syntax Tree) that will be used by the future tree-walking interpreter.
26
-
27
- ### Example using RawParser class
28
+ ## Example using RawParser class
28
29
  ```ruby
29
30
  require 'loxxy'
30
31
 
@@ -69,7 +70,6 @@ program
69
70
  +-- EOF: ''
70
71
  ```
71
72
 
72
-
73
73
  ## Installation
74
74
 
75
75
  Add this line to your application's Gemfile:
@@ -91,9 +91,9 @@ Or install it yourself as:
91
91
  TODO: Write usage instructions here
92
92
 
93
93
  ## Other Lox implementations in Ruby
94
- An impressive list of Lox implementations can be found [here](https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations
94
+ An impressive list of Lox implementations can be found [here](https://github.com/munificent/craftinginterpreters/wiki/Lox-implementations)
95
95
 
96
- For Ruby, ther is the [lox](https://github.com/rdodson41/ruby-lox) gem.
96
+ For Ruby, there is the [lox](https://github.com/rdodson41/ruby-lox) gem.
97
97
  There are other Ruby-based projects as well:
98
98
  - [SlowLox](https://github.com/ArminKleinert/SlowLox), described as a "1-to-1 conversion of JLox to Ruby"
99
99
  - [rulox](https://github.com/LevitatingBusinessMan/rulox)
@@ -72,18 +72,59 @@ module Loxxy
72
72
  node
73
73
  end
74
74
 
75
+ # rule('term' => 'factor additive_plus')
76
+ def reduce_term_additive(_production, _range, tokens, theChildren)
77
+ operand1 = theChildren[0]
78
+
79
+ # Second child is anray with couples [operator, operand2]
80
+ theChildren[1].each do |(operator, operand2)|
81
+ operand1 = LoxBinaryExpr.new(tokens[0].position, operator, operand1, operand2)
82
+ end
83
+
84
+ operand1
85
+ end
86
+
75
87
  # rule('additive_star' => 'additive_star additionOp factor').as 'additionOp_expr'
76
- def reduce_additionOp_expr(_production, _range, _tokens, theChildren)
77
- (operand1, operator_node, operand2) = theChildren
78
- operator = operator_node.symbol.name == 'MINUS' ? :- : :+
79
- LoxBinaryExpr.new(operator_node.token.position, operator, operand1, operand2)
88
+ def reduce_additive_plus_more(_production, _range, _tokens, theChildren)
89
+ result = theChildren[0]
90
+ operator = theChildren[1].symbol.name == 'MINUS' ? :- : :+
91
+ operand2 = theChildren[2]
92
+ result << [operator, operand2]
93
+ end
94
+
95
+ # rule('additive_plus' => 'additionOp factor')
96
+ def reduce_additive_plus_end(_production, _range, _tokens, theChildren)
97
+ operator = theChildren[0].symbol.name == 'MINUS' ? :- : :+
98
+ operand2 = theChildren[1]
99
+ [[operator, operand2]]
80
100
  end
81
101
 
82
- # rule('multiplicative_star' => 'multiplicative_star multOp unary').as 'multOp_expr'
83
- # def reduce_multOp_expr(_production, _range, _tokens, theChildren)
84
- # (operand1, operator, operand2) = theChildren
85
- # LoxBinaryExpr.new(operator.token.position, operator, operand1, operand2)
86
- # end
102
+ # rule('factor' => 'multiplicative_plus')
103
+ def reduce_factor_multiplicative(_production, _range, tokens, theChildren)
104
+ operand1 = theChildren[0]
105
+
106
+ # Second child is anray with couples [operator, operand2]
107
+ theChildren[1].each do |(operator, operand2)|
108
+ operand1 = LoxBinaryExpr.new(tokens[0].position, operator, operand1, operand2)
109
+ end
110
+
111
+ operand1
112
+ end
113
+
114
+ # rule('multiplicative_plus' => 'multiplicative_plus multOp unary')
115
+ def reduce_multiplicative_plus_more(_production, _range, _tokens, theChildren)
116
+ result = theChildren[0]
117
+ operator = theChildren[1].symbol.name == 'SLASH' ? :/ : :*
118
+ operand2 = theChildren[2]
119
+ result << [operator, operand2]
120
+ end
121
+
122
+ # rule('multiplicative_plus' => 'multOp unary')
123
+ def reduce_multiplicative_plus_end(_production, _range, _tokens, theChildren)
124
+ operator = theChildren[0].symbol.name == 'SLASH' ? :/ : :*
125
+ operand2 = theChildren[1]
126
+ [[operator, operand2]]
127
+ end
87
128
 
88
129
  # rule('primary' => 'FALSE' | TRUE').as 'literal_expr'
89
130
  def reduce_literal_expr(_production, _range, _tokens, theChildren)
@@ -110,15 +110,15 @@ module Loxxy
110
110
  rule('comparisonTest' => 'LESS')
111
111
  rule('comparisonTest' => 'LESS_EQUAL')
112
112
  rule('term' => 'factor')
113
- rule('term' => 'factor additive_plus')
114
- rule('additive_plus' => 'additive_plus additionOp factor').as 'additionOp_expr'
115
- rule('additive_plus' => 'additionOp factor')
113
+ rule('term' => 'factor additive_plus').as 'term_additive'
114
+ rule('additive_plus' => 'additive_plus additionOp factor').as 'additive_plus_more'
115
+ rule('additive_plus' => 'additionOp factor').as 'additive_plus_end'
116
116
  rule('additionOp' => 'MINUS')
117
117
  rule('additionOp' => 'PLUS')
118
118
  rule('factor' => 'unary')
119
- rule('factor' => 'multiplicative_plus')
120
- rule('multiplicative_plus' => 'multiplicative_plus multOp unary') # .as 'multOp_expr'
121
- rule('multiplicative_plus' => 'multOp unary')
119
+ rule('factor' => 'unary multiplicative_plus').as 'factor_multiplicative'
120
+ rule('multiplicative_plus' => 'multiplicative_plus multOp unary').as 'multiplicative_plus_more'
121
+ rule('multiplicative_plus' => 'multOp unary').as 'multiplicative_plus_end'
122
122
  rule('multOp' => 'SLASH')
123
123
  rule('multOp' => 'STAR')
124
124
  rule('unary' => 'unaryOp unary')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.0.7'
4
+ VERSION = '0.0.8'
5
5
  end
@@ -137,13 +137,89 @@ LOX_END
137
137
  end
138
138
  end # context
139
139
 
140
- context 'Parsing literals:' do
140
+ context 'Parsing arithmetic operations' do
141
141
  it 'should parse the addition of two number literals' do
142
- # input = '123 + 456;'
143
- # ptree = subject.parse(input)
144
- # term = walk_subnodes(ptree.root, [0, 0, 0, 0, 0, 0, 0])
145
- # expect(leaf).to be_kind_of(Ast::LoxBinaryExpr)
146
- # expect(leaf.literal).to be_equal(Datatype::False.instance)
142
+ input = '123 + 456;'
143
+ ptree = subject.parse(input)
144
+ parent = ptree.root.subnodes[0]
145
+ expect(parent).to be_kind_of(Rley::PTree::NonTerminalNode)
146
+ expect(parent.symbol.name).to eq('exprStmt')
147
+ expr = parent.subnodes[0]
148
+ expect(expr).to be_kind_of(Ast::LoxBinaryExpr)
149
+ expect(expr.operator).to eq(:+)
150
+ expect(expr.operands[0].literal.value).to eq(123)
151
+ expect(expr.operands[1].literal.value).to eq(456)
152
+ end
153
+
154
+ it 'should parse the subtraction of two number literals' do
155
+ input = '4 - 3;'
156
+ ptree = subject.parse(input)
157
+ parent = ptree.root.subnodes[0]
158
+ expect(parent).to be_kind_of(Rley::PTree::NonTerminalNode)
159
+ expect(parent.symbol.name).to eq('exprStmt')
160
+ expr = parent.subnodes[0]
161
+ expect(expr).to be_kind_of(Ast::LoxBinaryExpr)
162
+ expect(expr.operator).to eq(:-)
163
+ expect(expr.operands[0].literal.value).to eq(4)
164
+ expect(expr.operands[1].literal.value).to eq(3)
165
+ end
166
+
167
+ it 'should parse multiple additive operations' do
168
+ input = '5 + 2 - 3;'
169
+ ptree = subject.parse(input)
170
+ parent = ptree.root.subnodes[0]
171
+ expect(parent).to be_kind_of(Rley::PTree::NonTerminalNode)
172
+ expect(parent.symbol.name).to eq('exprStmt')
173
+ expr = parent.subnodes[0]
174
+ expect(expr).to be_kind_of(Ast::LoxBinaryExpr)
175
+ expect(expr.operator).to eq(:-)
176
+ expect(expr.operands[0]).to be_kind_of(Ast::LoxBinaryExpr)
177
+ expect(expr.operands[0].operator).to eq(:+)
178
+ expect(expr.operands[0].operands[0].literal.value).to eq(5)
179
+ expect(expr.operands[0].operands[1].literal.value).to eq(2)
180
+ expect(expr.operands[1].literal.value).to eq(3)
181
+ end
182
+
183
+ it 'should parse the division of two number literals' do
184
+ input = '8 / 2;'
185
+ ptree = subject.parse(input)
186
+ parent = ptree.root.subnodes[0]
187
+ expect(parent).to be_kind_of(Rley::PTree::NonTerminalNode)
188
+ expect(parent.symbol.name).to eq('exprStmt')
189
+ expr = parent.subnodes[0]
190
+ expect(expr).to be_kind_of(Ast::LoxBinaryExpr)
191
+ expect(expr.operator).to eq(:/)
192
+ expect(expr.operands[0].literal.value).to eq(8)
193
+ expect(expr.operands[1].literal.value).to eq(2)
194
+ end
195
+
196
+ it 'should parse the product of two number literals' do
197
+ input = '12.34 * 0.3;'
198
+ ptree = subject.parse(input)
199
+ parent = ptree.root.subnodes[0]
200
+ expect(parent).to be_kind_of(Rley::PTree::NonTerminalNode)
201
+ expect(parent.symbol.name).to eq('exprStmt')
202
+ expr = parent.subnodes[0]
203
+ expect(expr).to be_kind_of(Ast::LoxBinaryExpr)
204
+ expect(expr.operator).to eq(:*)
205
+ expect(expr.operands[0].literal.value).to eq(12.34)
206
+ expect(expr.operands[1].literal.value).to eq(0.3)
207
+ end
208
+
209
+ it 'should parse multiple additive operations' do
210
+ input = '5 * 2 / 3;'
211
+ ptree = subject.parse(input)
212
+ parent = ptree.root.subnodes[0]
213
+ expect(parent).to be_kind_of(Rley::PTree::NonTerminalNode)
214
+ expect(parent.symbol.name).to eq('exprStmt')
215
+ expr = parent.subnodes[0]
216
+ expect(expr).to be_kind_of(Ast::LoxBinaryExpr)
217
+ expect(expr.operator).to eq(:/)
218
+ expect(expr.operands[0]).to be_kind_of(Ast::LoxBinaryExpr)
219
+ expect(expr.operands[0].operator).to eq(:*)
220
+ expect(expr.operands[0].operands[0].literal.value).to eq(5)
221
+ expect(expr.operands[0].operands[1].literal.value).to eq(2)
222
+ expect(expr.operands[1].literal.value).to eq(3)
147
223
  end
148
224
  end # context
149
225
  end # describe
@@ -223,6 +223,18 @@ LOX_END
223
223
  ]
224
224
  match_expectations(subject, expectations)
225
225
  end
226
+
227
+ it 'should cope with single slash (divide) expression' do
228
+ subject.start_with('8 / 2')
229
+
230
+ expectations = [
231
+ # [token lexeme]
232
+ %w[NUMBER 8],
233
+ %w[SLASH /],
234
+ %w[NUMBER 2]
235
+ ]
236
+ match_expectations(subject, expectations)
237
+ end
226
238
  end # context
227
239
  end # describe
228
240
  end # module
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loxxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-06 00:00:00.000000000 Z
11
+ date: 2021-01-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley