loxxy 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74cd4aa3bd58cad64cad8ac452535052c761f166da883b06b593590310edd97d
4
- data.tar.gz: 15af4b4a4c86c7b8e6a14bda16433a9d1663ab581eae78331d29adeed02313d3
3
+ metadata.gz: e4f33203580d2b83ee7139e449787b439c0fb56c5a8c3dcc8035d114ffd957d3
4
+ data.tar.gz: 46c9fb2f55849c6aa9b9e4d58588746ddb3ac3353f7ed09922d9394a9fc512c6
5
5
  SHA512:
6
- metadata.gz: 0dbd9244c36913eed955b1ff92bdc63fd77cc6f7cda3d6b037f3ee87cdcc8d4450673f852426a7395d968711aaf9a3a539efeeaf5e2a0d46865f4f4fa7276c74
7
- data.tar.gz: c8c65b58fa53d0cce81a3e7508317dfbeb5d8e10f883a0a011d278ca33ee647967bfd34e79fc4703ad7a5b4a3a88aece8d17ca0d0db107f0ec0fcb9ac12e4280
6
+ metadata.gz: 30f554af6338b50297ce6befaa62c86c8406df681e25098cc95dc28da64bb6feabbb9e085846eb8032f51d8d3655332105eb1d7165903bbd0d6be24cb13c4d0b
7
+ data.tar.gz: d9d9a69a010d16807f6c4bf24b15e8135367bb62b6d2e052943e0d6030751f282c777f652dd3fced08093aee8abae228e63d365cae156fa6e87ac7f52fc7e2e6
@@ -1,3 +1,14 @@
1
+ ## [0.0.10] - 2021-01-08
2
+ - AST node generation for equality expression.
3
+
4
+ ## Changed
5
+ - Class `AST::ASTBuilder` refactoring and added `reduce_` methods for equality operations.
6
+ - File `grammar.rb`added name to equality rules
7
+ - File `README.md` added gem version and license badges, expanded roadmap section.
8
+
9
+ ## Fixed
10
+ - File `grammar.rb`: a rule had still the discarded non-terminal `equalityTest_star` in its lhs.
11
+
1
12
  ## [0.0.9] - 2021-01-07
2
13
  - AST node generation for comparison expression.
3
14
 
