loxxy 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -0
- data/.yardopts +6 -0
- data/CHANGELOG.md +7 -0
- data/README.md +39 -3
- data/lib/loxxy/datatype/builtin_datatype.rb +3 -4
- data/lib/loxxy/datatype/false.rb +3 -3
- data/lib/loxxy/datatype/lx_string.rb +4 -9
- data/lib/loxxy/datatype/nil.rb +3 -3
- data/lib/loxxy/datatype/number.rb +2 -10
- data/lib/loxxy/datatype/true.rb +4 -4
- data/lib/loxxy/front_end/grammar.rb +4 -5
- data/lib/loxxy/front_end/literal.rb +1 -1
- data/lib/loxxy/front_end/raw_parser.rb +2 -3
- data/lib/loxxy/front_end/scanner.rb +4 -6
- data/lib/loxxy/version.rb +1 -1
- data/loxxy.gemspec +2 -2
- data/spec/datatype/lx_string_spec.rb +35 -35
- data/spec/front_end/raw_parser_spec.rb +3 -1
- data/spec/front_end/scanner_spec.rb +2 -2
- data/spec/loxxy_spec.rb +1 -1
- data/spec/spec_helper.rb +5 -3
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5db00fee0e8e7ef89a48cacc4e9ad0baf7ae5ee2cb419ba76964199bd7552199
|
4
|
+
data.tar.gz: ddb8e9c7ac267f32bed3f77ada05a6af38a872b5f892452a496b17522b608977
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44e0049b0bc01e5d35bed7b91c32a7a3b977e6ba4e806439958bad2dc8aae7ead017a310c8523bd4cb628c14951946981bee42f4001d68b701159fcdaff53419
|
7
|
+
data.tar.gz: c90236a82f0a4872b209b8462d5f13377815fd4fc41babf256ff4894ea6900e343c6f192194e1b713cb9f8a8d2bffc326e7ea4f00726193e0a792dc9e1457e41
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
AllCops:
|
2
2
|
Exclude:
|
3
3
|
- 'exp/**/*'
|
4
|
+
- 'demo/**/*'
|
4
5
|
|
5
6
|
Layout/ArgumentAlignment:
|
6
7
|
Enabled: false
|
@@ -55,6 +56,9 @@ Layout/MultilineMethodCallBraceLayout:
|
|
55
56
|
|
56
57
|
Layout/SpaceAroundOperators:
|
57
58
|
Enabled: true
|
59
|
+
|
60
|
+
Layout/SpaceBeforeBrackets:
|
61
|
+
Enabled: true
|
58
62
|
|
59
63
|
Layout/SpaceInsideParens:
|
60
64
|
Enabled: true
|
@@ -70,6 +74,9 @@ Layout/TrailingEmptyLines:
|
|
70
74
|
|
71
75
|
Layout/TrailingWhitespace:
|
72
76
|
Enabled: true
|
77
|
+
|
78
|
+
Lint/AmbiguousAssignment:
|
79
|
+
Enabled: true
|
73
80
|
|
74
81
|
Lint/DuplicateBranch:
|
75
82
|
Enabled: true
|
@@ -226,6 +233,9 @@ Style/GuardClause:
|
|
226
233
|
|
227
234
|
Style/HashEachMethods:
|
228
235
|
Enabled: true
|
236
|
+
|
237
|
+
Style/HashExcept:
|
238
|
+
Enabled: true
|
229
239
|
|
230
240
|
Style/HashTransformKeys:
|
231
241
|
Enabled: true
|
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## [0.0.5] - 2021-01-02
|
2
|
+
- Improved example in `README.md`, code re-styling to please `Rubocop` 1.7
|
3
|
+
|
4
|
+
## Changed
|
5
|
+
- Code re-styling to please `Rubocop` 1.7
|
6
|
+
- File `README.md` Improved example with better parse tree visualization.
|
7
|
+
|
1
8
|
## [0.0.4] - 2021-01-01
|
2
9
|
- A first parser implementation able to parse Lox source code.
|
3
10
|
|
data/README.md
CHANGED
@@ -13,6 +13,8 @@ a simple language used in Bob Nystrom's online book [Crafting Interpreters](http
|
|
13
13
|
- [DONE] Scanner (tokenizer)
|
14
14
|
- [DONE] Raw parser. It parses Lox programs and generates a parse tree.
|
15
15
|
- [TODO] Tailored parser for generating AST (Abstract Syntax Tree)
|
16
|
+
- [TODO] Custom AST builder class
|
17
|
+
- [TODO] Hierarchy classes for representing Lox expressions in AST
|
16
18
|
- [TODO] Interpreter or transpiler
|
17
19
|
|
18
20
|
|
@@ -34,11 +36,45 @@ base_parser = Loxxy::FrontEnd::RawParser.new
|
|
34
36
|
# Now parse the input into a concrete parse tree...
|
35
37
|
ptree = base_parser.parse(lox_input)
|
36
38
|
|
37
|
-
#
|
38
|
-
|
39
|
+
# Display the parse tree thanks to Rley formatters...
|
40
|
+
visitor = Rley::ParseTreeVisitor.new(ptree)
|
41
|
+
tree_formatter = Rley::Formatter::Asciitree.new($stdout)
|
42
|
+
tree_formatter.render(visitor)
|
39
43
|
```
|
40
44
|
|
41
|
-
|
45
|
+
This is the output produced by the above example:
|
46
|
+
```
|
47
|
+
program
|
48
|
+
+-- declaration_star
|
49
|
+
| +-- declaration_star
|
50
|
+
| +-- declaration
|
51
|
+
| +-- statement
|
52
|
+
| +-- printStmt
|
53
|
+
| +-- PRINT: 'print'
|
54
|
+
| +-- expression
|
55
|
+
| | +-- assignment
|
56
|
+
| | +-- logic_or
|
57
|
+
| | +-- logic_and
|
58
|
+
| | | +-- equality
|
59
|
+
| | | | +-- comparison
|
60
|
+
| | | | | +-- term
|
61
|
+
| | | | | | +-- factor
|
62
|
+
| | | | | | | +-- unary
|
63
|
+
| | | | | | | | +-- call
|
64
|
+
| | | | | | | | +-- primary
|
65
|
+
| | | | | | | | | +-- STRING: '"Hello, world!"'
|
66
|
+
| | | | | | | | +-- refinement_star
|
67
|
+
| | | | | | | +-- multiplicative_star
|
68
|
+
| | | | | | +-- additive_star
|
69
|
+
| | | | | +-- comparisonTest_star
|
70
|
+
| | | | +-- equalityTest_star
|
71
|
+
| | | +-- conjunct_star
|
72
|
+
| | +-- disjunct_star
|
73
|
+
| +-- SEMICOLON: ';'
|
74
|
+
+-- EOF: ''
|
75
|
+
```
|
76
|
+
|
77
|
+
Soon, the `loxxy` will host another, tailored parser, that will generate
|
42
78
|
abstract syntax tree which much more convenient for further processing
|
43
79
|
(like implementing an interpreter).
|
44
80
|
|
@@ -8,15 +8,14 @@ module Loxxy
|
|
8
8
|
class BuiltinDatatype
|
9
9
|
# @return [Object] The Ruby representation
|
10
10
|
attr_reader :value
|
11
|
-
|
11
|
+
|
12
12
|
# Constructor. Initialize a Lox value from one of its built-in data type.
|
13
13
|
def initialize(aValue)
|
14
14
|
@value = validated_value(aValue)
|
15
15
|
end
|
16
|
-
|
17
|
-
|
16
|
+
|
18
17
|
protected
|
19
|
-
|
18
|
+
|
20
19
|
def validated_value(aValue)
|
21
20
|
aValue
|
22
21
|
end
|
data/lib/loxxy/datatype/false.rb
CHANGED
@@ -8,13 +8,13 @@ module Loxxy
|
|
8
8
|
# Class for representing a Lox false value.
|
9
9
|
class False < Boolean
|
10
10
|
include Singleton # Make a singleton class
|
11
|
-
|
11
|
+
|
12
12
|
# Build the sole instance
|
13
13
|
def initialize
|
14
14
|
super(false)
|
15
15
|
end
|
16
16
|
end # class
|
17
|
-
|
18
|
-
False.instance.freeze
|
17
|
+
|
18
|
+
False.instance.freeze # Make the sole instance immutable
|
19
19
|
end # module
|
20
20
|
end # module
|
@@ -6,12 +6,6 @@ module Loxxy
|
|
6
6
|
module Datatype
|
7
7
|
# Class for representing a Lox string of characters value.
|
8
8
|
class LXString < BuiltinDatatype
|
9
|
-
|
10
|
-
# Build the sole instance
|
11
|
-
def initialize(aValue)
|
12
|
-
super(aValue)
|
13
|
-
end
|
14
|
-
|
15
9
|
# Compare a Lox String with another Lox (or genuine Ruby) String
|
16
10
|
# @param other [Datatype::LxString, String]
|
17
11
|
# @return [Boolean]
|
@@ -22,7 +16,8 @@ module Loxxy
|
|
22
16
|
when String
|
23
17
|
value == other
|
24
18
|
else
|
25
|
-
|
19
|
+
err_msg = "Cannot compare a #{self.class} with #{other.class}"
|
20
|
+
raise StandardError, err_msg
|
26
21
|
end
|
27
22
|
end
|
28
23
|
|
@@ -34,8 +29,8 @@ module Loxxy
|
|
34
29
|
end
|
35
30
|
|
36
31
|
# Remove double quotes delimiter
|
37
|
-
aValue.gsub(/(^")|("$)/, '')
|
32
|
+
aValue.gsub(/(^")|("$)/, '')
|
38
33
|
end
|
39
34
|
end # class
|
40
35
|
end # module
|
41
|
-
end # module
|
36
|
+
end # module
|
data/lib/loxxy/datatype/nil.rb
CHANGED
@@ -8,13 +8,13 @@ module Loxxy
|
|
8
8
|
# Class for representing a Lox nil "value".
|
9
9
|
class Nil < BuiltinDatatype
|
10
10
|
include Singleton # Make a singleton class
|
11
|
-
|
11
|
+
|
12
12
|
# Build the sole instance
|
13
13
|
def initialize
|
14
14
|
super(nil)
|
15
15
|
end
|
16
16
|
end # class
|
17
|
-
|
18
|
-
Nil.instance.freeze
|
17
|
+
|
18
|
+
Nil.instance.freeze # Make the sole instance immutable
|
19
19
|
end # module
|
20
20
|
end # module
|
@@ -6,19 +6,11 @@ module Loxxy
|
|
6
6
|
module Datatype
|
7
7
|
# Class for representing a Lox numeric value.
|
8
8
|
class Number < BuiltinDatatype
|
9
|
-
|
10
|
-
# Build the sole instance
|
11
|
-
def initialize(aValue)
|
12
|
-
super(aValue)
|
13
|
-
end
|
14
|
-
|
15
9
|
protected
|
16
10
|
|
17
11
|
def validated_value(aValue)
|
18
12
|
case aValue
|
19
|
-
when Integer
|
20
|
-
result = aValue
|
21
|
-
when Numeric
|
13
|
+
when Integer, Numeric
|
22
14
|
result = aValue
|
23
15
|
when /^-?\d+$/
|
24
16
|
result = aValue.to_i
|
@@ -32,4 +24,4 @@ module Loxxy
|
|
32
24
|
end
|
33
25
|
end # class
|
34
26
|
end # module
|
35
|
-
end # module
|
27
|
+
end # module
|
data/lib/loxxy/datatype/true.rb
CHANGED
@@ -8,13 +8,13 @@ module Loxxy
|
|
8
8
|
# Class for representing a Lox true value.
|
9
9
|
class True < Boolean
|
10
10
|
include Singleton # Make a singleton class
|
11
|
-
|
11
|
+
|
12
12
|
# Build the sole instance
|
13
13
|
def initialize
|
14
14
|
super(true)
|
15
|
-
end
|
15
|
+
end
|
16
16
|
end # class
|
17
|
-
|
18
|
-
True.instance.freeze
|
17
|
+
|
18
|
+
True.instance.freeze # Make the sole instance immutable
|
19
19
|
end # module
|
20
20
|
end # module
|
@@ -131,7 +131,7 @@ module Loxxy
|
|
131
131
|
rule('primary' => 'IDENTIFIER')
|
132
132
|
rule('primary' => 'LEFT_PAREN expression RIGHT_PAREN')
|
133
133
|
rule('primary' => 'SUPER DOT IDENTIFIER')
|
134
|
-
|
134
|
+
|
135
135
|
# Utility rules
|
136
136
|
rule('function' => 'IDENTIFIER LEFT_PAREN params_opt RIGHT_PAREN block')
|
137
137
|
rule('params_opt' => 'parameters')
|
@@ -142,11 +142,10 @@ module Loxxy
|
|
142
142
|
rule('arguments_opt' => [])
|
143
143
|
rule('arguments' => 'arguments COMMA expression')
|
144
144
|
rule('arguments' => 'expression')
|
145
|
-
|
146
145
|
end
|
147
146
|
|
148
|
-
|
149
|
-
|
150
|
-
|
147
|
+
# And now build the grammar and make it accessible via a constant
|
148
|
+
# @return [Rley::Syntax::Grammar]
|
149
|
+
Grammar = builder.grammar
|
151
150
|
end # module
|
152
151
|
end # module
|
@@ -14,7 +14,7 @@ module Loxxy
|
|
14
14
|
# @param theLexeme [String] the lexeme (= piece of text from input)
|
15
15
|
# @param aTerminal [Rley::Syntax::Terminal, String]
|
16
16
|
# The terminal symbol corresponding to the lexeme.
|
17
|
-
# @param aPosition [Rley::Lexical::Position] The position of lexeme
|
17
|
+
# @param aPosition [Rley::Lexical::Position] The position of lexeme
|
18
18
|
# in input text.
|
19
19
|
def initialize(aValue, aLexeme, aTerminal, aPosition)
|
20
20
|
super(aLexeme, aTerminal, aPosition)
|
@@ -15,7 +15,7 @@ module Loxxy
|
|
15
15
|
# A TerminalNode is leaf node, that is, it has no child node.
|
16
16
|
# While concrete parse tree nodes can be generated out of the box,
|
17
17
|
# they have the following drawbacks:
|
18
|
-
# - Generic node classes that aren't always suited for the needs of
|
18
|
+
# - Generic node classes that aren't always suited for the needs of
|
19
19
|
# the language being processing.
|
20
20
|
# - Concrete parse tree tend to be deeply nested, which may complicate
|
21
21
|
# further processing.
|
@@ -27,7 +27,6 @@ module Loxxy
|
|
27
27
|
# Create a Rley facade object
|
28
28
|
@engine = Rley::Engine.new do |cfg|
|
29
29
|
cfg.diagnose = true
|
30
|
-
# cfg.repr_builder = SkmBuilder
|
31
30
|
end
|
32
31
|
|
33
32
|
# Step 1. Load Lox grammar
|
@@ -52,4 +51,4 @@ module Loxxy
|
|
52
51
|
end
|
53
52
|
end # class
|
54
53
|
end # module
|
55
|
-
end # module
|
54
|
+
end # module
|
@@ -50,7 +50,7 @@ module Loxxy
|
|
50
50
|
'>' => 'GREATER',
|
51
51
|
'>=' => 'GREATER_EQUAL',
|
52
52
|
'<' => 'LESS',
|
53
|
-
'<=' => 'LESS_EQUAL'
|
53
|
+
'<=' => 'LESS_EQUAL'
|
54
54
|
}.freeze
|
55
55
|
|
56
56
|
# Here are all the implemented Lox keywords (in uppercase)
|
@@ -99,7 +99,7 @@ module Loxxy
|
|
99
99
|
|
100
100
|
token = nil
|
101
101
|
|
102
|
-
if
|
102
|
+
if '(){},.;/*'.include? curr_ch
|
103
103
|
# Single delimiter or separator character
|
104
104
|
token = build_token(@@lexeme2name[curr_ch], scanner.getch)
|
105
105
|
elsif (lexeme = scanner.scan(/[+\-](?!\d)/))
|
@@ -150,7 +150,7 @@ module Loxxy
|
|
150
150
|
when 'FALSE'
|
151
151
|
value = Datatype::False.instance
|
152
152
|
when 'NIL'
|
153
|
-
value = Datatype::Nil.instance
|
153
|
+
value = Datatype::Nil.instance
|
154
154
|
when 'NUMBER'
|
155
155
|
value = Datatype::Number.new(aLexeme)
|
156
156
|
when 'STRING'
|
@@ -167,8 +167,6 @@ module Loxxy
|
|
167
167
|
# Skip non-significant whitespaces and comments.
|
168
168
|
# Advance the scanner until something significant is found.
|
169
169
|
def skip_intertoken_spaces
|
170
|
-
pre_pos = scanner.pos
|
171
|
-
|
172
170
|
loop do
|
173
171
|
ws_found = scanner.skip(/[ \t\f]+/) ? true : false
|
174
172
|
nl_found = scanner.skip(/(?:\r\n)|\r|\n/)
|
@@ -191,7 +189,7 @@ module Loxxy
|
|
191
189
|
break unless ws_found || cmt_found
|
192
190
|
end
|
193
191
|
|
194
|
-
|
192
|
+
scanner.pos
|
195
193
|
end
|
196
194
|
|
197
195
|
def skip_block_comment
|
data/lib/loxxy/version.rb
CHANGED
data/loxxy.gemspec
CHANGED
@@ -40,8 +40,8 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.version = Loxxy::VERSION
|
41
41
|
spec.authors = ['Dimitri Geshef']
|
42
42
|
spec.email = ['famished.tiger@yahoo.com']
|
43
|
-
spec.summary =
|
44
|
-
spec.description =
|
43
|
+
spec.summary = 'An implementation of the Lox programming language. WIP'
|
44
|
+
spec.description = 'An implementation of the Lox programming language. WIP'
|
45
45
|
spec.homepage = 'https://github.com/famished-tiger/loxxy'
|
46
46
|
spec.license = 'MIT'
|
47
47
|
spec.required_ruby_version = '~> 2.4'
|
@@ -1,35 +1,35 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
|
5
|
-
# Load the class under test
|
6
|
-
require_relative '../../lib/loxxy/datatype/lx_string'
|
7
|
-
|
8
|
-
module Loxxy
|
9
|
-
module Datatype
|
10
|
-
describe LXString do
|
11
|
-
let(:sample_text) { 'some_text' }
|
12
|
-
subject { LXString.new(sample_text) }
|
13
|
-
|
14
|
-
context 'Initialization:' do
|
15
|
-
it 'should accept a String value at initialization' do
|
16
|
-
expect { LXString.new(sample_text) }.not_to raise_error
|
17
|
-
end
|
18
|
-
|
19
|
-
it 'should know its value' do
|
20
|
-
expect(subject.value).to eq(sample_text)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'Provided services:' do
|
25
|
-
it 'compares with another string' do
|
26
|
-
expect(subject).to eq(sample_text)
|
27
|
-
expect(subject).to eq(LXString.new(sample_text.dup))
|
28
|
-
|
29
|
-
expect(subject).not_to eq('')
|
30
|
-
expect(subject).not_to eq('other-text')
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end # describe
|
34
|
-
end # module
|
35
|
-
end # module
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
|
5
|
+
# Load the class under test
|
6
|
+
require_relative '../../lib/loxxy/datatype/lx_string'
|
7
|
+
|
8
|
+
module Loxxy
|
9
|
+
module Datatype
|
10
|
+
describe LXString do
|
11
|
+
let(:sample_text) { 'some_text' }
|
12
|
+
subject { LXString.new(sample_text) }
|
13
|
+
|
14
|
+
context 'Initialization:' do
|
15
|
+
it 'should accept a String value at initialization' do
|
16
|
+
expect { LXString.new(sample_text) }.not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should know its value' do
|
20
|
+
expect(subject.value).to eq(sample_text)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'Provided services:' do
|
25
|
+
it 'compares with another string' do
|
26
|
+
expect(subject).to eq(sample_text)
|
27
|
+
expect(subject).to eq(LXString.new(sample_text.dup))
|
28
|
+
|
29
|
+
expect(subject).not_to eq('')
|
30
|
+
expect(subject).not_to eq('other-text')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end # describe
|
34
|
+
end # module
|
35
|
+
end # module
|
@@ -92,8 +92,10 @@ LOX_END
|
|
92
92
|
expect(leaf_node.token.value).to eq('Hello, world!')
|
93
93
|
expect(prnt_stmt.subnodes[2]).to be_kind_of(Rley::PTree::TerminalNode)
|
94
94
|
expect(prnt_stmt.subnodes[2].symbol.name).to eq('SEMICOLON')
|
95
|
+
expect(eof).to be_kind_of(Rley::PTree::TerminalNode)
|
96
|
+
expect(eof.symbol.name).to eq('EOF')
|
95
97
|
end
|
96
98
|
end
|
97
99
|
end # describe
|
98
100
|
end # module
|
99
|
-
end # module
|
101
|
+
end # module
|
@@ -78,7 +78,7 @@ module Loxxy
|
|
78
78
|
end
|
79
79
|
|
80
80
|
it 'should recognize non-datatype keywords' do
|
81
|
-
keywords
|
81
|
+
keywords = <<-LOX_END
|
82
82
|
and class else fun for if or
|
83
83
|
print return super this var while
|
84
84
|
LOX_END
|
@@ -167,7 +167,7 @@ LOX_END
|
|
167
167
|
end
|
168
168
|
|
169
169
|
it 'should recognize string values' do
|
170
|
-
input
|
170
|
+
input = <<-LOX_END
|
171
171
|
""
|
172
172
|
"string"
|
173
173
|
"123"
|
data/spec/loxxy_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'loxxy'
|
3
5
|
|
4
6
|
RSpec.configure do |config|
|
5
7
|
# Enable flags like --only-failures and --next-failure
|
6
|
-
config.example_status_persistence_file_path =
|
8
|
+
config.example_status_persistence_file_path = '.rspec_status'
|
7
9
|
|
8
10
|
config.expect_with :rspec do |c|
|
9
11
|
# Disable the `should` syntax
|
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.
|
4
|
+
version: 0.0.5
|
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-
|
11
|
+
date: 2021-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rley
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- ".rspec"
|
78
78
|
- ".rubocop.yml"
|
79
79
|
- ".travis.yml"
|
80
|
+
- ".yardopts"
|
80
81
|
- CHANGELOG.md
|
81
82
|
- Gemfile
|
82
83
|
- LICENSE.txt
|