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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/LICENSE +21 -0
- data/README.md +87 -0
- data/Rakefile +11 -0
- data/TODO.md +2 -0
- data/examples/hat.rb +27 -0
- data/examples/trash.rb +42 -0
- data/examples/xml.rb +45 -0
- data/gullah.gemspec +31 -0
- data/lib/gullah/atom.rb +132 -0
- data/lib/gullah/boundary.rb +11 -0
- data/lib/gullah/dotifier.rb +127 -0
- data/lib/gullah/error.rb +7 -0
- data/lib/gullah/hopper.rb +142 -0
- data/lib/gullah/iterator.rb +67 -0
- data/lib/gullah/leaf.rb +24 -0
- data/lib/gullah/node.rb +553 -0
- data/lib/gullah/parse.rb +233 -0
- data/lib/gullah/picker.rb +56 -0
- data/lib/gullah/rule.rb +90 -0
- data/lib/gullah/segment.rb +92 -0
- data/lib/gullah/trash.rb +15 -0
- data/lib/gullah/version.rb +7 -0
- data/lib/gullah.rb +777 -0
- data/test/basic_test.rb +451 -0
- data/test/big_tree_test.rb +26 -0
- data/test/boundary_test.rb +29 -0
- data/test/date_test.rb +111 -0
- data/test/error_test.rb +245 -0
- data/test/json_test.rb +124 -0
- data/test/parse_demo_test.rb +33 -0
- data/test/precondition_test.rb +68 -0
- data/test/tests_per_subrule_test.rb +49 -0
- data/test/tree_walking_test.rb +88 -0
- metadata +157 -0
@@ -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
|