sequitur 0.1.24 → 0.1.26
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 +7 -1
- data/Gemfile +2 -4
- data/LICENSE.txt +1 -1
- data/README.md +2 -3
- data/appveyor.yml +10 -10
- data/examples/inductive_english.rb +35 -0
- data/lib/sequitur/constants.rb +6 -5
- data/lib/sequitur/digram.rb +9 -9
- data/lib/sequitur/dynamic_grammar.rb +9 -8
- data/lib/sequitur/formatter/base_formatter.rb +1 -1
- data/lib/sequitur/formatter/base_text.rb +5 -2
- data/lib/sequitur/formatter/debug.rb +10 -3
- data/lib/sequitur/grammar_visitor.rb +6 -6
- data/lib/sequitur/production.rb +20 -17
- data/lib/sequitur/production_ref.rb +9 -8
- data/lib/sequitur/symbol_sequence.rb +6 -6
- data/lib/sequitur.rb +2 -1
- data/sig/lib/sequitur/constants.rbs +10 -0
- data/sig/lib/sequitur/digram.rbs +37 -0
- data/sig/lib/sequitur/dynamic_grammar.rbs +58 -0
- data/sig/lib/sequitur/formatter/base_formatter.rbs +20 -0
- data/sig/lib/sequitur/formatter/base_text.rbs +62 -0
- data/sig/lib/sequitur/formatter/debug.rbs +89 -0
- data/sig/lib/sequitur/production.rbs +120 -0
- data/sig/lib/sequitur/production_ref.rbs +73 -0
- data/sig/lib/sequitur/sequitur_grammar.rbs +55 -0
- data/sig/lib/sequitur/symbol_sequence.rbs +83 -0
- data/sig/lib/sequitur.rbs +9 -0
- data/spec/sequitur/symbol_sequence_spec.rb +1 -4
- metadata +47 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 86e5e7a51109f635607be37902ce3edf561b204119005eea6baa0f90d1dc90b8
|
4
|
+
data.tar.gz: 686f7ed1ba3e76ab16f06b891809025afd7b020009b3a67cba7600f4c66c18cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff134c984fe467059df107491030b84cfd1c73aca32ef78eca7fca90a5f207db06c552dab126e12e81eb97537789b6d24c36cdf79af0e7934fcf42ff17c818b1
|
7
|
+
data.tar.gz: b6c909ca88b6031252c53f11d4e07babae1c0fe0f3b146d50e0aaea55be7befa5a4fdf8ac456c8da76ecac0cfe579f41f939cdb569c605e9da6fb491d5182991
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
## [0.1.
|
1
|
+
## [0.1.25] - 2023-07-10
|
2
|
+
- First version using RBS (Ruby Type System): new folder `sig` with `*.rbs` files
|
3
|
+
- Yard documentation updated to align with RBS
|
4
|
+
- File `appveyor.yml` updated to cover Rubies 2.6, .., 3.1
|
5
|
+
- File `Gemfile`: removed dependencies to `simplecov` and `coverall`
|
6
|
+
|
7
|
+
## [0.1.24] - 2023-07-01
|
2
8
|
- Code restyling to please rubocop 1.53.1
|
3
9
|
|
4
10
|
## [0.1.23] - 2021-09-04
|
data/Gemfile
CHANGED
@@ -4,8 +4,6 @@ source 'https://rubygems.org'
|
|
4
4
|
# Prevent Bundler to load the dependencies from our .gemspec file
|
5
5
|
|
6
6
|
group :development do
|
7
|
-
gem '
|
8
|
-
gem '
|
9
|
-
gem 'rspec', '>= 3.0.0'
|
10
|
-
gem 'simplecov', '>= 0.8.0'
|
7
|
+
gem 'rake', '>= 13.1.0'
|
8
|
+
gem 'rspec', '>= 3.10.0'
|
11
9
|
end
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -3,9 +3,8 @@ Sequitur
|
|
3
3
|
_Ruby gem implementing the Sequitur algorithm_
|
4
4
|
[Homepage](https://github.com/famished-tiger/Sequitur)
|
5
5
|
|
6
|
-
|
6
|
+
|
7
7
|
[](https://ci.appveyor.com/project/famished-tiger/sequitur)
|
8
|
-
[](https://coveralls.io/r/famished-tiger/Sequitur)
|
9
8
|
[](http://badge.fury.io/rb/sequitur)
|
10
9
|
[](http://inch-ci.org/github/famished-tiger/Sequitur)
|
11
10
|
[](https://codeclimate.com/github/famished-tiger/Sequitur)
|
@@ -247,4 +246,4 @@ More examples are available in the examples folder.
|
|
247
246
|
|
248
247
|
Copyright
|
249
248
|
---------
|
250
|
-
Copyright (c) 2014-
|
249
|
+
Copyright (c) 2014-2025, Dimitri Geshef. Sequitur is released under the MIT License see [LICENSE.txt](https://github.com/famished-tiger/Sequitur/blob/master/LICENSE.txt) for details.
|
data/appveyor.yml
CHANGED
@@ -2,19 +2,19 @@ version: '{build}'
|
|
2
2
|
max_jobs: 5
|
3
3
|
environment:
|
4
4
|
matrix:
|
5
|
-
- Ruby_version:
|
6
|
-
- Ruby_version:
|
7
|
-
- Ruby_version:
|
8
|
-
- Ruby_version:
|
9
|
-
- Ruby_version:
|
10
|
-
- Ruby_version:
|
11
|
-
- Ruby_version: 24
|
12
|
-
- Ruby_version: 23
|
5
|
+
- Ruby_version: 31-x64
|
6
|
+
- Ruby_version: 30-x64
|
7
|
+
- Ruby_version: 27-x64
|
8
|
+
- Ruby_version: 31
|
9
|
+
- Ruby_version: 30
|
10
|
+
- Ruby_version: 27
|
13
11
|
|
12
|
+
# - gem update --system --source http://rubygems.org/
|
14
13
|
install:
|
15
14
|
- set PATH=C:\Ruby%Ruby_version%\bin;%PATH%
|
16
|
-
-
|
17
|
-
- gem install
|
15
|
+
- ruby --version
|
16
|
+
- gem install rubygems-update
|
17
|
+
- gem install bundler
|
18
18
|
- bundle install --retry=3 --clean --force
|
19
19
|
|
20
20
|
build: off
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Demo of sequitur gem: from a set of sentences, generate a context-free grammar
|
4
|
+
|
5
|
+
require 'engtagger'
|
6
|
+
require 'sequitur'
|
7
|
+
|
8
|
+
# Simple sentences taken from the first lesson of "Learn These Words First".
|
9
|
+
# ( https://learnthesewordsfirst.com/ )
|
10
|
+
sentences = <<~END_TEXT
|
11
|
+
Tony sees Lisa.
|
12
|
+
Tony sees something.
|
13
|
+
Lisa sees something.
|
14
|
+
Tony sees this thing.
|
15
|
+
Lisa sees the other thing.
|
16
|
+
END_TEXT
|
17
|
+
|
18
|
+
tagger = EngTagger.new
|
19
|
+
pairs = tagger.tag_pairs(sentences)
|
20
|
+
tag_sequence = pairs.map(&:last)
|
21
|
+
|
22
|
+
# Generate the grammar from the tag sequence
|
23
|
+
grammar = Sequitur.build_from(tag_sequence)
|
24
|
+
|
25
|
+
# Use a formatter to display the grammar rules on the console output
|
26
|
+
formatter = Sequitur::Formatter::BaseText.new($stdout)
|
27
|
+
|
28
|
+
# Now render the rules
|
29
|
+
formatter.render(grammar.visitor)
|
30
|
+
# Rendered output is:
|
31
|
+
# start : P1 nnp P2 P2 P4 nn P4 jj nn pp.
|
32
|
+
# P1 : nnp vbz.
|
33
|
+
# P2 : P3 nn.
|
34
|
+
# P3 : pp P1.
|
35
|
+
# P4 : P3 det.
|
data/lib/sequitur/constants.rb
CHANGED
@@ -3,13 +3,14 @@
|
|
3
3
|
# File: constants.rb
|
4
4
|
# Purpose: definition of Sequitur constants.
|
5
5
|
|
6
|
-
|
6
|
+
# Module used as a namespace for Sequitur classes
|
7
|
+
module Sequitur
|
7
8
|
# rubocop:disable Naming/ConstantName
|
8
9
|
|
9
|
-
# The version number of the gem.
|
10
|
-
Version = '0.1.
|
10
|
+
# @return [String] The version number of the gem.
|
11
|
+
Version = '0.1.26'
|
11
12
|
|
12
|
-
# Brief description of the gem.
|
13
|
+
# @return [String] Brief description of the gem.
|
13
14
|
Description = 'Ruby implementation of the Sequitur algorithm'
|
14
15
|
|
15
16
|
# Constant Sequitur::RootDir contains the absolute path of Sequitur's
|
@@ -18,7 +19,7 @@ module Sequitur # Module used as a namespace
|
|
18
19
|
# The initialisation of constant RootDir is guarded in order
|
19
20
|
# to avoid multiple initialisation (not allowed for constants)
|
20
21
|
|
21
|
-
# The start folder of Sequitur.
|
22
|
+
# @return [String] The start folder of Sequitur.
|
22
23
|
RootDir = begin
|
23
24
|
require 'pathname' # Load Pathname class from standard library
|
24
25
|
startdir = Pathname(__FILE__).dirname.parent.parent.expand_path
|
data/lib/sequitur/digram.rb
CHANGED
@@ -9,22 +9,22 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
9
9
|
# can be a terminal or not.
|
10
10
|
class Digram
|
11
11
|
# The sequence of two consecutive grammar symbols.
|
12
|
-
#
|
12
|
+
# @return [Array<String, Symbol>] The two symbols should respond to the :hash message.
|
13
13
|
attr_reader(:symbols)
|
14
14
|
|
15
|
-
# An unique hash key of the digram
|
15
|
+
# @return [String] An unique hash key of the digram
|
16
16
|
attr_reader(:key)
|
17
17
|
|
18
|
-
# The production in which the digram occurs
|
18
|
+
# @return [Sequitur::Production] The production in which the digram occurs
|
19
19
|
attr_reader(:production)
|
20
20
|
|
21
21
|
# Constructor.
|
22
22
|
# A digram represents a sequence of two symbols
|
23
23
|
# (that appears in a rhs of a production).
|
24
24
|
# Terminal symbols must respond to the :hash message.
|
25
|
-
# @param symbol1 [
|
26
|
-
# @param symbol2 [
|
27
|
-
# @param aProduction [Production] Production in which the RHS
|
25
|
+
# @param symbol1 [String, Symbol] First element of the digram
|
26
|
+
# @param symbol2 [String, Symbol] Second element of the digram
|
27
|
+
# @param aProduction [Sequitur::Production] Production in which the RHS
|
28
28
|
# the sequence symbol1 symbol2 appears.
|
29
29
|
def initialize(symbol1, symbol2, aProduction)
|
30
30
|
@symbols = [symbol1, symbol2]
|
@@ -34,14 +34,14 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
34
34
|
|
35
35
|
# Equality testing.
|
36
36
|
# true iff keys of both digrams are equal, false otherwise
|
37
|
-
# @param other [Digram] another to compare with
|
38
|
-
# @return [
|
37
|
+
# @param other [Sequitur::Digram] another to compare with
|
38
|
+
# @return [TrueClass, FalseClass]
|
39
39
|
def ==(other)
|
40
40
|
key == other.key
|
41
41
|
end
|
42
42
|
|
43
43
|
# Does the digram consists of twice the same symbols?
|
44
|
-
# @return [
|
44
|
+
# @return [TrueClass, FalseClass] true when symbols.first == symbols.last
|
45
45
|
def repeating?
|
46
46
|
symbols[0] == symbols[1]
|
47
47
|
end
|
@@ -13,13 +13,13 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
13
13
|
# -terminal symbols (i.e. String, Ruby Symbol,...)
|
14
14
|
# -non-terminal symbols (i.e. ProductionRef)
|
15
15
|
class DynamicGrammar
|
16
|
-
# Link to the start production.
|
16
|
+
# @return [Sequitur::Production] Link to the start production.
|
17
17
|
attr_reader(:start)
|
18
18
|
|
19
|
-
# The set of production rules of the grammar
|
19
|
+
# @return [Array<Sequitur::Production>] The set of production rules of the grammar
|
20
20
|
attr_reader(:productions)
|
21
21
|
|
22
|
-
#
|
22
|
+
# @return [TrueClass, FalseClass] Trace the execution of the algorithm.
|
23
23
|
attr_accessor(:trace)
|
24
24
|
|
25
25
|
# Constructor.
|
@@ -38,7 +38,8 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# Add a given production to the grammar.
|
41
|
-
# @param aProduction [Production]
|
41
|
+
# @param aProduction [Sequitur::Production]
|
42
|
+
# @return [Array<Sequitur::Production>]
|
42
43
|
def add_production(aProduction)
|
43
44
|
# TODO: remove output
|
44
45
|
puts "Adding #{aProduction.object_id}" if trace
|
@@ -47,8 +48,8 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
47
48
|
end
|
48
49
|
|
49
50
|
# Remove a production with given index from the grammar
|
50
|
-
# @param anIndex [
|
51
|
-
# @return [Production] the production removed from the grammar.
|
51
|
+
# @param anIndex [Integer]
|
52
|
+
# @return [Sequitur::Production] the production removed from the grammar.
|
52
53
|
def remove_production(anIndex)
|
53
54
|
puts "Before production removal #{productions[anIndex].object_id}" if trace
|
54
55
|
puts to_string if trace
|
@@ -69,7 +70,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
69
70
|
|
70
71
|
# Part of the 'visitee' role in the Visitor design pattern.
|
71
72
|
# A visitee is expected to accept the visit from a visitor object
|
72
|
-
# @param aVisitor [GrammarVisitor] the visitor object
|
73
|
+
# @param aVisitor [Sequitur::GrammarVisitor] the visitor object
|
73
74
|
def accept(aVisitor)
|
74
75
|
aVisitor.start_visit_grammar(self)
|
75
76
|
|
@@ -80,7 +81,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
80
81
|
end
|
81
82
|
|
82
83
|
# Factory method. Returns a visitor for this grammar.
|
83
|
-
# @return [GrammarVisitor]
|
84
|
+
# @return [Sequitur::GrammarVisitor]
|
84
85
|
def visitor
|
85
86
|
GrammarVisitor.new(self)
|
86
87
|
end
|
@@ -17,7 +17,7 @@ module Sequitur
|
|
17
17
|
|
18
18
|
# Given a grammar or a grammar visitor, perform the visit
|
19
19
|
# and render the visit events in the output stream.
|
20
|
-
# @param aGrmOrVisitor [DynamicGrammar
|
20
|
+
# @param aGrmOrVisitor [DynamicGrammar, GrammarVisitor]
|
21
21
|
def render(aGrmOrVisitor)
|
22
22
|
a_visitor = if aGrmOrVisitor.is_a?(GrammarVisitor)
|
23
23
|
aGrmOrVisitor
|
@@ -12,6 +12,7 @@ module Sequitur
|
|
12
12
|
# # Render the grammar (through a visitor)
|
13
13
|
# formatter.run(some_grammar.visitor)
|
14
14
|
class BaseText < BaseFormatter
|
15
|
+
# @return [Hash{Production => Integer}]
|
15
16
|
attr_reader :prod_lookup
|
16
17
|
|
17
18
|
# Constructor.
|
@@ -24,7 +25,7 @@ module Sequitur
|
|
24
25
|
|
25
26
|
# Method called by a GrammarVisitor to which the formatter subscribed.
|
26
27
|
# Notification of a visit event: the visitor is about to visit a grammar
|
27
|
-
# @param aGrammar [DynamicGrammar
|
28
|
+
# @param aGrammar [DynamicGrammar]
|
28
29
|
def before_grammar(aGrammar)
|
29
30
|
aGrammar.productions.each_with_index do |a_prod, index|
|
30
31
|
prod_lookup[a_prod] = index
|
@@ -34,7 +35,7 @@ module Sequitur
|
|
34
35
|
# Method called by a GrammarVisitor to which the formatter subscribed.
|
35
36
|
# Notification of a visit event: the visitor is about to visit
|
36
37
|
# a production
|
37
|
-
# @param aProduction [
|
38
|
+
# @param aProduction [Production]
|
38
39
|
def before_production(aProduction)
|
39
40
|
p_name = prod_name(aProduction)
|
40
41
|
output.print p_name
|
@@ -69,6 +70,7 @@ module Sequitur
|
|
69
70
|
# Method called by a GrammarVisitor to which the formatter subscribed.
|
70
71
|
# Notification of a visit event: the visitor complete the visit
|
71
72
|
# of a production
|
73
|
+
# @param _ [Production]
|
72
74
|
def after_production(_)
|
73
75
|
output.print ".\n"
|
74
76
|
end
|
@@ -77,6 +79,7 @@ module Sequitur
|
|
77
79
|
|
78
80
|
# Generate a name of a given production.
|
79
81
|
# @param aProduction [Production]
|
82
|
+
# @return [String]
|
80
83
|
def prod_name(aProduction)
|
81
84
|
prod_index = prod_lookup[aProduction]
|
82
85
|
prod_index.zero? ? 'start' : "P#{prod_index}"
|
@@ -13,7 +13,7 @@ module Sequitur
|
|
13
13
|
# # Render the visit notifications
|
14
14
|
# formatter.run(some_grammar.visitor)
|
15
15
|
class Debug < BaseFormatter
|
16
|
-
# Current indentation level
|
16
|
+
# @return [Integer] Current indentation level
|
17
17
|
attr_accessor(:indentation)
|
18
18
|
|
19
19
|
# Constructor.
|
@@ -26,7 +26,7 @@ module Sequitur
|
|
26
26
|
|
27
27
|
# Method called by a GrammarVisitor to which the formatter subscribed.
|
28
28
|
# Notification of a visit event: the visitor is about to visit a grammar
|
29
|
-
# @param _ [DynamicGrammar
|
29
|
+
# @param _ [DynamicGrammar]
|
30
30
|
def before_grammar(_)
|
31
31
|
output_event(__method__, indentation)
|
32
32
|
indent
|
@@ -35,7 +35,7 @@ module Sequitur
|
|
35
35
|
# Method called by a GrammarVisitor to which the formatter subscribed.
|
36
36
|
# Notification of a visit event: the visitor is about to visit
|
37
37
|
# a production
|
38
|
-
# @param _ [
|
38
|
+
# @param _ [Production]
|
39
39
|
def before_production(_)
|
40
40
|
output_event(__method__, indentation)
|
41
41
|
indent
|
@@ -95,6 +95,7 @@ module Sequitur
|
|
95
95
|
# Method called by a GrammarVisitor to which the formatter subscribed.
|
96
96
|
# Notification of a visit event: the visitor completed the visit
|
97
97
|
# of a production
|
98
|
+
# @param _ [Production]
|
98
99
|
def after_production(_)
|
99
100
|
dedent
|
100
101
|
output_event(__method__, indentation)
|
@@ -103,6 +104,7 @@ module Sequitur
|
|
103
104
|
# Method called by a GrammarVisitor to which the formatter subscribed.
|
104
105
|
# Notification of a visit event: the visitor completed the visit
|
105
106
|
# of a grammar
|
107
|
+
# @param _ [DynamicGrammar]
|
106
108
|
def after_grammar(_)
|
107
109
|
dedent
|
108
110
|
output_event(__method__, indentation)
|
@@ -110,14 +112,19 @@ module Sequitur
|
|
110
112
|
|
111
113
|
private
|
112
114
|
|
115
|
+
# @return [Integer]
|
113
116
|
def indent
|
114
117
|
@indentation += 1
|
115
118
|
end
|
116
119
|
|
120
|
+
# @return [Integer]
|
117
121
|
def dedent
|
118
122
|
@indentation -= 1
|
119
123
|
end
|
120
124
|
|
125
|
+
# @param anEvent [Symbol]
|
126
|
+
# @param indentationLevel [Integer]
|
127
|
+
# @return [NilClass]
|
121
128
|
def output_event(anEvent, indentationLevel)
|
122
129
|
output.puts "#{' ' * 2 * indentationLevel}#{anEvent}"
|
123
130
|
end
|
@@ -3,14 +3,14 @@
|
|
3
3
|
module Sequitur # Module for classes implementing the Sequitur algorithm
|
4
4
|
# A visitor class dedicated in the visit of Grammar.
|
5
5
|
class GrammarVisitor
|
6
|
-
# Link to the grammar to visit
|
6
|
+
# @return [Sequitur::DynamicGrammar] Link to the grammar to visit
|
7
7
|
attr_reader(:grammar)
|
8
8
|
|
9
|
-
# List of objects that subscribed to the visit event notification.
|
9
|
+
# @return [Object] List of objects that subscribed to the visit event notification.
|
10
10
|
attr_reader(:subscribers)
|
11
11
|
|
12
12
|
# Build a visitor for the given grammar.
|
13
|
-
# @param aGrammar [DynamicGrammar
|
13
|
+
# @param aGrammar [DynamicGrammar] the grammar to visit.
|
14
14
|
def initialize(aGrammar)
|
15
15
|
@grammar = aGrammar
|
16
16
|
@subscribers = []
|
@@ -35,13 +35,13 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
35
35
|
end
|
36
36
|
|
37
37
|
# Visit event. The visitor is about to visit the grammar.
|
38
|
-
# @param aGrammar [DynamicGrammar
|
38
|
+
# @param aGrammar [DynamicGrammar] the grammar to visit.
|
39
39
|
def start_visit_grammar(aGrammar)
|
40
40
|
broadcast(:before_grammar, aGrammar)
|
41
41
|
end
|
42
42
|
|
43
43
|
# Visit event. The visitor is about to visit the given production.
|
44
|
-
# @param aProduction [Production] the production to visit.
|
44
|
+
# @param aProduction [Sequitur::Production] the production to visit.
|
45
45
|
def start_visit_production(aProduction)
|
46
46
|
broadcast(:before_production, aProduction)
|
47
47
|
end
|
@@ -82,7 +82,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
82
82
|
end
|
83
83
|
|
84
84
|
# Visit event. The visitor has completed the visit of the grammar.
|
85
|
-
# @param aGrammar [DynamicGrammar
|
85
|
+
# @param aGrammar [DynamicGrammar] the grammar to visit.
|
86
86
|
def end_visit_grammar(aGrammar)
|
87
87
|
broadcast(:after_grammar, aGrammar)
|
88
88
|
end
|
data/lib/sequitur/production.rb
CHANGED
@@ -14,13 +14,14 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
14
14
|
# corresponding RHS.
|
15
15
|
# Implementation note: the object id of the production is taken as its LHS.
|
16
16
|
class Production
|
17
|
-
# The right-hand side (rhs)
|
17
|
+
# @return [Sequitur::SymbolSequence] The right-hand side (rhs)
|
18
|
+
# consists of a sequence of grammar symbols
|
18
19
|
attr_reader(:rhs)
|
19
20
|
|
20
|
-
# The reference count (= how times other productions reference this one)
|
21
|
+
# @return [Integer] The reference count (= how times other productions reference this one)
|
21
22
|
attr_reader(:refcount)
|
22
23
|
|
23
|
-
# The sequence of digrams appearing in the RHS
|
24
|
+
# @return [Array<Sequitur::Digram>] The sequence of digrams appearing in the RHS
|
24
25
|
attr_reader(:digrams)
|
25
26
|
|
26
27
|
# Constructor.
|
@@ -32,8 +33,8 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
32
33
|
end
|
33
34
|
|
34
35
|
# Identity testing.
|
35
|
-
# @param other [] another production or production reference.
|
36
|
-
# @return true when the receiver and other are the same.
|
36
|
+
# @param other [Production, ProductionRef] another production or production reference.
|
37
|
+
# @return [TrueClass, FalseClass] true when the receiver and other are the same.
|
37
38
|
def ==(other)
|
38
39
|
return true if object_id == other.object_id
|
39
40
|
|
@@ -45,17 +46,19 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
45
46
|
end
|
46
47
|
|
47
48
|
# Is the rhs empty?
|
48
|
-
# @
|
49
|
+
# @return [TrueClass, FalseClass] true if the rhs has no members.
|
49
50
|
def empty?
|
50
51
|
rhs.empty?
|
51
52
|
end
|
52
53
|
|
53
54
|
# Increment the reference count by one.
|
55
|
+
# @return [Integer]
|
54
56
|
def incr_refcount
|
55
57
|
@refcount += 1
|
56
58
|
end
|
57
59
|
|
58
60
|
# Decrement the reference count by one.
|
61
|
+
# @return [Integer]
|
59
62
|
def decr_refcount
|
60
63
|
raise StandardError, 'Internal error' if @refcount.zero?
|
61
64
|
|
@@ -63,21 +66,21 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
63
66
|
end
|
64
67
|
|
65
68
|
# Select the references to production appearing in the rhs.
|
66
|
-
# @return [Array
|
69
|
+
# @return [Array<ProductionRef>]
|
67
70
|
def references
|
68
71
|
rhs.references
|
69
72
|
end
|
70
73
|
|
71
74
|
# Look in the rhs all the references to a production passed a argument.
|
72
|
-
#
|
73
|
-
# @return [Array]
|
75
|
+
# @param a_prod [Production, ProductionRef] The production to search for.
|
76
|
+
# @return [Array<ProductionRef>]
|
74
77
|
def references_of(a_prod)
|
75
78
|
real_prod = a_prod.is_a?(ProductionRef) ? a_prod.production : a_prod
|
76
79
|
rhs.references_of(real_prod)
|
77
80
|
end
|
78
81
|
|
79
82
|
# Enumerate the digrams appearing in the right-hand side (rhs)
|
80
|
-
# @return [Array] the list of digrams found in rhs of this production.
|
83
|
+
# @return [Array<Sequitur::Digram>] the list of digrams found in rhs of this production.
|
81
84
|
def recalc_digrams
|
82
85
|
return [] if rhs.size < 2
|
83
86
|
|
@@ -87,7 +90,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
87
90
|
end
|
88
91
|
|
89
92
|
# Does the rhs have exactly one digram only (= 2 symbols)?
|
90
|
-
# @return [
|
93
|
+
# @return [TrueClass, FalseClass] true when the rhs contains exactly two symbols.
|
91
94
|
def single_digram?
|
92
95
|
rhs.size == 2
|
93
96
|
end
|
@@ -95,7 +98,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
95
98
|
# Detect whether the last digram occurs twice
|
96
99
|
# Assumption: when a digram occurs twice in a production then it must occur
|
97
100
|
# at the end of the rhs
|
98
|
-
# @return [
|
101
|
+
# @return [TrueClass, FalseClass] true when the digram occurs twice in rhs.
|
99
102
|
def repeated_digram?
|
100
103
|
return false if rhs.size < 3
|
101
104
|
|
@@ -107,7 +110,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
107
110
|
end
|
108
111
|
|
109
112
|
# Retrieve the last digram appearing in the RHS (if any).
|
110
|
-
# @return [Digram] last digram in the rhs otherwise nil.
|
113
|
+
# @return [Sequitur::Digram, NilClass] last digram in the rhs otherwise nil.
|
111
114
|
def last_digram
|
112
115
|
digrams.empty? ? nil : digrams.last
|
113
116
|
end
|
@@ -150,7 +153,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
150
153
|
# Find all the positions where the digram occurs in the rhs
|
151
154
|
# @param symb1 [Object] first symbol of the digram
|
152
155
|
# @param symb2 [Object] second symbol of the digram
|
153
|
-
# @return [Array] the list of indices where the digram occurs in rhs.
|
156
|
+
# @return [Array<Integer>] the list of indices where the digram occurs in rhs.
|
154
157
|
# @example
|
155
158
|
# # Given the production p : a b c a b a b d
|
156
159
|
# #Then ...
|
@@ -176,7 +179,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
176
179
|
# Given that the production P passed as argument has exactly 2 symbols
|
177
180
|
# in its rhs s1 s2, substitute in the rhs of self all occurrences of
|
178
181
|
# s1 s2 by a reference to P.
|
179
|
-
# @param another [Production
|
182
|
+
# @param another [Production, ProductionRef] a production that
|
180
183
|
# consists exactly of one digram (= 2 symbols).
|
181
184
|
def reduce_step(another)
|
182
185
|
(symb1, symb2) = another.rhs.symbols
|
@@ -190,7 +193,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
190
193
|
|
191
194
|
# Replace every occurrence of 'another' production in self.rhs by
|
192
195
|
# the symbols in the rhs of 'another'.
|
193
|
-
# @param another [Production
|
196
|
+
# @param another [Production, ProductionRef] a production that
|
194
197
|
# consists exactly of one digram (= 2 symbols).
|
195
198
|
# @example Synopsis
|
196
199
|
# # Given the production p_A : a p_B b p_B c
|
@@ -211,7 +214,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
211
214
|
end
|
212
215
|
|
213
216
|
# Part of the 'visitee' role in Visitor design pattern.
|
214
|
-
# @param aVisitor[GrammarVisitor]
|
217
|
+
# @param aVisitor[Sequitur::GrammarVisitor]
|
215
218
|
def accept(aVisitor)
|
216
219
|
aVisitor.start_visit_production(self)
|
217
220
|
rhs.accept(aVisitor)
|
@@ -17,11 +17,11 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
17
17
|
# # ... Production reference count is updated...
|
18
18
|
# puts prod.refcount # outputs 1
|
19
19
|
class ProductionRef
|
20
|
-
# Link to the production to reference.
|
20
|
+
# @return [Sequitur::Production] Link to the production to reference.
|
21
21
|
attr_reader(:production)
|
22
22
|
|
23
23
|
# Constructor
|
24
|
-
# @param target [Production
|
24
|
+
# @param target [Production, ProductionRef]
|
25
25
|
# The production that is being referenced.
|
26
26
|
def initialize(target)
|
27
27
|
bind_to(target)
|
@@ -51,8 +51,8 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
51
51
|
# A production ref is equal to another one when its
|
52
52
|
# refers to the same production or when it is compared to
|
53
53
|
# the production it refers to.
|
54
|
-
# @param other [ProductionRef]
|
55
|
-
# @return [
|
54
|
+
# @param other [Production, ProductionRef]
|
55
|
+
# @return [TrueClass, FalseClass]
|
56
56
|
def ==(other)
|
57
57
|
return true if object_id == other.object_id
|
58
58
|
|
@@ -67,7 +67,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
67
67
|
# A reference has no identity on its own,
|
68
68
|
# the method returns the hash value of the
|
69
69
|
# referenced production
|
70
|
-
# @return [
|
70
|
+
# @return [Integer] the hash value
|
71
71
|
def hash
|
72
72
|
raise StandardError, 'Nil production' if production.nil?
|
73
73
|
|
@@ -75,7 +75,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
75
75
|
end
|
76
76
|
|
77
77
|
# Make this reference point to the given production.
|
78
|
-
# @param aProduction [Production
|
78
|
+
# @param aProduction [Production, ProductionRef] the production
|
79
79
|
# to refer to
|
80
80
|
def bind_to(aProduction)
|
81
81
|
return if aProduction == @production
|
@@ -90,20 +90,21 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
90
90
|
end
|
91
91
|
|
92
92
|
# Clear the reference to the target production.
|
93
|
+
# return [NilClass]
|
93
94
|
def unbind
|
94
95
|
production.decr_refcount
|
95
96
|
@production = nil
|
96
97
|
end
|
97
98
|
|
98
99
|
# Check that the this object doesn't refer to any production.
|
99
|
-
# @return [
|
100
|
+
# @return [TrueClass, FalseClass] true when this object doesn't
|
100
101
|
# point to a production.
|
101
102
|
def unbound?
|
102
103
|
production.nil?
|
103
104
|
end
|
104
105
|
|
105
106
|
# Part of the 'visitee' role in the Visitor design pattern.
|
106
|
-
# @param aVisitor [GrammarVisitor] the visitor
|
107
|
+
# @param aVisitor [Sequitur::GrammarVisitor] the visitor
|
107
108
|
def accept(aVisitor)
|
108
109
|
aVisitor.visit_prod_ref(self)
|
109
110
|
end
|
@@ -4,7 +4,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
4
4
|
# Represents a sequence (concatenation) of grammar symbols
|
5
5
|
# as they appear in rhs of productions
|
6
6
|
class SymbolSequence
|
7
|
-
# The sequence of symbols itself
|
7
|
+
# @return [Array] The sequence of symbols itself
|
8
8
|
attr_reader(:symbols)
|
9
9
|
|
10
10
|
# Create an empty sequence
|
@@ -59,9 +59,9 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
59
59
|
end
|
60
60
|
|
61
61
|
# Equality testing.
|
62
|
-
# @param other [SymbolSequence
|
62
|
+
# @param other [SymbolSequence, Array] the other other sequence
|
63
63
|
# to compare to.
|
64
|
-
# @true when an item from self equals the corresponding
|
64
|
+
# @return [TrueClass, FalseClass] true when an item from self equals the corresponding
|
65
65
|
# item from 'other'
|
66
66
|
def ==(other)
|
67
67
|
true if object_id == other.object_id
|
@@ -119,9 +119,9 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
119
119
|
# Given that the production P passed as argument has exactly 2 symbols
|
120
120
|
# in its rhs s1 s2, substitute in the rhs of self all occurrences of
|
121
121
|
# s1 s2 by a reference to P.
|
122
|
-
# @param index [
|
122
|
+
# @param index [Integer] the position of a two symbol sequence to be replaced
|
123
123
|
# by the production
|
124
|
-
# @param aProduction [Production
|
124
|
+
# @param aProduction [Production, ProductionRef] a production that
|
125
125
|
# consists exactly of one digram (= 2 symbols).
|
126
126
|
def reduce_step(index, aProduction)
|
127
127
|
if symbols[index].is_a?(ProductionRef)
|
@@ -141,7 +141,7 @@ module Sequitur # Module for classes implementing the Sequitur algorithm
|
|
141
141
|
end
|
142
142
|
|
143
143
|
# Remove the element at given position
|
144
|
-
# @param position [
|
144
|
+
# @param position [Integer] a zero-based index.
|
145
145
|
def delete_at(position)
|
146
146
|
invalidate_refs if symbols[position].is_a?(ProductionRef)
|
147
147
|
symbols.delete_at(position)
|