dendroid 0.0.4 → 0.0.5
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 +38 -0
- data/dendroid.gemspec +1 -0
- data/lib/dendroid/syntax/choice.rb +84 -0
- data/lib/dendroid/syntax/production.rb +1 -2
- data/spec/dendroid/syntax/choice_spec.rb +54 -0
- data/version.txt +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e94a9721000d8e9a45184107ec3488a3dad0c92337507c6753d4cbfa973400fd
|
4
|
+
data.tar.gz: 03bbe70d73b5e12de42b5dca4f008f1850fb9efcc4272115e5123c7397984f4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8dde1d9509f2d713db092e5730a1c37f1aaab2a1a58b45cb46c3e28011e672d6c27d9e630262d96a5e5597de35b9278aab8b6e2b87934bf4840e024eee0d6bea
|
7
|
+
data.tar.gz: d927b08bf68f6c2a128c92c4724a533991799acf207cd13c381d4abea4cbbf8b340de17771c0a41c351bed3a0d6ac2cd523990d1c0bb699824ce14b9ccd97fe6
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [Unreleased]
|
4
|
+
|
5
|
+
## [0.0.5] - 2023-10-28
|
6
|
+
### Added
|
7
|
+
- Class `Choice` and its spec file
|
8
|
+
|
9
|
+
### Fixed
|
10
|
+
- File `dendroid.gemspec`: added missing `CHANGELOG.md` in the package
|
11
|
+
|
12
|
+
## [0.0.4] - 2023-10-28
|
13
|
+
### Added
|
14
|
+
- Class `Production` and its spec file
|
15
|
+
|
16
|
+
## [0.0.3] - 2023-10-28
|
17
|
+
### Added
|
18
|
+
- Class `Rule` and its spec file
|
19
|
+
|
20
|
+
## [0.0.2] - 2023-10-28
|
21
|
+
### Added
|
22
|
+
- Class `SymbolSeq` and its spec file
|
23
|
+
- File `CHANGELOG.md`; the file file you're reading now.
|
24
|
+
|
25
|
+
### Changed
|
26
|
+
- Line separator set to lf (line feed)
|
27
|
+
- Code re-styling to please Rubocop 1.57.1
|
28
|
+
|
29
|
+
## [0.0.1] - 2023-10-27
|
30
|
+
### Added
|
31
|
+
- Class `NonTerminal` and its spec file
|
32
|
+
|
33
|
+
## [0.0.0] - 2023-10-27
|
34
|
+
- Initial commit
|
35
|
+
|
36
|
+
### Added
|
37
|
+
- Class `GrmSymbol` and its spec file
|
38
|
+
- Class `Terminal` and its spec file
|
data/dendroid.gemspec
CHANGED
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'rule'
|
4
|
+
|
5
|
+
module Dendroid
|
6
|
+
module Syntax
|
7
|
+
# A specialization of the Rule class.
|
8
|
+
# A choice is a rule with multiple rhs
|
9
|
+
class Choice < Rule
|
10
|
+
# @return [Array<Dendroid::Syntax::SymbolSeq>]
|
11
|
+
attr_reader :alternatives
|
12
|
+
|
13
|
+
# Create a Choice instance.
|
14
|
+
# @param lhs [Dendroid::Syntax::NonTerminal] The left-hand side of the rule.
|
15
|
+
# @param alt [Array<Dendroid::Syntax::SymbolSeq>] the alternatives (each as a sequence of symbols).
|
16
|
+
def initialize(lhs, alt)
|
17
|
+
super(lhs)
|
18
|
+
@alternatives = valid_alternatives(alt)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Predicate method to check whether the rule has alternatives
|
22
|
+
# @return [TrueClass]
|
23
|
+
def choice?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return the text representation of the choice
|
28
|
+
# @return [String]
|
29
|
+
def to_s
|
30
|
+
"#{head} => #{alternatives.join(' | ')}"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Predicate method to check whether the choice rule body is productive.
|
34
|
+
# It is productive when at least of its alternative is productive.
|
35
|
+
# @return [Boolean]
|
36
|
+
def productive?
|
37
|
+
productive_alts = alternatives.select(&:productive?)
|
38
|
+
return false if productive_alts.empty?
|
39
|
+
|
40
|
+
@productive = Set.new(productive_alts)
|
41
|
+
head.productive = true
|
42
|
+
end
|
43
|
+
|
44
|
+
# Predicate method to check whether the rule has at least one empty alternative.
|
45
|
+
# @return [Boolean]
|
46
|
+
def empty?
|
47
|
+
alternatives.any?(&:empty?)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns an array with the symbol sequence of its alternatives
|
51
|
+
# @return [Array<Dendroid::Syntax::SymbolSeq>]
|
52
|
+
def rhs
|
53
|
+
alternatives
|
54
|
+
end
|
55
|
+
|
56
|
+
# Equality operator
|
57
|
+
# Two production rules are equal when their head and alternatives are equal.
|
58
|
+
# @return [Boolean]
|
59
|
+
def ==(other)
|
60
|
+
return true if equal?(other)
|
61
|
+
return false if other.is_a?(Production)
|
62
|
+
|
63
|
+
(head == other.head) && (alternatives == other.alternatives)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def valid_alternatives(alt)
|
69
|
+
if alt.size < 2
|
70
|
+
# A choice must have at least two alternatives
|
71
|
+
raise StandardError.new, "The choice for #{lhs} must have at least two alternatives."
|
72
|
+
end
|
73
|
+
|
74
|
+
cyclic = alt.find { |a| a.size == 1 && lhs == a.first }
|
75
|
+
if cyclic
|
76
|
+
# Forbid cyclic rules (e.g. A => A)
|
77
|
+
raise StandardError.new, "Cyclic rule of the kind #{lhs} => #{lhs} is not allowed."
|
78
|
+
end
|
79
|
+
|
80
|
+
alt
|
81
|
+
end
|
82
|
+
end # class
|
83
|
+
end # module
|
84
|
+
end # module
|
@@ -5,8 +5,7 @@ require_relative 'rule'
|
|
5
5
|
module Dendroid
|
6
6
|
module Syntax
|
7
7
|
# A specialization of the Rule class.
|
8
|
-
# A production is
|
9
|
-
# at its left-hand side (lhs).
|
8
|
+
# A production is a rule with a single rhs
|
10
9
|
class Production < Rule
|
11
10
|
# @return [Dendroid::Syntax::SymbolSeq]
|
12
11
|
attr_reader :body
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '..\..\spec_helper'
|
4
|
+
require_relative '..\..\..\lib\dendroid\syntax\terminal'
|
5
|
+
require_relative '..\..\..\lib\dendroid\syntax\non_terminal'
|
6
|
+
require_relative '..\..\..\lib\dendroid\syntax\symbol_seq'
|
7
|
+
require_relative '..\..\..\lib\dendroid\syntax\choice'
|
8
|
+
|
9
|
+
describe Dendroid::Syntax::Choice do
|
10
|
+
let(:num_symb) { Dendroid::Syntax::Terminal.new('NUMBER') }
|
11
|
+
let(:plus_symb) { Dendroid::Syntax::Terminal.new('PLUS') }
|
12
|
+
let(:minus_symb) { Dendroid::Syntax::Terminal.new('MINUS') }
|
13
|
+
let(:expr_symb) { Dendroid::Syntax::NonTerminal.new('expression') }
|
14
|
+
let(:foo_symb) { Dendroid::Syntax::NonTerminal.new('foo') }
|
15
|
+
let(:alt1) { Dendroid::Syntax::SymbolSeq.new([num_symb, plus_symb, num_symb]) }
|
16
|
+
let(:alt2) { Dendroid::Syntax::SymbolSeq.new([num_symb, minus_symb, num_symb]) }
|
17
|
+
let(:empty_body) { Dendroid::Syntax::SymbolSeq.new([]) }
|
18
|
+
|
19
|
+
# Implements a choice rule:
|
20
|
+
# expression => NUMBER PLUS NUMBER
|
21
|
+
# | NUMBER MINUS NUMBER
|
22
|
+
# | epsilon
|
23
|
+
subject { described_class.new(expr_symb, [alt1, alt2, empty_body]) }
|
24
|
+
|
25
|
+
context 'Initialization:' do
|
26
|
+
it 'is initialized with a head and alternatives' do
|
27
|
+
expect { described_class.new(expr_symb, [alt1, alt2, empty_body]) }.not_to raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'knows its alternatives' do
|
31
|
+
expect(subject.alternatives).to eq([alt1, alt2, empty_body])
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'renders a String representation of itself' do
|
35
|
+
expectation = 'expression => NUMBER PLUS NUMBER | NUMBER MINUS NUMBER | '
|
36
|
+
expect(subject.to_s).to eq(expectation)
|
37
|
+
end
|
38
|
+
end # context
|
39
|
+
|
40
|
+
context 'Provided services:' do
|
41
|
+
it 'knows its terminal members' do
|
42
|
+
expect(subject.terminals).to eq([num_symb, plus_symb, minus_symb])
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'knows its non-terminal members' do
|
46
|
+
expect(subject.nonterminals).to be_empty
|
47
|
+
|
48
|
+
my_alt1 = Dendroid::Syntax::SymbolSeq.new([expr_symb, plus_symb, expr_symb])
|
49
|
+
my_alt2 = Dendroid::Syntax::SymbolSeq.new([foo_symb, minus_symb, expr_symb])
|
50
|
+
instance = described_class.new(foo_symb, [my_alt1, my_alt2])
|
51
|
+
expect(instance.nonterminals).to eq([expr_symb, foo_symb])
|
52
|
+
end
|
53
|
+
end # context
|
54
|
+
end # describe
|
data/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.5
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dendroid
|
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
|
@@ -17,18 +17,21 @@ extensions: []
|
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
19
|
- ".rubocop.yml"
|
20
|
+
- CHANGELOG.md
|
20
21
|
- LICENSE
|
21
22
|
- README.md
|
22
23
|
- Rakefile
|
23
24
|
- bin/dendroid
|
24
25
|
- dendroid.gemspec
|
25
26
|
- lib/dendroid/dendroid.rb
|
27
|
+
- lib/dendroid/syntax/choice.rb
|
26
28
|
- lib/dendroid/syntax/grm_symbol.rb
|
27
29
|
- lib/dendroid/syntax/non_terminal.rb
|
28
30
|
- lib/dendroid/syntax/production.rb
|
29
31
|
- lib/dendroid/syntax/rule.rb
|
30
32
|
- lib/dendroid/syntax/symbol_seq.rb
|
31
33
|
- lib/dendroid/syntax/terminal.rb
|
34
|
+
- spec/dendroid/syntax/choice_spec.rb
|
32
35
|
- spec/dendroid/syntax/grm_symbol_spec.rb
|
33
36
|
- spec/dendroid/syntax/non_terminal_spec.rb
|
34
37
|
- spec/dendroid/syntax/production_spec.rb
|