zenlish 0.1.0
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 +7 -0
- data/.rspec +3 -0
- data/.yardopts +6 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +95 -0
- data/Rakefile +6 -0
- data/lib/zenlish.rb +9 -0
- data/lib/zenlish/lex/empty_lexicon.rb +7 -0
- data/lib/zenlish/lex/empty_lexicon_factory.rb +32 -0
- data/lib/zenlish/lex/lexeme.rb +19 -0
- data/lib/zenlish/lex/lexical_entry.rb +19 -0
- data/lib/zenlish/lex/lexicon.rb +55 -0
- data/lib/zenlish/lex/literal.rb +16 -0
- data/lib/zenlish/parser/zenlish_grammar.rb +29 -0
- data/lib/zenlish/parser/zparser.rb +30 -0
- data/lib/zenlish/version.rb +3 -0
- data/lib/zenlish/wclasses/adjective.rb +9 -0
- data/lib/zenlish/wclasses/all_word_classes.rb +11 -0
- data/lib/zenlish/wclasses/article.rb +9 -0
- data/lib/zenlish/wclasses/common_noun.rb +9 -0
- data/lib/zenlish/wclasses/definite_article.rb +9 -0
- data/lib/zenlish/wclasses/demonstrative_determiner.rb +9 -0
- data/lib/zenlish/wclasses/determiner.rb +9 -0
- data/lib/zenlish/wclasses/indefinite_pronoun.rb +9 -0
- data/lib/zenlish/wclasses/irregular_verb.rb +9 -0
- data/lib/zenlish/wclasses/lexical_verb.rb +9 -0
- data/lib/zenlish/wclasses/noun.rb +11 -0
- data/lib/zenlish/wclasses/pronoun.rb +9 -0
- data/lib/zenlish/wclasses/proper_noun.rb +10 -0
- data/lib/zenlish/wclasses/test_hierarchy.rb +3 -0
- data/lib/zenlish/wclasses/verb.rb +9 -0
- data/lib/zenlish/wclasses/word_class.rb +20 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/zenlish/lex/empty_lexicon_factory_spec.rb +35 -0
- data/spec/zenlish/lex/lexeme_spec.rb +39 -0
- data/spec/zenlish/lex/lexical_entry_spec.rb +46 -0
- data/spec/zenlish/lex/lexicon_spec.rb +104 -0
- data/spec/zenlish/lex/literal_spec.rb +41 -0
- data/spec/zenlish/parser/zenlish_grammar_spec.rb +21 -0
- data/spec/zenlish/parser/zparser_spec.rb +86 -0
- data/spec/zenlish/support/minimal_lexicon.rb +30 -0
- data/spec/zenlish/wclasses/common_noun_spec.rb +22 -0
- data/spec/zenlish/wclasses/irregular_verb_spec.rb +21 -0
- data/spec/zenlish/wclasses/proper_noun_spec.rb +21 -0
- data/spec/zenlish_spec.rb +5 -0
- data/zenlish.gemspec +61 -0
- metadata +158 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative 'word_class'
|
2
|
+
|
3
|
+
module Zenlish
|
4
|
+
module WClasses
|
5
|
+
# A noun denotes classes and categories of things in the unverse of discourse.
|
6
|
+
# Nouns denote people, animals, inanimate things, places, events, qualities
|
7
|
+
# and states.
|
8
|
+
class Noun < WordClass
|
9
|
+
end # class
|
10
|
+
end # module
|
11
|
+
end # module
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rley'
|
2
|
+
|
3
|
+
module Zenlish
|
4
|
+
module WClasses
|
5
|
+
# Also known as: part of speech, syntactic category or word category.
|
6
|
+
# A word class represents a group of word which have similar functions.
|
7
|
+
# Word classes are divided into:
|
8
|
+
# - Lexical words (?? same as content words??) such as nouns, verbs, adjectives, adverbs
|
9
|
+
# Content words carry the meaning of a sentence
|
10
|
+
# - Function words (?? same as structure words??) such as pronouns, determiners, modal verbs,
|
11
|
+
# auxiliary verbs,
|
12
|
+
# Structure words structure a sentence
|
13
|
+
# conjunctions and prepositions
|
14
|
+
class WordClass < Rley::Syntax::Terminal
|
15
|
+
def initialize
|
16
|
+
super(self.class.name.split('::').last)
|
17
|
+
end
|
18
|
+
end # class
|
19
|
+
end # module
|
20
|
+
end # module
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'rspec' # Use the RSpec framework
|
3
|
+
# require_relative '../lib/zenlish'
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
# Enable flags like --only-failures and --next-failure
|
7
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
8
|
+
|
9
|
+
config.expect_with :rspec do |c|
|
10
|
+
c.syntax = :expect
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../spec_helper' # Use the RSpec framework
|
4
|
+
|
5
|
+
# Load module under test
|
6
|
+
require_relative '../../../lib/zenlish/lex/empty_lexicon_factory'
|
7
|
+
|
8
|
+
module Zenlish
|
9
|
+
module Lex
|
10
|
+
describe EmptyLexiconFactory do
|
11
|
+
subject do
|
12
|
+
obj = Object.new
|
13
|
+
obj.extend(EmptyLexiconFactory)
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'Mix-in integration:' do
|
17
|
+
it 'should acquire the methods of the mix-in module' do
|
18
|
+
expect(subject.respond_to?(:create_empty_lexicon)).to be_truthy
|
19
|
+
end
|
20
|
+
end # context
|
21
|
+
|
22
|
+
context 'Created lexicon:' do
|
23
|
+
it 'should allow the creation of empty lexicon' do
|
24
|
+
expect(subject.create_empty_lexicon).to be_kind_of(Lexicon)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should initialize lexicon with terminal symbols of the language' do
|
28
|
+
lexicon = subject.create_empty_lexicon
|
29
|
+
found = lexicon.terminals.find { |symb| symb.kind_of?(WClasses::CommonNoun) }
|
30
|
+
expect(found).to be_truthy
|
31
|
+
end
|
32
|
+
end # context
|
33
|
+
end # describe
|
34
|
+
end # module
|
35
|
+
end # module
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../../lib/zenlish/wclasses/all_word_classes'
|
5
|
+
require_relative '../../../lib/zenlish/lex/lexical_entry'
|
6
|
+
require_relative '../../../lib/zenlish/lex/lexeme' # Load the class under test
|
7
|
+
|
8
|
+
module Zenlish
|
9
|
+
module Lex
|
10
|
+
describe Lexeme do
|
11
|
+
let(:sample_wclass) { WClasses::CommonNoun.new }
|
12
|
+
let(:sample_lemma) { 'thing' }
|
13
|
+
let(:sample_entry) { LexicalEntry.new(sample_lemma) }
|
14
|
+
|
15
|
+
subject { Lexeme.new(sample_wclass, sample_entry) }
|
16
|
+
|
17
|
+
context 'Initialization:' do
|
18
|
+
it 'should be initialized with a word class and a lexical entry' do
|
19
|
+
expect { Lexeme.new(sample_wclass, sample_entry) }.not_to raise_error
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should know its word class' do
|
23
|
+
expect(subject.wclass).to eq(sample_wclass)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should know its lexical entry' do
|
27
|
+
expect(subject.entry).to eq(sample_entry)
|
28
|
+
end
|
29
|
+
end # context
|
30
|
+
|
31
|
+
context 'Provided services:' do
|
32
|
+
it 'should know its lemma' do
|
33
|
+
expect(subject.lemma).to eq(sample_lemma)
|
34
|
+
end
|
35
|
+
end # context
|
36
|
+
end # describe
|
37
|
+
end # module
|
38
|
+
end # module
|
39
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../spec_helper' # Use the RSpec framework'
|
4
|
+
require_relative '../../../lib/zenlish/lex/lexical_entry' # Load the class under test
|
5
|
+
|
6
|
+
module Zenlish
|
7
|
+
module Lex
|
8
|
+
describe LexicalEntry do
|
9
|
+
let(:sample_lemma) { 'other' }
|
10
|
+
let(:sample_lexeme1) { double('other-as-adjective') }
|
11
|
+
let(:sample_lexeme2) { double('other-as-pronoun') }
|
12
|
+
subject { LexicalEntry.new(sample_lemma) }
|
13
|
+
|
14
|
+
context 'Initialization:' do
|
15
|
+
it 'can be initialized with a lemma only' do
|
16
|
+
expect { LexicalEntry.new(sample_lemma) }.not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'can be initialized with a lemma and a word class' do
|
20
|
+
expect { LexicalEntry.new(sample_lemma, sample_lexeme1) }.not_to raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should know its lemma' do
|
24
|
+
expect(subject.lemma).to eq(sample_lemma)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should know its lexeme (if any)' do
|
28
|
+
expect(subject.lexemes).to be_empty
|
29
|
+
instance = LexicalEntry.new(sample_lemma, sample_lexeme1)
|
30
|
+
expect(instance.lexemes).to eq([sample_lexeme1])
|
31
|
+
end
|
32
|
+
end # context
|
33
|
+
|
34
|
+
context 'Provided services:' do
|
35
|
+
|
36
|
+
it 'should accept links with lexeme(s)' do
|
37
|
+
subject.add_lexeme(sample_lexeme1)
|
38
|
+
expect(subject.lexemes).to eq([sample_lexeme1])
|
39
|
+
|
40
|
+
subject.add_lexeme(sample_lexeme2)
|
41
|
+
expect(subject.lexemes).to eq([sample_lexeme1, sample_lexeme2])
|
42
|
+
end
|
43
|
+
end # context
|
44
|
+
end # describe
|
45
|
+
end # module
|
46
|
+
end # module
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../spec_helper' # Use the RSpec framework'
|
4
|
+
require_relative '../../../lib/zenlish/wclasses/all_word_classes'
|
5
|
+
require_relative '../../../lib/zenlish/lex/lexical_entry'
|
6
|
+
require_relative '../../../lib/zenlish/lex/lexeme'
|
7
|
+
require_relative '../../../lib/zenlish/lex/lexicon' # Load the class under test
|
8
|
+
|
9
|
+
=begin
|
10
|
+
|
11
|
+
minimal_lexicon = Zenlish::Lex::Lexicon.new
|
12
|
+
ent = Zenlish::Lex::LexicalEntry.new('Lisa')
|
13
|
+
lexeme = Zenlish::Lex::Lexeme.new(o_proper_noun, ent)
|
14
|
+
minimal_lexicon.add_entry(ent)
|
15
|
+
|
16
|
+
ent = Zenlish::Lex::LexicalEntry.new('see')
|
17
|
+
lexeme = Zenlish::Lex::Lexeme.new(o_irregular_verb, ent)
|
18
|
+
minimal_lexicon.add_entry(ent)
|
19
|
+
|
20
|
+
ent = Zenlish::Lex::LexicalEntry.new('Tony')
|
21
|
+
lexeme = Zenlish::Lex::Lexeme.new(o_proper_noun, ent)
|
22
|
+
minimal_lexicon.add_entry(ent)
|
23
|
+
=end
|
24
|
+
|
25
|
+
|
26
|
+
module Zenlish
|
27
|
+
module Lex
|
28
|
+
describe Lexicon do
|
29
|
+
def create_entry(aLemma, aWordClass)
|
30
|
+
entry = Zenlish::Lex::LexicalEntry.new(aLemma)
|
31
|
+
lexeme = Zenlish::Lex::Lexeme.new(aWordClass, entry)
|
32
|
+
entry
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:adjective) { Zenlish::WClasses::Adjective.new }
|
36
|
+
let(:proper_noun) { Zenlish::WClasses::ProperNoun.new }
|
37
|
+
let(:pronoun) { Zenlish::WClasses::Pronoun.new }
|
38
|
+
let(:irregular_verb) { Zenlish::WClasses::IrregularVerb.new }
|
39
|
+
|
40
|
+
let(:sample_lexeme) { double('other-as-adjective') }
|
41
|
+
let(:sample_entry) { LexicalEntry.new('other', sample_lexeme) }
|
42
|
+
let(:other_lexeme) { double('other-as-pronoun') }
|
43
|
+
let(:similar_entry) { LexicalEntry.new('other', other_lexeme) }
|
44
|
+
let(:verb_lexeme) { double('hope-as-verb') }
|
45
|
+
let(:distinct_entry) {LexicalEntry.new('hope', verb_lexeme) }
|
46
|
+
subject { Lexicon.new }
|
47
|
+
|
48
|
+
context 'Initialization:' do
|
49
|
+
it 'should be initialized without parameter' do
|
50
|
+
expect { Lexicon.new }.not_to raise_error
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should have no registered terminals at initialization' do
|
54
|
+
expect(subject.terminals).to be_empty
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should have no entry at initialization' do
|
58
|
+
expect(subject.entries).to be_empty
|
59
|
+
expect(subject.lemma2entry).to be_empty
|
60
|
+
end
|
61
|
+
end # context
|
62
|
+
|
63
|
+
context 'Provided services:' do
|
64
|
+
it 'should accept the addition of terminals' do
|
65
|
+
terminal1 = proper_noun
|
66
|
+
terminal2 = irregular_verb
|
67
|
+
terminal3 = adjective
|
68
|
+
|
69
|
+
subject.add_terminal(terminal1)
|
70
|
+
expect(subject.terminals).to eq([terminal1])
|
71
|
+
subject.add_terminal(terminal2)
|
72
|
+
expect(subject.terminals).to eq([terminal1, terminal2])
|
73
|
+
subject.add_terminal(terminal3)
|
74
|
+
expect(subject.terminals).to eq([terminal1, terminal2, terminal3])
|
75
|
+
expect(subject.name2terminal['ProperNoun']).to eq(terminal1)
|
76
|
+
expect(subject.name2terminal['IrregularVerb']).to eq(terminal2)
|
77
|
+
expect(subject.name2terminal['Adjective']).to eq(terminal3)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should accept the addition of entries' do
|
81
|
+
subject.add_entry(sample_entry)
|
82
|
+
expect(subject.entries).to eq([sample_entry])
|
83
|
+
expect(subject.lemma2entry['other']).to eq(sample_entry)
|
84
|
+
|
85
|
+
# Add dissimilar entry
|
86
|
+
subject.add_entry(distinct_entry)
|
87
|
+
expect(subject.entries).to eq([sample_entry, distinct_entry])
|
88
|
+
expect(subject.lemma2entry['hope']).to eq(distinct_entry)
|
89
|
+
|
90
|
+
# Add "homonym" entry
|
91
|
+
subject.add_entry(similar_entry)
|
92
|
+
expect(subject.entries).to eq([sample_entry, distinct_entry, similar_entry])
|
93
|
+
expect(subject.lemma2entry['other']).to eq([sample_entry, similar_entry])
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should complain when retrieving an non-existing entry' do
|
97
|
+
subject.add_entry(sample_entry)
|
98
|
+
err_msg = 'key not found: "hapax"'
|
99
|
+
expect { subject.get_lexeme('hapax') }.to raise_error(KeyError, err_msg)
|
100
|
+
end
|
101
|
+
end # context
|
102
|
+
end # describe
|
103
|
+
end # module
|
104
|
+
end # module
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../../lib/zenlish/wclasses/all_word_classes'
|
5
|
+
require_relative '../../../lib/zenlish/lex/lexical_entry'
|
6
|
+
require_relative '../../../lib/zenlish/lex/lexeme'
|
7
|
+
require_relative '../../../lib/zenlish/lex/literal' # Load the class under test
|
8
|
+
|
9
|
+
module Zenlish
|
10
|
+
module Lex
|
11
|
+
describe Lexeme do
|
12
|
+
let(:sample_wclass) { WClasses::CommonNoun.new }
|
13
|
+
let(:sample_lemma) { 'thing' }
|
14
|
+
let(:sample_entry) { LexicalEntry.new(sample_lemma) }
|
15
|
+
let(:sample_position) { double('position') }
|
16
|
+
let(:sample_lexeme) { Lexeme.new(sample_wclass, sample_entry) }
|
17
|
+
|
18
|
+
subject { Literal.new('things', sample_lexeme, sample_position) }
|
19
|
+
|
20
|
+
context 'Initialization:' do
|
21
|
+
it 'should be initialized with a string, a lexeme and a position' do
|
22
|
+
expect { Literal.new('things', sample_lexeme, sample_position) }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
# it 'should know its word class' do
|
26
|
+
# expect(subject.wclass).to eq(sample_wclass)
|
27
|
+
# end
|
28
|
+
|
29
|
+
# it 'should know its lexical entry' do
|
30
|
+
# expect(subject.entry).to eq(sample_entry)
|
31
|
+
# end
|
32
|
+
end # context
|
33
|
+
|
34
|
+
context 'Provided services:' do
|
35
|
+
# it 'should know its lemma' do
|
36
|
+
# expect(subject.lemma).to eq(sample_lemma)
|
37
|
+
# end
|
38
|
+
end # context
|
39
|
+
end # describe
|
40
|
+
end # module
|
41
|
+
end # module
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../../lib/zenlish/parser/zenlish_grammar' # Load the class under test
|
5
|
+
|
6
|
+
module Zenlish
|
7
|
+
module Parser
|
8
|
+
describe ZenlishGrammar do
|
9
|
+
subject { ZenlishGrammar }
|
10
|
+
|
11
|
+
context 'Initialization:' do
|
12
|
+
it 'should know its terminal symbols' do
|
13
|
+
expect { subject.name2symbol['CommonNoun'] }.not_to raise_error
|
14
|
+
end
|
15
|
+
end # context
|
16
|
+
|
17
|
+
context 'Provided services:' do
|
18
|
+
end # context
|
19
|
+
end # describe
|
20
|
+
end # module
|
21
|
+
end # module
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../support/minimal_lexicon'
|
5
|
+
require_relative '../../../lib/zenlish/lex/literal'
|
6
|
+
require_relative '../../../lib/zenlish/parser/zparser' # Load the class under test
|
7
|
+
|
8
|
+
module Zenlish
|
9
|
+
module Parser
|
10
|
+
describe ZParser do
|
11
|
+
subject { ZParser.new }
|
12
|
+
|
13
|
+
context 'Initialization:' do
|
14
|
+
it 'should be initialized without argument' do
|
15
|
+
expect { ZParser.new }.not_to raise_error
|
16
|
+
end
|
17
|
+
end # context
|
18
|
+
|
19
|
+
context 'Provided services:' do
|
20
|
+
def get_lexeme(aLemma)
|
21
|
+
$ZenlishLexicon.get_lexeme(aLemma)
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:tony) do
|
25
|
+
Lex::Literal.new('Tony', $ZenlishLexicon.get_lexeme('Tony'), 0)
|
26
|
+
end
|
27
|
+
let(:lisa) do
|
28
|
+
Lex::Literal.new('Lisa', $ZenlishLexicon.get_lexeme('Lisa'), 0)
|
29
|
+
end
|
30
|
+
let(:the) do
|
31
|
+
Lex::Literal.new('the', $ZenlishLexicon.get_lexeme('the'), 0)
|
32
|
+
end
|
33
|
+
let(:other) do
|
34
|
+
Lex::Literal.new('other', $ZenlishLexicon.get_lexeme('other'), 0)
|
35
|
+
end
|
36
|
+
let(:sees) do
|
37
|
+
Lex::Literal.new('sees', $ZenlishLexicon.get_lexeme('see'), 0)
|
38
|
+
end
|
39
|
+
let(:dot) do
|
40
|
+
Lex::Literal.new('.', $ZenlishLexicon.get_lexeme('.'), 0)
|
41
|
+
end
|
42
|
+
let(:something) do
|
43
|
+
Lex::Literal.new('something', $ZenlishLexicon.get_lexeme('something'), 0)
|
44
|
+
end
|
45
|
+
let(:thing) do
|
46
|
+
Lex::Literal.new('thing', $ZenlishLexicon.get_lexeme('thing'), 0)
|
47
|
+
end
|
48
|
+
let(:this) do
|
49
|
+
Lex::Literal.new('this', $ZenlishLexicon.get_lexeme('this'), 0)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should parse sample sentence 1-01' do
|
53
|
+
# Sentence is: "Tony sees Lisa."
|
54
|
+
# in absence of a tokenizer, we create a sequence of literals by hand...
|
55
|
+
literals = [tony, sees, lisa, dot]
|
56
|
+
expect { subject.parse(literals) }.not_to raise_error
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'should parse sample sentence 1-02a' do
|
60
|
+
# Sentence is: "Tony sees something."
|
61
|
+
sentence_literals = [tony, sees, something, dot]
|
62
|
+
expect { subject.parse(sentence_literals) }.not_to raise_error
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should parse sample sentence 1-02b' do
|
66
|
+
# Sentence is: "Lisa sees something"
|
67
|
+
sentence_literals = [lisa, sees, something, dot]
|
68
|
+
expect { subject.parse(sentence_literals) }.not_to raise_error
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should parse sample sentence 1-03' do
|
72
|
+
# Sentence is: "Tony sees this thing."
|
73
|
+
sentence_literals = [tony, sees, this, thing, dot]
|
74
|
+
expect { subject.parse(sentence_literals) }.not_to raise_error
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should parse sample sentence 1-04' do
|
78
|
+
# Sentence is: "Lisa sees the other thing."
|
79
|
+
sentence_literals = [lisa, sees, the, other, thing, dot]
|
80
|
+
expect { subject.parse(sentence_literals) }.not_to raise_error
|
81
|
+
end
|
82
|
+
end # context
|
83
|
+
end # describe
|
84
|
+
end # module
|
85
|
+
end # module
|
86
|
+
|