data/README.md CHANGED
@@ -1,4 +1,7 @@
1
- # Loxxy
1
+ # loxxy
2
+ [![Gem Version](https://badge.fury.io/rb/loxxy.svg)](https://badge.fury.io/rb/loxxy)
3
+ [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](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,7 +9,7 @@ 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 (LoxLox)[https://github.com/benhoyt/loxlox],
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
15
  ## Current status
@@ -18,12 +21,48 @@ The __loxxy__ gem hosts two distinct parsers classes (`RawParser` and `Parser`).
18
21
  Currently it generates AST for arithmetic expressions with literal numbers only.
19
22
 
20
23
  ## Roadmap
21
- - [DONE] Scanner (tokenizer)
22
- - [DONE] Raw parser. It parses Lox programs and generates a parse tree.
23
- - [DONE] Tailored parser for generating AST (Abstract Syntax Tree)
24
- - [STARTED] Custom AST builder class
25
- - [STARTED] Hierarchy classes for representing Lox expressions in AST
26
- - [TODO] Interpreter or transpiler
24
+ ### Done
25
+ - Scanner (tokenizer)
26
+ - Lox grammar (in format required by Rley gem)
27
+ - Raw parser. It parses Lox programs and generates a raw parse tree.
28
+ - Tailored parser for generating AST (Abstract Syntax Tree)
29
+
30
+ ### Started
31
+ - Custom AST builder class
32
+ - Classes for representing Lox expressions in AST
33
+
34
+ ### TODO
35
+ AST Node generation
36
+ Goal: parser should generate AST for any input Lox program
37
+ - [X] Equality operator
38
+ - [] Logical operator (and, or)
39
+ - [] Unary expressions (negate, not)
40
+ - [] Grouping expressions
41
+ - [] Print statement
42
+ - [] Simple assignment expressions
43
+ - [] Variable declaration
44
+ - [] Dot notation
45
+ - [] Block statement
46
+ - [] If statement
47
+ - [] For statement
48
+ - [] While statement
49
+ - [] Function declaration
50
+ - [] Call expression
51
+ - [] Return statement
52
+ - [] Class declaration
53
+ - [] AST generation covers complete grammar
54
+
55
+ Tree-walking:
56
+ - [] Tree visitor recognizes all AST node types
57
+
58
+ Interpreter:
59
+ - Keywords: symbol table, scope, activation record, class & object model, Lox test suite
60
+ - [] Milestone: Interpreter handles expressions but function calls
61
+ - [] Milestone: Interpreter handles `for`, `if`, `print`, `while` and block statements
62
+ - [] Milestone: Interpreter handles variable declarations (global, block)
63
+ - [] Milestone: Interpreter handles function declarations and calls
64
+ - [] Milestone: Interpreter supports class and object definition
65
+ - [] Milestone: Lox interpreter complete
27
66
 
28
67
  ## Example using RawParser class
29
68
  ```ruby
@@ -10,13 +10,31 @@ 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
- # Terminal2NodeClass = {
14
- # 'FALSE' => Datatype::False,
15
- # 'NIL' => Datatype::Nil,
16
- # 'NUMBER' => Datatype::Number,
17
- # 'STRING' => Datatype::LXString,
18
- # 'TRUE' => Datatype::True
19
- # }.freeze
13
+ # Mapping Token name => operator | separator | delimiter characters
14
+ # @return [Hash{String => String}]
15
+ Name2special = {
16
+ 'AND' => 'and',
17
+ 'BANG' => '!',
18
+ 'BANG_EQUAL' => '!=',
19
+ 'COMMA' => ',',
20
+ 'DOT' => '.',
21
+ 'EQUAL' => '=',
22
+ 'EQUAL_EQUAL' => '==',
23
+ 'GREATER' => '>',
24
+ 'GREATER_EQUAL' => '>=',
25
+ 'LEFT_BRACE' => '{',
26
+ 'LEFT_PAREN' => '(',
27
+ 'LESS' => '<',
28
+ 'LESS_EQUAL' => '<=',
29
+ 'MINUS' => '-',
30
+ 'OR' => 'or',
31
+ 'PLUS' => '+',
32
+ 'RIGHT_BRACE' => '}',
33
+ 'RIGHT_PAREN' => ')',
34
+ 'SEMICOLON' => ';',
35
+ 'SLASH' => '/',
36
+ 'STAR' => '*'
37
+ }.freeze
20
38
 
21
39
  attr_reader :strict
22
40
 
@@ -76,7 +94,7 @@ module Loxxy
76
94
  def reduce_binary_operator(_production, _range, tokens, theChildren)
77
95
  operand1 = theChildren[0]
78
96
 
79
- # Second child is anray with couples [operator, operand2]
97
+ # Second child is array with couples [operator, operand2]
80
98
  theChildren[1].each do |(operator, operand2)|
81
99
  operand1 = LoxBinaryExpr.new(tokens[0].position, operator, operand1, operand2)
82
100
  end
@@ -84,6 +102,36 @@ module Loxxy
84
102
  operand1
85
103
  end
86
104
 
105
+ # rule('something_plus' => 'something_plus operator symbol')
106
+ def reduce_binary_plus_more(_production, _range, _tokens, theChildren)
107
+ result = theChildren[0]
108
+ operator = Name2special[theChildren[1].symbol.name].to_sym
109
+ operand2 = theChildren[2]
110
+ result << [operator, operand2]
111
+ end
112
+
113
+ # rule('something_plus' => 'something_plus symbol')
114
+ def reduce_binary_plus_end(_production, _range, _tokens, theChildren)
115
+ operator = Name2special[theChildren[0].symbol.name].to_sym
116
+ operand2 = theChildren[1]
117
+ [[operator, operand2]]
118
+ end
119
+
120
+ # rule('equality' => 'comparison equalityTest_plus')
121
+ def reduce_equality_plus(production, range, tokens, theChildren)
122
+ reduce_binary_operator(production, range, tokens, theChildren)
123
+ end
124
+
125
+ # rule('equalityTest_plus' => 'equalityTest_plus equalityTest comparison')
126
+ def reduce_equality_t_plus_more(production, range, tokens, theChildren)
127
+ reduce_binary_plus_more(production, range, tokens, theChildren)
128
+ end
129
+
130
+ # rule('equalityTest_star' => 'equalityTest comparison')
131
+ def reduce_equality_t_plus_end(production, range, tokens, theChildren)
132
+ reduce_binary_plus_end(production, range, tokens, theChildren)
133
+ end
134
+
87
135
  # rule('comparison' => 'term comparisonTest_plus')
88
136
  def reduce_comparison_plus(production, range, tokens, theChildren)
89
137
  reduce_binary_operator(production, range, tokens, theChildren)
@@ -93,16 +141,8 @@ module Loxxy
93
141
  # TODO: is it meaningful to implement this rule?
94
142
 
95
143
  # rule('comparisonTest_plus' => 'comparisonTest term')
96
- def reduce_comparison_t_plus_end(_production, _range, _tokens, theChildren)
97
- name2operators = {
98
- 'GREATER' => '>',
99
- 'GREATER_EQUAL' => '>=',
100
- 'LESS' => '<',
101
- 'LESS_EQUAL' => '<='
102
- }
103
- operator = name2operators[theChildren[0].symbol.name].to_sym
104
- operand2 = theChildren[1]
105
- [[operator, operand2]]
144
+ def reduce_comparison_t_plus_end(production, range, tokens, theChildren)
145
+ reduce_binary_plus_end(production, range, tokens, theChildren)
106
146
  end
107
147
 
108
148
  # rule('term' => 'factor additive_plus')
@@ -111,18 +151,13 @@ module Loxxy
111
151
  end
112
152
 
113
153
  # rule('additive_star' => 'additive_star additionOp factor').as 'additionOp_expr'
114
- def reduce_additive_plus_more(_production, _range, _tokens, theChildren)
115
- result = theChildren[0]
116
- operator = theChildren[1].symbol.name == 'MINUS' ? :- : :+
117
- operand2 = theChildren[2]
118
- result << [operator, operand2]
154
+ def reduce_additive_plus_more(production, range, tokens, theChildren)
155
+ reduce_binary_plus_more(production, range, tokens, theChildren)
119
156
  end
120
157
 
121
158
  # rule('additive_plus' => 'additionOp factor')
122
- def reduce_additive_plus_end(_production, _range, _tokens, theChildren)
123
- operator = theChildren[0].symbol.name == 'MINUS' ? :- : :+
124
- operand2 = theChildren[1]
125
- [[operator, operand2]]
159
+ def reduce_additive_plus_end(production, range, tokens, theChildren)
160
+ reduce_binary_plus_end(production, range, tokens, theChildren)
126
161
  end
127
162
 
128
163
  # rule('factor' => 'multiplicative_plus')
@@ -131,18 +166,13 @@ module Loxxy
131
166
  end
132
167
 
133
168
  # rule('multiplicative_plus' => 'multiplicative_plus multOp unary')
134
- def reduce_multiplicative_plus_more(_production, _range, _tokens, theChildren)
135
- result = theChildren[0]
136
- operator = theChildren[1].symbol.name == 'SLASH' ? :/ : :*
137
- operand2 = theChildren[2]
138
- result << [operator, operand2]
169
+ def reduce_multiplicative_plus_more(production, range, tokens, theChildren)
170
+ reduce_binary_plus_more(production, range, tokens, theChildren)
139
171
  end
140
172
 
141
173
  # rule('multiplicative_plus' => 'multOp unary')
142
- def reduce_multiplicative_plus_end(_production, _range, _tokens, theChildren)
143
- operator = theChildren[0].symbol.name == 'SLASH' ? :/ : :*
144
- operand2 = theChildren[1]
145
- [[operator, operand2]]
174
+ def reduce_multiplicative_plus_end(production, range, tokens, theChildren)
175
+ reduce_binary_plus_end(production, range, tokens, theChildren)
146
176
  end
147
177
 
148
178
  # rule('primary' => 'FALSE' | TRUE').as 'literal_expr'
@@ -96,9 +96,9 @@ module Loxxy
96
96
  rule('conjunct_plus' => 'conjunct_plus AND equality')
97
97
  rule('conjunct_' => 'AND equality')
98
98
  rule('equality' => 'comparison')
99
- rule('equality' => 'comparison equalityTest_plus')
100
- rule('equalityTest_plus' => 'equalityTest_plus equalityTest comparison')
101
- rule('equalityTest_star' => 'equalityTest comparison')
99
+ rule('equality' => 'comparison equalityTest_plus').as 'equality_plus'
100
+ rule('equalityTest_plus' => 'equalityTest_plus equalityTest comparison').as 'equality_t_plus_more'
101
+ rule('equalityTest_plus' => 'equalityTest comparison').as 'equality_t_plus_end'
102
102
  rule('equalityTest' => 'BANG_EQUAL')
103
103
  rule('equalityTest' => 'EQUAL_EQUAL')
104
104
  rule('comparison' => 'term')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.0.9'
4
+ VERSION = '0.0.10'
5
5
  end
@@ -255,8 +255,25 @@ LOX_END
255
255
  end # context
256
256
 
257
257
  context 'Parsing comparison expressions' do
258
- it 'should parse the comparison of two number literals' do
259
- %w[> >= < <=].each do |predicate|
258
+ it 'should parse the comparison of two number literals' do
259
+ %w[> >= < <=].each do |predicate|
260
+ input = "3 #{predicate} 2;"
261
+ ptree = subject.parse(input)
262
+ parent = ptree.root.subnodes[0]
263
+ expect(parent).to be_kind_of(Rley::PTree::NonTerminalNode)
264
+ expect(parent.symbol.name).to eq('exprStmt')
265
+ expr = parent.subnodes[0]
266
+ expect(expr).to be_kind_of(Ast::LoxBinaryExpr)
267
+ expect(expr.operator).to eq(predicate.to_sym)
268
+ expect(expr.operands[0].literal.value).to eq(3)
269
+ expect(expr.operands[1].literal.value).to eq(2)
270
+ end
271
+ end
272
+ end # context
273
+
274
+ context 'Parsing equality expressions' do
275
+ it 'should parse the equality of two number literals' do
276
+ %w[!= ==].each do |predicate|
260
277
  input = "3 #{predicate} 2;"
261
278
  ptree = subject.parse(input)
262
279
  parent = ptree.root.subnodes[0]
@@ -269,6 +286,22 @@ LOX_END
269
286
  expect(expr.operands[1].literal.value).to eq(2)
270
287
  end
271
288
  end
289
+
290
+ it 'should parse combination of equality expressions' do
291
+ input = '5 != 2 == false; // A bit contrived example'
292
+ ptree = subject.parse(input)
293
+ parent = ptree.root.subnodes[0]
294
+ expect(parent).to be_kind_of(Rley::PTree::NonTerminalNode)
295
+ expect(parent.symbol.name).to eq('exprStmt')
296
+ expr = parent.subnodes[0]
297
+ expect(expr).to be_kind_of(Ast::LoxBinaryExpr)
298
+ expect(expr.operator).to eq(:==)
299
+ expect(expr.operands[0]).to be_kind_of(Ast::LoxBinaryExpr)
300
+ expect(expr.operands[0].operator).to eq(:!=)
301
+ expect(expr.operands[0].operands[0].literal.value).to eq(5)
302
+ expect(expr.operands[0].operands[1].literal.value).to eq(2)
303
+ expect(expr.operands[1].literal.value).to be_falsey
304
+ end
272
305
  end # context
273
306
  end # describe
274
307
  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.9
4
+ version: 0.0.10
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-07 00:00:00.000000000 Z
11
+ date: 2021-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley