gullah 0.0.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.
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+
5
+ require 'gullah'
6
+ require 'byebug'
7
+ require 'date'
8
+
9
+ # :stopdoc:
10
+
11
+ # a test to make sure the demo code for the parse class is telling the truth
12
+ class ParseDemoTest < Minitest::Test
13
+ class Example
14
+ extend Gullah
15
+
16
+ rule :S, 'NP VP'
17
+ rule :NP, 'D N'
18
+ rule :VP, 'V'
19
+
20
+ leaf :D, /the/
21
+ leaf :N, /cat/
22
+ leaf :V, /sat/
23
+ end
24
+
25
+ def test_example
26
+ parses = Example.parse 'the cat sat', n: 1
27
+
28
+ parse = parses.first
29
+ assert_equal 1, parse.length
30
+ assert_equal 8, parse.size
31
+ assert_equal 'S[NP[D,_ws,N],_ws,VP[V]]', parse.summary
32
+ end
33
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+
5
+ require 'gullah'
6
+ require 'byebug'
7
+
8
+ # :stopdoc:
9
+
10
+ class PreconditionTest < Minitest::Test
11
+ class Balanced
12
+ extend Gullah
13
+
14
+ rule :a, 'a{2}', preconditions: %i[balanced]
15
+
16
+ leaf :a, /\S+/
17
+
18
+ # we only want a perfectly symmetrical tree
19
+ def balanced(_name, _start, _end, _text, children)
20
+ left, *, right = children
21
+ left.size == right.size
22
+ end
23
+ end
24
+
25
+ def test_test
26
+ parses = Balanced.parse 'foo bar baz plugh'
27
+ assert_equal 1, parses.length, '1 optimal parse'
28
+ parse = parses.first
29
+ assert_equal 1, parse.roots.length, 'parse has a root node'
30
+ root = parse.roots.first
31
+ assertion = root.subtree
32
+ .select(&:nonterminal?)
33
+ .all? { |n| n.children.first.size == n.children.last.size }
34
+ assert assertion, 'the nodes are all balanced'
35
+ end
36
+
37
+ class LeafPrecondition
38
+ extend Gullah
39
+
40
+ rule :phrase, 'word+'
41
+
42
+ leaf :word, /\S+/, preconditions: [:not_foo]
43
+
44
+ def not_foo(_name, s, e, text, _children)
45
+ text[s...e] == 'foo' ? :fail : :pass
46
+ end
47
+ end
48
+
49
+ def test_good_words
50
+ parse = LeafPrecondition.first 'bar baz plugh'
51
+ assert_equal 'phrase[word,_ws,word,_ws,word]', parse.summary
52
+ end
53
+
54
+ def test_bad_first
55
+ parse = LeafPrecondition.first 'foo bar baz plugh'
56
+ assert_equal ';_ws;phrase[word,_ws,word,_ws,word]', parse.summary
57
+ end
58
+
59
+ def test_bad_middle
60
+ parse = LeafPrecondition.first 'bar foo baz plugh'
61
+ assert_equal 'phrase[word,_ws];;_ws;phrase[word,_ws,word]', parse.summary
62
+ end
63
+
64
+ def test_bad_end
65
+ parse = LeafPrecondition.first 'bar baz plugh foo'
66
+ assert_equal 'phrase[word,_ws,word,_ws,word,_ws];', parse.summary
67
+ end
68
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+
5
+ require 'gullah'
6
+ require 'byebug'
7
+
8
+ # :stopdoc:
9
+
10
+ # to verify that if subrules have different tests the tests only apply to the
11
+ # appropriate subrule
12
+ class TestsPerSubruleTest < Minitest::Test
13
+ class TestsPerLeaf
14
+ extend Gullah
15
+
16
+ rule :phrase, 'noun+'
17
+
18
+ leaf :noun, /\bfoo\b/
19
+ leaf :noun, /\bbar\b/, tests: [:preceding_foo]
20
+
21
+ def preceding_foo(node)
22
+ node.text_before =~ /\bfoo\s*\z/ ? :pass : :fail
23
+ end
24
+ end
25
+
26
+ def test_just_foos
27
+ parse = TestsPerLeaf.first 'foo foo foo'
28
+ # basically, we should get one good parse
29
+ assert_equal 'phrase[noun,_ws,noun,_ws,noun]', parse.summary
30
+ end
31
+
32
+ def test_just_bars
33
+ parse = TestsPerLeaf.first 'bar bar bar'
34
+ assert_equal 'noun;_ws;noun;_ws;noun', parse.summary
35
+ assert parse.roots.select(&:significant?).all?(&:error?), 'all leaves are errors'
36
+ end
37
+
38
+ def test_foo_bar
39
+ parse = TestsPerLeaf.first 'foo bar'
40
+ # again, one good parse
41
+ assert_equal 'phrase[noun,_ws,noun]', parse.summary
42
+ end
43
+
44
+ def test_foo_bar_bar
45
+ parse = TestsPerLeaf.first 'foo bar bar'
46
+ assert_equal 'phrase[noun,_ws,noun,_ws];noun', parse.summary
47
+ assert_equal 1, parse.roots.select(&:significant?).count(&:error?)
48
+ end
49
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+
5
+ require 'gullah'
6
+ require 'byebug'
7
+
8
+ # :stopdoc:
9
+
10
+ # test all the tree walking methods on node
11
+ class TreeWalkingTest < Minitest::Test
12
+ class Quaternary
13
+ extend Gullah
14
+
15
+ rule :b, 'a{4} | b{4}'
16
+
17
+ leaf :a, /\S+/
18
+ end
19
+
20
+ def test_tree_walking
21
+ parses = Quaternary.parse '1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16'
22
+ assert_equal 1, parses.length, 'only one optimal parse'
23
+ parse = parses.first
24
+ assert_equal 1, parse.roots.length, 'parse has a root node'
25
+ root = parse.roots.first
26
+ nine = root.leaves.find { |l| l.text == '9' }
27
+ assert !nine.nil?, 'found node number 9'
28
+ assert_equal root, nine.root
29
+ assert_equal 0, nine.sibling_index
30
+ assert_nil nine.prior_sibling
31
+ assert nine.first_child?
32
+ ls = nine.later_sibling
33
+ assert !ls.nil?
34
+ assert_equal ' ', ls.text
35
+ assert_equal [10, 11, 12], collect(nine.siblings).map(&:to_i)
36
+ assert_equal [10, 11, 12], collect(nine.later_siblings).map(&:to_i)
37
+ assert_equal (1..8).to_a, collect(nine.prior.select(&:leaf?)).map(&:to_i)
38
+ assert_equal (10..16).to_a, collect(nine.later.select(&:leaf?)).map(&:to_i)
39
+ assert_equal %i[b b], nine.prior.reject(&:leaf?).map(&:name)
40
+ assert_equal %i[b], nine.later.reject(&:leaf?).map(&:name)
41
+ assert_equal (9..12).to_a, collect(nine.parent.leaves).map(&:to_i)
42
+ assert_equal (1..16).to_a, collect(root.leaves).map(&:to_i)
43
+ ten = root.leaves.find { |l| l.text == '10' }
44
+ assert !ten.nil?, 'found node number 10'
45
+ assert !ten.first_child?
46
+ assert_equal 2, ten.sibling_index
47
+ assert_equal ' ', ten.prior_sibling.text
48
+ assert_equal nine, ten.prior_sibling.prior_sibling
49
+ assert_equal ' ', ten.later_sibling.text
50
+ assert_equal '11', ten.later_sibling.later_sibling.text
51
+ assert_equal [9, 11, 12], collect(ten.siblings).map(&:to_i)
52
+ assert_equal [11, 12], collect(ten.later_siblings).map(&:to_i)
53
+ assert_equal ten.parent, ten.ancestors.first
54
+ assert_equal root, ten.ancestors.last
55
+ assert_equal %i[b b], ten.ancestors.map(&:name)
56
+ assert root.subtree.include?(root)
57
+ assert !root.descendants.include?(root)
58
+ [nine, ten].each do |n|
59
+ assert root.subtree.include?(n)
60
+ assert root.descendants.include?(n)
61
+ assert n.ancestors.include?(root)
62
+ assert !n.siblings.include?(n)
63
+ end
64
+ last_node = nil
65
+ root.subtree.each do |n|
66
+ last_node = n
67
+ assert n.ancestors.include?(root) unless n == root
68
+ assert !n.ancestors.include?(n)
69
+ next if n.leaf?
70
+
71
+ first, *, last = n.children
72
+ assert first.first_child?
73
+ if last
74
+ assert last.last_child?
75
+ else
76
+ assert first.last_child?
77
+ end
78
+ end
79
+ assert_equal root.leaves.last, root.subtree.last
80
+ assert_equal last_node, root.subtree.last
81
+ end
82
+
83
+ private
84
+
85
+ def collect(nodes)
86
+ nodes.reject(&:ignorable?).map(&:text)
87
+ end
88
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gullah
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - David F. Houghton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-08-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: byebug
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 9.1.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 9.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ description: Gullah is a bottom-up parser generator than can handle errors, ambiguous
84
+ syntax, and arbitrary matching conditions.
85
+ email: dfhoughton@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - LICENSE
92
+ - README.md
93
+ - Rakefile
94
+ - TODO.md
95
+ - examples/hat.rb
96
+ - examples/trash.rb
97
+ - examples/xml.rb
98
+ - gullah.gemspec
99
+ - lib/gullah.rb
100
+ - lib/gullah/atom.rb
101
+ - lib/gullah/boundary.rb
102
+ - lib/gullah/dotifier.rb
103
+ - lib/gullah/error.rb
104
+ - lib/gullah/hopper.rb
105
+ - lib/gullah/iterator.rb
106
+ - lib/gullah/leaf.rb
107
+ - lib/gullah/node.rb
108
+ - lib/gullah/parse.rb
109
+ - lib/gullah/picker.rb
110
+ - lib/gullah/rule.rb
111
+ - lib/gullah/segment.rb
112
+ - lib/gullah/trash.rb
113
+ - lib/gullah/version.rb
114
+ - test/basic_test.rb
115
+ - test/big_tree_test.rb
116
+ - test/boundary_test.rb
117
+ - test/date_test.rb
118
+ - test/error_test.rb
119
+ - test/json_test.rb
120
+ - test/parse_demo_test.rb
121
+ - test/precondition_test.rb
122
+ - test/tests_per_subrule_test.rb
123
+ - test/tree_walking_test.rb
124
+ homepage: https://rubygems.org/gems/gullah
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '2.6'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.2.15
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: A bottom up parser generator
147
+ test_files:
148
+ - test/basic_test.rb
149
+ - test/big_tree_test.rb
150
+ - test/boundary_test.rb
151
+ - test/date_test.rb
152
+ - test/error_test.rb
153
+ - test/json_test.rb
154
+ - test/parse_demo_test.rb
155
+ - test/precondition_test.rb
156
+ - test/tests_per_subrule_test.rb
157
+ - test/tree_walking_test.rb