gullah 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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