loxxy 0.4.03 → 0.4.07
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +47 -7
- data/CHANGELOG.md +58 -17
- data/LICENSE.txt +1 -1
- data/lib/loxxy/ast/ast_builder.rb +12 -12
- data/lib/loxxy/ast/ast_visitor.rb +0 -1
- data/lib/loxxy/ast/lox_call_expr.rb +1 -1
- data/lib/loxxy/ast/lox_return_stmt.rb +1 -1
- data/lib/loxxy/back_end/resolver.rb +1 -1
- data/lib/loxxy/front_end/grammar.rb +3 -10
- data/lib/loxxy/front_end/scanner.rb +2 -3
- data/lib/loxxy/version.rb +1 -1
- data/loxxy.gemspec +2 -2
- data/spec/front_end/parser_spec.rb +1 -1
- data/spec/front_end/raw_parser_spec.rb +5 -8
- data/spec/front_end/scanner_spec.rb +7 -7
- metadata +6 -7
- data/lib/loxxy/front_end/literal.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cd3e438270c62a4863cddfd1b737182993ea205d84985e8862a25c74bb2e8c4
|
4
|
+
data.tar.gz: f6bd428ebc505e238392cbb04e5fb1207eb34752f974ae8f81a23798e4ef51b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77ac1d09cb77b8afab98c21bb2f8544fd2961473efd1acaae3134a2aba0ed7138270aa86f384fe2ce1f76d865c8cd049dc3b8379b954c70992cc53b068244593
|
7
|
+
data.tar.gz: 9fa0e0c3c3d96600bc4e8cd0447383a287be6ff483fb2a843056c87175239bc5fd319e0f11cfe8ab496652a773c91d91f8c05176275b07873f08ffad0de7a1f4
|
data/.rubocop.yml
CHANGED
@@ -84,6 +84,9 @@ Layout/TrailingWhitespace:
|
|
84
84
|
Lint/AmbiguousAssignment:
|
85
85
|
Enabled: true
|
86
86
|
|
87
|
+
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
88
|
+
Enabled: true
|
89
|
+
|
87
90
|
Lint/AmbiguousRange:
|
88
91
|
Enabled: true
|
89
92
|
|
@@ -105,6 +108,9 @@ Lint/EmptyClass:
|
|
105
108
|
Lint/EmptyInPattern:
|
106
109
|
Enabled: true
|
107
110
|
|
111
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
112
|
+
Enabled: true
|
113
|
+
|
108
114
|
Lint/LambdaWithoutLiteralBlock:
|
109
115
|
Enabled: true
|
110
116
|
|
@@ -126,6 +132,9 @@ Lint/RaiseException:
|
|
126
132
|
Lint/RedundantDirGlobSort:
|
127
133
|
Enabled: true
|
128
134
|
|
135
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
136
|
+
Enabled: true
|
137
|
+
|
129
138
|
Lint/RescueException:
|
130
139
|
Enabled: true
|
131
140
|
|
@@ -153,6 +162,9 @@ Lint/UnusedMethodArgument:
|
|
153
162
|
Lint/UselessAccessModifier:
|
154
163
|
Enabled: true
|
155
164
|
|
165
|
+
Lint/UselessRuby2Keywords: # new in 1.23
|
166
|
+
Enabled: true
|
167
|
+
|
156
168
|
Lint/Void:
|
157
169
|
Enabled: false
|
158
170
|
|
@@ -192,6 +204,9 @@ Metrics/ModuleLength:
|
|
192
204
|
Metrics/PerceivedComplexity:
|
193
205
|
Enabled: false
|
194
206
|
|
207
|
+
Naming/BlockForwarding: # new in 1.24
|
208
|
+
Enabled: true
|
209
|
+
|
195
210
|
Naming/ConstantName:
|
196
211
|
Enabled: false
|
197
212
|
|
@@ -213,6 +228,9 @@ Naming/MethodName:
|
|
213
228
|
Naming/VariableName:
|
214
229
|
Enabled: false
|
215
230
|
|
231
|
+
Security/IoMethods: # new in 1.22
|
232
|
+
Enabled: true
|
233
|
+
|
216
234
|
Style/Alias:
|
217
235
|
Enabled: true
|
218
236
|
|
@@ -293,9 +311,9 @@ Style/InverseMethods:
|
|
293
311
|
|
294
312
|
Style/MissingRespondToMissing:
|
295
313
|
Enabled: false
|
296
|
-
|
314
|
+
|
297
315
|
Style/MultilineInPatternThen:
|
298
|
-
Enabled: true
|
316
|
+
Enabled: true
|
299
317
|
|
300
318
|
Style/NegatedIfElseCondition:
|
301
319
|
Enabled: true
|
@@ -306,11 +324,17 @@ Style/Next:
|
|
306
324
|
Style/NilLambda:
|
307
325
|
Enabled: true
|
308
326
|
|
327
|
+
Style/NumberedParameters: # new in 1.22
|
328
|
+
Enabled: true
|
329
|
+
|
330
|
+
Style/NumberedParametersLimit: # new in 1.22
|
331
|
+
Enabled: true
|
332
|
+
|
309
333
|
Style/NumericLiterals:
|
310
334
|
Enabled: false
|
311
|
-
|
335
|
+
|
312
336
|
Style/QuotedSymbols:
|
313
|
-
Enabled: true
|
337
|
+
Enabled: true
|
314
338
|
|
315
339
|
Style/RaiseArgs:
|
316
340
|
Enabled: true
|
@@ -323,9 +347,9 @@ Style/RedundantReturn:
|
|
323
347
|
|
324
348
|
Style/RedundantSelf:
|
325
349
|
Enabled: true
|
326
|
-
|
350
|
+
|
327
351
|
Style/RedundantSelfAssignmentBranch:
|
328
|
-
Enabled: true
|
352
|
+
Enabled: true
|
329
353
|
|
330
354
|
Style/RegexpLiteral:
|
331
355
|
Enabled: false
|
@@ -333,6 +357,9 @@ Style/RegexpLiteral:
|
|
333
357
|
Style/PercentLiteralDelimiters:
|
334
358
|
Enabled: false
|
335
359
|
|
360
|
+
Style/SelectByRegexp: # new in 1.22
|
361
|
+
Enabled: true
|
362
|
+
|
336
363
|
Style/StderrPuts:
|
337
364
|
Enabled: false
|
338
365
|
|
@@ -406,6 +433,12 @@ Style/EndlessMethod:
|
|
406
433
|
Style/ExplicitBlockArgument:
|
407
434
|
Enabled: true
|
408
435
|
|
436
|
+
Style/FileRead: # new in 1.24
|
437
|
+
Enabled: true
|
438
|
+
|
439
|
+
Style/FileWrite: # new in 1.24
|
440
|
+
Enabled: true
|
441
|
+
|
409
442
|
Style/GlobalStdStream:
|
410
443
|
Enabled: true
|
411
444
|
|
@@ -417,12 +450,19 @@ Style/HashConversion:
|
|
417
450
|
|
418
451
|
Style/HashLikeCase:
|
419
452
|
Enabled: true
|
420
|
-
|
453
|
+
|
421
454
|
Style/IfWithBooleanLiteralBranches:
|
422
455
|
Enabled: true
|
456
|
+
|
457
|
+
Style/MapToHash: # new in 1.24
|
458
|
+
Enabled: true
|
459
|
+
|
460
|
+
Style/OpenStructUse: # new in 1.23
|
461
|
+
Enabled: true
|
423
462
|
|
424
463
|
Style/OptionalBooleanParameter:
|
425
464
|
Enabled: true
|
465
|
+
|
426
466
|
|
427
467
|
Style/RedundantAssignment:
|
428
468
|
Enabled: true
|
data/CHANGELOG.md
CHANGED
@@ -1,15 +1,56 @@
|
|
1
|
+
## [0.4.07] - 2022-11-21
|
2
|
+
- Minor fixes; dependency towards Rubies 3+ allowed...
|
3
|
+
|
4
|
+
### Fixed
|
5
|
+
- File `loxxy.gemspec` dependency on Ruby version relaxed to support Ruby 3+
|
6
|
+
- File `resolver.rb` Fixed a typo in standard Lox error message.
|
7
|
+
- File `collide_with_paramaeter.lox` Fixed typo in error message.
|
8
|
+
- File `duplicate_local.lox` Fixed typo in error message.
|
9
|
+
- File `duplicate_parameter.lox` Fixed typo in error message.
|
10
|
+
|
11
|
+
|
12
|
+
## [0.4.06] - 2021-11-01
|
13
|
+
- Code update to cope with `Rley` v.0.8.08 changes
|
14
|
+
|
15
|
+
### Changed
|
16
|
+
- File `AST::AstBuilder` some `reduce_` to cope implementation change of ? quantifier
|
17
|
+
- Method `AST::LoxCallExpr#initialize` call to `Array#flatten` with argList argument
|
18
|
+
- File `loxxy.gemspec` dependency towards `rely` minimal version number is now `0.8.08`
|
19
|
+
- Some spec files updated after `rley` changes of ?, *, + quantifiers
|
20
|
+
|
21
|
+
### Removed
|
22
|
+
- File `front_end/literal.rb`: obsolete
|
23
|
+
|
24
|
+
|
25
|
+
## [0.4.05] - 2021-10-10
|
26
|
+
- Removal of `Literal` class, code restyling to please Rubocop 1.22
|
27
|
+
|
28
|
+
### Changed
|
29
|
+
- Class `Scanner` remove all dependencies to `Frontend::Literal` class
|
30
|
+
- File `.rubocop.yml` added new cops from Rubocop 1.21 and 1.22
|
31
|
+
- File `parser_spec.rb` use of parentheses in ambiguous expressions
|
32
|
+
- File `raw_parser_spec.rb` use of parentheses in ambiguous expressions
|
33
|
+
- File `loxxy.gemspec` forced dependency to Rley 0.8.06
|
34
|
+
|
35
|
+
## [0.4.04] - 2021-09-11
|
36
|
+
- Grammar optimization (3 rules less, use of match_closest feature from `Rley`)
|
37
|
+
|
38
|
+
### Changed
|
39
|
+
- Method `Ast::AstBuilder#reduce_arguments` code re-styling: use shorthand &:
|
40
|
+
- File `grammar.rb` use `match_closest` constraint from Rley to cope with dangling else statement
|
41
|
+
|
1
42
|
## [0.4.02] - 2021-09-10
|
2
|
-
- Fixes in`AST::AstBuilder` class to
|
43
|
+
- Fixes in`AST::AstBuilder` class to cope with changes in Rley 0.8.03
|
3
44
|
|
4
45
|
### Changed
|
5
46
|
- File `loxxy.gemspec` forced dependency to Rley 0.8.03
|
6
47
|
|
7
48
|
### Fixed
|
8
49
|
- Method `Ast::AstBuilder#reduce_class_naming` fixed access to `IDENTIFER` in (LESS IDENTIFER)?
|
9
|
-
- Method `Ast::AstBuilder#reduce_var_declaration` fixed access to `expression` in (EQUAL expression)?
|
10
|
-
- Method `Ast::AstBuilder#reduce_assign_expr`fixed access to `call` in (call DOT)?
|
11
|
-
- Method `Ast::AstBuilder#reduce_parameters`fixed access to `IDENTIFIER` in (COMMA IDENTIFIER)*
|
12
|
-
- Method `Ast::AstBuilder#reduce_arguments`fixed access to `expression` in (COMMA expression)*
|
50
|
+
- Method `Ast::AstBuilder#reduce_var_declaration` fixed access to `expression` in (EQUAL expression)?
|
51
|
+
- Method `Ast::AstBuilder#reduce_assign_expr`fixed access to `call` in (call DOT)?
|
52
|
+
- Method `Ast::AstBuilder#reduce_parameters`fixed access to `IDENTIFIER` in (COMMA IDENTIFIER)*
|
53
|
+
- Method `Ast::AstBuilder#reduce_arguments`fixed access to `expression` in (COMMA expression)*
|
13
54
|
|
14
55
|
|
15
56
|
|
@@ -68,14 +109,14 @@
|
|
68
109
|
- Milestone: `Loxxy` passes all reference test suite.
|
69
110
|
|
70
111
|
### Fixed
|
71
|
-
- Method `BackEnd::Resolver#before_variable_expr`: Standard `Lox` allows re-declaration of a variable at top-level scope
|
112
|
+
- Method `BackEnd::Resolver#before_variable_expr`: Standard `Lox` allows re-declaration of a variable at top-level scope
|
113
|
+
|
72
114
|
|
73
|
-
|
74
115
|
## [0.2.06] - 2021-05-04
|
75
116
|
- Nearly passing the 'official' test suite, fixing non-compliant behavior, specialized exceptions for errors
|
76
117
|
|
77
118
|
### New
|
78
|
-
- Module `LoxFileTester` module that hosts methods that simplify the tests of `Lox` source file.
|
119
|
+
- Module `LoxFileTester` module that hosts methods that simplify the tests of `Lox` source file.
|
79
120
|
|
80
121
|
### Changed
|
81
122
|
- Folder `test_suite` vastly reorganized. Sub-folder `baseline` contains spec files testing the `Lox` files from official implementation
|
@@ -85,7 +126,7 @@
|
|
85
126
|
|
86
127
|
### Fixed
|
87
128
|
- `0/0` expression results in a ZeroDivisionError exception, in Lox this result to a NaN (Not a Number). Now, `Loxxy` is aligned to standard `Lox`
|
88
|
-
- `FrontEnd::Scanner` now always treats expression like `-123` as the unary or binary minus operator applied to a positive number.
|
129
|
+
- `FrontEnd::Scanner` now always treats expression like `-123` as the unary or binary minus operator applied to a positive number.
|
89
130
|
|
90
131
|
## [0.2.05] - 2021-04-26
|
91
132
|
- `Loxxy` now transforms for loops into while loops (desugaring), fix in Scanner class
|
@@ -112,7 +153,7 @@
|
|
112
153
|
- Method `BackEnd::Resolver#after_for_stmt now accepts nil test expression
|
113
154
|
|
114
155
|
## [0.2.03] - 2021-04-24
|
115
|
-
- Fixes for the set (field) expressions, `accept` methods for AST nodes are meta-programmed
|
156
|
+
- Fixes for the set (field) expressions, `accept` methods for AST nodes are meta-programmed
|
116
157
|
|
117
158
|
### New
|
118
159
|
- Module `Ast::Visitee` provides the `define_accept` method that generate `accept` method with meta-programming
|
@@ -287,7 +328,7 @@
|
|
287
328
|
- Fix and test suite for return statements
|
288
329
|
|
289
330
|
### CHANGED
|
290
|
-
- `Loxxy` reports an error when a return statement occurs in top-level scope
|
331
|
+
- `Loxxy` reports an error when a return statement occurs in top-level scope
|
291
332
|
|
292
333
|
### Fixed
|
293
334
|
- A return without explicit value genrated an exception in some cases.
|
@@ -311,7 +352,7 @@
|
|
311
352
|
- Class `BackEnd::Environment`: added the attributes `predecessor` and `embedding` to support closures.
|
312
353
|
- Class `BackeEnd::LoxFunction`: added the attribute `closure` that is equal to the environment where the function is declared.
|
313
354
|
- Constructor `BackEnd::LoxFunction#new` now takes a `BackEnd::Engine`as its fourth parameter
|
314
|
-
- Methods `BackEnd::SymbolTable#enter_environment`, `BackEnd::SymbolTable#leave_environment` take into account closures.
|
355
|
+
- Methods `BackEnd::SymbolTable#enter_environment`, `BackEnd::SymbolTable#leave_environment` take into account closures.
|
315
356
|
|
316
357
|
### Fixed
|
317
358
|
- Method `Ast::AstBuilder#after_var_stmt` now takes into account the value from the top of stack
|
@@ -357,7 +398,7 @@
|
|
357
398
|
|
358
399
|
### Changed
|
359
400
|
- File `console` renamed to `loxxy`. Very basic command-line interface.
|
360
|
-
- Custom exception classes
|
401
|
+
- Custom exception classes
|
361
402
|
- File `README.md` updated list of supported `Lox` keywords.
|
362
403
|
|
363
404
|
|
@@ -388,8 +429,8 @@
|
|
388
429
|
- Method `Ast::ASTVisitor#visit_fun_stmt` for visiting an `Ast::LoxFunStmt` node
|
389
430
|
- Method `Ast::LoxBlockStmt#empty?` returns true if the code block is empty
|
390
431
|
- Method `BackEnd::Engine#after_fun_stmt`
|
391
|
-
- Method `BackEnd::NativeFunction#call`
|
392
|
-
- Method `BackEnd::NativeFunction#to_str`
|
432
|
+
- Method `BackEnd::NativeFunction#call`
|
433
|
+
- Method `BackEnd::NativeFunction#to_str`
|
393
434
|
- Method `BackEnd::LoxFunction` runtime representation of a Lox function.
|
394
435
|
|
395
436
|
### Changed
|
@@ -458,7 +499,7 @@
|
|
458
499
|
- Method `Ast::ASTBuilder#reduce_assign_expr` creates an `Ast::LoxAssignExpr` node
|
459
500
|
- Method `Ast::ASTVisitor#visit_assign_expr` for visiting an `Ast::LoxAssignExpr` node
|
460
501
|
- Method `BackEnd::Engine#after_assign_expr` implementation of the assignment
|
461
|
-
- Method `BackEnd::Variable#assign` to assign a value to a variable
|
502
|
+
- Method `BackEnd::Variable#assign` to assign a value to a variable
|
462
503
|
|
463
504
|
## [0.0.23] - 2021-01-20
|
464
505
|
- Fix for variables without explicit initialization.
|
@@ -728,4 +769,4 @@
|
|
728
769
|
|
729
770
|
## [0.0.1] - 2020-12-27
|
730
771
|
### Added
|
731
|
-
- Initial Github commit
|
772
|
+
- Initial Github commit
|
data/LICENSE.txt
CHANGED
@@ -222,10 +222,8 @@ module Loxxy
|
|
222
222
|
if test.nil? && update
|
223
223
|
# when test expr is nil but update expr is not, then force test to be true
|
224
224
|
test = LoxLiteralExpr.new(tokens[0].position, Datatype::True.instance)
|
225
|
-
[init, test, update]
|
226
|
-
else
|
227
|
-
theChildren
|
228
225
|
end
|
226
|
+
[init, test, update&.first]
|
229
227
|
end
|
230
228
|
|
231
229
|
# rule('forInitialization' => 'SEMICOLON')
|
@@ -234,8 +232,8 @@ module Loxxy
|
|
234
232
|
end
|
235
233
|
|
236
234
|
# rule('forTest' => 'expression? SEMICOLON')
|
237
|
-
def reduce_for_test(_production,
|
238
|
-
|
235
|
+
def reduce_for_test(_production, _range, _tokens, theChildren)
|
236
|
+
theChildren[0]&.first
|
239
237
|
end
|
240
238
|
|
241
239
|
# rule('ifStmt' => 'IF ifCondition statement ELSE statement')
|
@@ -262,7 +260,8 @@ module Loxxy
|
|
262
260
|
|
263
261
|
# rule('returnStmt' => 'RETURN expression? SEMICOLON')
|
264
262
|
def reduce_return_stmt(_production, _range, tokens, theChildren)
|
265
|
-
|
263
|
+
ret_expr = theChildren[1].nil? ? nil : theChildren[1].first
|
264
|
+
Ast::LoxReturnStmt.new(tokens[1].position, ret_expr)
|
266
265
|
end
|
267
266
|
|
268
267
|
# rule('whileStmt' => 'WHILE LEFT_PAREN expression RIGHT_PAREN statement').as ''
|
@@ -275,7 +274,7 @@ module Loxxy
|
|
275
274
|
decls = nil
|
276
275
|
if theChildren[1]
|
277
276
|
pos = tokens[1].position
|
278
|
-
decls = LoxSeqDecl.new(
|
277
|
+
decls = LoxSeqDecl.new(pos, theChildren[1].flatten)
|
279
278
|
else
|
280
279
|
pos = tokens[0].position
|
281
280
|
end
|
@@ -377,15 +376,16 @@ module Loxxy
|
|
377
376
|
LoxSuperExpr.new(theChildren[0].token.position, theChildren[2].token.lexeme)
|
378
377
|
end
|
379
378
|
|
380
|
-
# rule('function' => 'IDENTIFIER LEFT_PAREN
|
379
|
+
# rule('function' => 'IDENTIFIER LEFT_PAREN parameters? RIGHT_PAREN block').as 'function'
|
381
380
|
def reduce_function(_production, _range, _tokens, theChildren)
|
382
381
|
first_child = theChildren.first
|
383
382
|
pos = first_child.token.position
|
384
|
-
|
383
|
+
params = theChildren[2] ? theChildren[2].flatten : []
|
384
|
+
if params.size > 255
|
385
385
|
msg = "Can't have more than 255 parameters."
|
386
386
|
raise Loxxy::SyntaxError, msg
|
387
387
|
end
|
388
|
-
LoxFunStmt.new(pos, first_child.token.lexeme,
|
388
|
+
LoxFunStmt.new(pos, first_child.token.lexeme, params, theChildren[4])
|
389
389
|
end
|
390
390
|
|
391
391
|
# rule('parameters' => 'IDENTIFIER (COMMA IDENTIFIER)*').as 'parameters'
|
@@ -399,9 +399,9 @@ module Loxxy
|
|
399
399
|
|
400
400
|
# rule('arguments' => 'expression (COMMA expression)*')
|
401
401
|
def reduce_arguments(_production, _range, _tokens, theChildren)
|
402
|
-
return [theChildren[0]]
|
402
|
+
return [theChildren[0]] if theChildren[1].empty?
|
403
403
|
|
404
|
-
successors = theChildren[1].map
|
404
|
+
successors = theChildren[1].map(&:last)
|
405
405
|
successors.unshift(theChildren[0])
|
406
406
|
end
|
407
407
|
end # class
|
@@ -12,7 +12,7 @@ module Loxxy
|
|
12
12
|
# @param argList [Array<Loxxy::Ast::LoxNode>]
|
13
13
|
def initialize(aPosition, argList)
|
14
14
|
super(aPosition, [])
|
15
|
-
@arguments = argList
|
15
|
+
@arguments = argList.flatten
|
16
16
|
end
|
17
17
|
|
18
18
|
define_accept # Add `accept` method as found in Visitor design pattern
|
@@ -6,7 +6,7 @@ module Loxxy
|
|
6
6
|
module Ast
|
7
7
|
class LoxReturnStmt < LoxCompoundExpr
|
8
8
|
# @param aPosition [Rley::Lexical::Position] Position of the entry in the input stream.
|
9
|
-
# @param anExpression [Ast::LoxNode] expression to return
|
9
|
+
# @param anExpression [Ast::LoxNode, NilClass] expression to return
|
10
10
|
def initialize(aPosition, anExpression)
|
11
11
|
expr = anExpression || Datatype::Nil.instance
|
12
12
|
super(aPosition, [expr])
|
@@ -220,7 +220,7 @@ module Loxxy
|
|
220
220
|
curr_scope = scopes.last
|
221
221
|
# Oddly enough, Lox allows variable re-declaration at top-level
|
222
222
|
if curr_scope.include?(aVarName)
|
223
|
-
msg = "Error at '#{aVarName}': Already variable with this name in this scope."
|
223
|
+
msg = "Error at '#{aVarName}': Already a variable with this name in this scope."
|
224
224
|
raise Loxxy::RuntimeError, msg
|
225
225
|
elsif curr_scope.size == 255 && current_function != :none
|
226
226
|
msg = "Error at '#{aVarName}': Too many local variables in function."
|
@@ -1,12 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
3
|
require 'rley' # Load the gem
|
5
4
|
|
6
5
|
module Loxxy
|
7
6
|
module FrontEnd
|
8
7
|
########################################
|
9
|
-
# Grammar for Lox language
|
8
|
+
# Grammar for the Lox language
|
10
9
|
# Authoritative grammar at:
|
11
10
|
# https://craftinginterpreters.com/appendix-i.html
|
12
11
|
builder = Rley::grammar_builder do
|
@@ -32,7 +31,7 @@ module Loxxy
|
|
32
31
|
rule('declaration' => 'classDecl')
|
33
32
|
rule('declaration' => 'funDecl')
|
34
33
|
rule('declaration' => 'varDecl')
|
35
|
-
rule('declaration' => '
|
34
|
+
rule('declaration' => 'statement')
|
36
35
|
|
37
36
|
rule('classDecl' => 'CLASS classNaming class_body').as 'class_decl'
|
38
37
|
rule('classNaming' => 'IDENTIFIER (LESS IDENTIFIER)?').as 'class_naming'
|
@@ -43,8 +42,6 @@ module Loxxy
|
|
43
42
|
rule('varDecl' => 'VAR IDENTIFIER (EQUAL expression)? SEMICOLON').as 'var_declaration'
|
44
43
|
|
45
44
|
# Statements: produce side effects, but don't introduce bindings
|
46
|
-
rule('stmt' => 'statement')
|
47
|
-
# rule('stmt' => 'unbalancedStmt') # Tweak to cope with "dangling else" problem
|
48
45
|
rule('statement' => 'exprStmt')
|
49
46
|
rule('statement' => 'forStmt')
|
50
47
|
rule('statement' => 'ifStmt')
|
@@ -63,11 +60,7 @@ module Loxxy
|
|
63
60
|
rule('forTest' => 'expression? SEMICOLON').as 'for_test'
|
64
61
|
|
65
62
|
rule('ifStmt' => 'IF ifCondition statement ELSE {match_closest: "IF"} statement').as 'if_else_stmt'
|
66
|
-
rule('ifStmt' => 'IF ifCondition
|
67
|
-
# rule('unbalancedStmt' => 'IF ifCondition statement ELSE unbalancedStmt').as 'if_else_stmt'
|
68
|
-
# rule('ifStmt' => 'IF ifCondition statement ELSE statement').as 'if_else_stmt'
|
69
|
-
# rule('unbalancedStmt' => 'IF ifCondition stmt').as 'if_stmt'
|
70
|
-
# rule('unbalancedStmt' => 'IF ifCondition statement ELSE unbalancedStmt').as 'if_else_stmt'
|
63
|
+
rule('ifStmt' => 'IF ifCondition statement').as 'if_stmt'
|
71
64
|
rule('ifCondition' => 'LEFT_PAREN expression RIGHT_PAREN').as 'keep_symbol2'
|
72
65
|
|
73
66
|
rule('printStmt' => 'PRINT expression SEMICOLON').as 'print_stmt'
|
@@ -4,7 +4,6 @@ require 'strscan'
|
|
4
4
|
require 'rley'
|
5
5
|
require_relative '../error'
|
6
6
|
require_relative '../datatype/all_datatypes'
|
7
|
-
require_relative 'literal'
|
8
7
|
|
9
8
|
module Loxxy
|
10
9
|
module FrontEnd
|
@@ -142,7 +141,7 @@ module Loxxy
|
|
142
141
|
col = scanner.pos - lex_length - @line_start + 1
|
143
142
|
pos = Rley::Lexical::Position.new(@lineno, col)
|
144
143
|
if value
|
145
|
-
token = Literal.new(value, aLexeme.dup, symb, pos)
|
144
|
+
token = Rley::Lexical::Literal.new(value, aLexeme.dup, symb, pos)
|
146
145
|
else
|
147
146
|
token = Rley::Lexical::Token.new(aLexeme.dup, symb, pos)
|
148
147
|
end
|
@@ -212,7 +211,7 @@ module Loxxy
|
|
212
211
|
pos = Rley::Lexical::Position.new(line, column_start)
|
213
212
|
lox_string = Datatype::LXString.new(literal)
|
214
213
|
lexeme = scanner.string[scan_pos - 1..scanner.pos - 1]
|
215
|
-
Literal.new(lox_string, lexeme, 'STRING', pos)
|
214
|
+
Rley::Lexical::Literal.new(lox_string, lexeme, 'STRING', pos)
|
216
215
|
end
|
217
216
|
|
218
217
|
# Skip non-significant whitespaces and comments.
|
data/lib/loxxy/version.rb
CHANGED
data/loxxy.gemspec
CHANGED
@@ -48,7 +48,7 @@ Gem::Specification.new do |spec|
|
|
48
48
|
DESCR_END
|
49
49
|
spec.homepage = 'https://github.com/famished-tiger/loxxy'
|
50
50
|
spec.license = 'MIT'
|
51
|
-
spec.required_ruby_version = '
|
51
|
+
spec.required_ruby_version = '>= 2.5'
|
52
52
|
|
53
53
|
spec.bindir = 'bin'
|
54
54
|
spec.executables = ['loxxy']
|
@@ -58,7 +58,7 @@ Gem::Specification.new do |spec|
|
|
58
58
|
PkgExtending.pkg_documentation(spec)
|
59
59
|
|
60
60
|
# Runtime dependencies
|
61
|
-
spec.add_dependency 'rley', '~> 0.8.
|
61
|
+
spec.add_dependency 'rley', '~> 0.8.08'
|
62
62
|
|
63
63
|
# Development dependencies
|
64
64
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
@@ -28,7 +28,7 @@ module Loxxy
|
|
28
28
|
expect(aParseTree.root.symbol.name).to eq('program')
|
29
29
|
(decls, eof) = aParseTree.root.subnodes
|
30
30
|
expect(decls).to be_kind_of(Rley::PTree::NonTerminalNode)
|
31
|
-
expect(decls.symbol.name).to eq('
|
31
|
+
expect(decls.symbol.name).to eq('rep_declaration_star')
|
32
32
|
expect(decls.subnodes).to be_empty
|
33
33
|
expect(eof).to be_kind_of(Rley::PTree::TerminalNode)
|
34
34
|
expect(eof.symbol.name).to eq('EOF')
|
@@ -40,7 +40,7 @@ module Loxxy
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should cope with whitespaces only input' do
|
43
|
-
ptree = subject.parse(' ' * 80 + "\n" * 20)
|
43
|
+
ptree = subject.parse((' ' * 80) + ("\n" * 20))
|
44
44
|
check_empty_input_result(ptree)
|
45
45
|
end
|
46
46
|
|
@@ -76,15 +76,12 @@ LOX_END
|
|
76
76
|
expect(root.symbol.name).to eq('program')
|
77
77
|
(decls, eof) = root.subnodes
|
78
78
|
expect(decls).to be_kind_of(Rley::PTree::NonTerminalNode)
|
79
|
-
expect(decls.symbol.name).to eq('
|
79
|
+
expect(decls.symbol.name).to eq('rep_declaration_star')
|
80
80
|
expect(decls.subnodes[0]).to be_kind_of(Rley::PTree::NonTerminalNode)
|
81
|
-
expect(decls.subnodes[0].symbol.name).to eq('
|
81
|
+
expect(decls.subnodes[0].symbol.name).to eq('rep_declaration_star')
|
82
82
|
expect(decls.subnodes[1]).to be_kind_of(Rley::PTree::NonTerminalNode)
|
83
83
|
expect(decls.subnodes[1].symbol.name).to eq('declaration')
|
84
|
-
|
85
|
-
expect(stmt).to be_kind_of(Rley::PTree::NonTerminalNode)
|
86
|
-
expect(stmt.symbol.name).to eq('stmt')
|
87
|
-
statement = stmt.subnodes[0]
|
84
|
+
statement = decls.subnodes[1].subnodes[0]
|
88
85
|
expect(statement).to be_kind_of(Rley::PTree::NonTerminalNode)
|
89
86
|
expect(statement.symbol.name).to eq('statement')
|
90
87
|
prnt_stmt = statement.subnodes[0]
|
@@ -105,7 +105,7 @@ LOX_END
|
|
105
105
|
it 'should recognize a false boolean token' do
|
106
106
|
subject.start_with('false')
|
107
107
|
token_false = subject.tokens[0]
|
108
|
-
expect(token_false).to be_kind_of(Literal)
|
108
|
+
expect(token_false).to be_kind_of(Rley::Lexical::Literal)
|
109
109
|
expect(token_false.terminal).to eq('FALSE')
|
110
110
|
expect(token_false.lexeme).to eq('false')
|
111
111
|
expect(token_false.value).to be_kind_of(Datatype::False)
|
@@ -115,7 +115,7 @@ LOX_END
|
|
115
115
|
it 'should recognize a true boolean token' do
|
116
116
|
subject.start_with('true')
|
117
117
|
token_true = subject.tokens[0]
|
118
|
-
expect(token_true).to be_kind_of(Literal)
|
118
|
+
expect(token_true).to be_kind_of(Rley::Lexical::Literal)
|
119
119
|
expect(token_true.terminal).to eq('TRUE')
|
120
120
|
expect(token_true.lexeme).to eq('true')
|
121
121
|
expect(token_true.value).to be_kind_of(Datatype::True)
|
@@ -137,7 +137,7 @@ LOX_END
|
|
137
137
|
|
138
138
|
subject.start_with(input)
|
139
139
|
subject.tokens[0..-2].each_with_index do |tok, i|
|
140
|
-
expect(tok).to be_kind_of(Literal)
|
140
|
+
expect(tok).to be_kind_of(Rley::Lexical::Literal)
|
141
141
|
expect(tok.terminal).to eq('NUMBER')
|
142
142
|
(lexeme, val) = expectations[i]
|
143
143
|
expect(tok.lexeme).to eq(lexeme)
|
@@ -177,10 +177,10 @@ LOX_END
|
|
177
177
|
tokens = subject.tokens[0..-2]
|
178
178
|
expect(tokens[0]).to be_kind_of(Rley::Lexical::Token)
|
179
179
|
expect(tokens[0].terminal).to eq('DOT')
|
180
|
-
expect(tokens[1]).to be_kind_of(Literal)
|
180
|
+
expect(tokens[1]).to be_kind_of(Rley::Lexical::Literal)
|
181
181
|
expect(tokens[1].terminal).to eq('NUMBER')
|
182
182
|
expect(tokens[1].value.value).to eq(456)
|
183
|
-
expect(tokens[2]).to be_kind_of(Literal)
|
183
|
+
expect(tokens[2]).to be_kind_of(Rley::Lexical::Literal)
|
184
184
|
expect(tokens[2].terminal).to eq('NUMBER')
|
185
185
|
expect(tokens[2].value.value).to eq(123)
|
186
186
|
expect(tokens[3]).to be_kind_of(Rley::Lexical::Token)
|
@@ -202,7 +202,7 @@ LOX_END
|
|
202
202
|
|
203
203
|
subject.start_with(input)
|
204
204
|
subject.tokens[0..-2].each_with_index do |str, i|
|
205
|
-
expect(str).to be_kind_of(Literal)
|
205
|
+
expect(str).to be_kind_of(Rley::Lexical::Literal)
|
206
206
|
expect(str.terminal).to eq('STRING')
|
207
207
|
val = expectations[i]
|
208
208
|
expect(str.value).to be_kind_of(Datatype::LXString)
|
@@ -236,7 +236,7 @@ LOX_END
|
|
236
236
|
it 'should recognize a nil token' do
|
237
237
|
subject.start_with('nil')
|
238
238
|
token_nil = subject.tokens[0]
|
239
|
-
expect(token_nil).to be_kind_of(Literal)
|
239
|
+
expect(token_nil).to be_kind_of(Rley::Lexical::Literal)
|
240
240
|
expect(token_nil.terminal).to eq('NIL')
|
241
241
|
expect(token_nil.lexeme).to eq('nil')
|
242
242
|
expect(token_nil.value).to be_kind_of(Datatype::Nil)
|
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.4.
|
4
|
+
version: 0.4.07
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.8.
|
19
|
+
version: 0.8.08
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.8.
|
26
|
+
version: 0.8.08
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -139,7 +139,6 @@ files:
|
|
139
139
|
- lib/loxxy/datatype/true.rb
|
140
140
|
- lib/loxxy/error.rb
|
141
141
|
- lib/loxxy/front_end/grammar.rb
|
142
|
-
- lib/loxxy/front_end/literal.rb
|
143
142
|
- lib/loxxy/front_end/parser.rb
|
144
143
|
- lib/loxxy/front_end/raw_parser.rb
|
145
144
|
- lib/loxxy/front_end/scanner.rb
|
@@ -171,7 +170,7 @@ require_paths:
|
|
171
170
|
- lib
|
172
171
|
required_ruby_version: !ruby/object:Gem::Requirement
|
173
172
|
requirements:
|
174
|
-
- - "
|
173
|
+
- - ">="
|
175
174
|
- !ruby/object:Gem::Version
|
176
175
|
version: '2.5'
|
177
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
@@ -180,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
180
179
|
- !ruby/object:Gem::Version
|
181
180
|
version: '0'
|
182
181
|
requirements: []
|
183
|
-
rubygems_version: 3.
|
182
|
+
rubygems_version: 3.3.3
|
184
183
|
signing_key:
|
185
184
|
specification_version: 4
|
186
185
|
summary: An implementation of the Lox programming language.
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rley'
|
4
|
-
|
5
|
-
module Loxxy
|
6
|
-
module FrontEnd
|
7
|
-
# The superclass for all tokens that have a data value.
|
8
|
-
class Literal < Rley::Lexical::Token
|
9
|
-
# @return [Datatype] The value expressed in one of the Lox datatype.
|
10
|
-
attr_reader :value
|
11
|
-
|
12
|
-
# Constructor.
|
13
|
-
# @param aValue [Datatype::BuiltinDatatype] the Lox data value
|
14
|
-
# @param aLexeme [String] the lexeme (= piece of text from input)
|
15
|
-
# @param aTerminal [Rley::Syntax::Terminal, String]
|
16
|
-
# The terminal symbol corresponding to the lexeme.
|
17
|
-
# @param aPosition [Rley::Lexical::Position] The position of lexeme
|
18
|
-
# in input text.
|
19
|
-
def initialize(aValue, aLexeme, aTerminal, aPosition)
|
20
|
-
super(aLexeme, aTerminal, aPosition)
|
21
|
-
@value = aValue
|
22
|
-
end
|
23
|
-
end # class
|
24
|
-
end # module
|
25
|
-
end # module
|