scripref 0.2.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.
- data/CHANGELOG +5 -0
- data/LICENSE +20 -0
- data/Rakefile +17 -0
- data/lib/scripref/const_reader.rb +46 -0
- data/lib/scripref/english.rb +59 -0
- data/lib/scripref/german.rb +56 -0
- data/lib/scripref/parser.rb +198 -0
- data/lib/scripref/processor.rb +60 -0
- data/lib/scripref.rb +17 -0
- data/test/test_english.rb +43 -0
- data/test/test_german.rb +40 -0
- data/test/test_parser.rb +166 -0
- data/test/test_processor.rb +41 -0
- metadata +66 -0
data/CHANGELOG
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010-2012 Jan Friedrich
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
20
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rim'
|
2
|
+
require 'rim/check_version'
|
3
|
+
require 'rim/gem'
|
4
|
+
require 'rim/git'
|
5
|
+
require 'rim/rimrc'
|
6
|
+
require 'rim/test'
|
7
|
+
|
8
|
+
$:.unshift File.dirname(__FILE__) + '/lib'
|
9
|
+
require 'scripref'
|
10
|
+
|
11
|
+
Rim.setup do
|
12
|
+
name 'scripref'
|
13
|
+
authors 'Jan Friedrich'
|
14
|
+
homepage 'http://gitorious.org/scripref'
|
15
|
+
version Scripref::VERSION
|
16
|
+
summary 'Library for parsing scripture references in real texts.'
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
|
3
|
+
# Mixin to generate instance methods to access of mixin constants.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# module M
|
7
|
+
# A = :a
|
8
|
+
# B = :b
|
9
|
+
# extend ConstReader
|
10
|
+
# const_reader constants
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# # Include in class
|
14
|
+
# class C
|
15
|
+
# include M
|
16
|
+
# end
|
17
|
+
# c = C.new
|
18
|
+
# c.a # => :a
|
19
|
+
# c.b # => :b
|
20
|
+
#
|
21
|
+
# # Extend an instance
|
22
|
+
# o = Object.new
|
23
|
+
# o.extend M
|
24
|
+
# o.a # => :a
|
25
|
+
# o.b # => :b
|
26
|
+
module ConstReader
|
27
|
+
|
28
|
+
# Define a getter method for one or more constants.
|
29
|
+
#
|
30
|
+
# Example:
|
31
|
+
# # all defined constants
|
32
|
+
# const_reader constants
|
33
|
+
#
|
34
|
+
# # constants A and B
|
35
|
+
# const_reader :A, :B
|
36
|
+
def const_reader *consts
|
37
|
+
consts.flatten.each do |c|
|
38
|
+
class_exec(c.to_s, c.to_s.downcase) do |c_name, m_name|
|
39
|
+
define_method m_name do
|
40
|
+
self.singleton_class.const_get c_name
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'scripref/const_reader'
|
3
|
+
|
4
|
+
module Scripref
|
5
|
+
|
6
|
+
# Mixin for parsing references in English.
|
7
|
+
module English
|
8
|
+
|
9
|
+
# Array of book names.
|
10
|
+
BOOK_NAMES = <<-END.strip.split(/,\s*/)
|
11
|
+
Genesis, Exodus, Leviticus, Numbers, Deuteronomy, Joshua, Judges,
|
12
|
+
Ruth, 1 Samuel, 2 Samuel, 1 Kings, 2 Kings, 1 Chronicles,
|
13
|
+
2 Chronicles, Ezra, Nehemiah, Esther, Job, Psalms, Proverbs,
|
14
|
+
Ecclesiastes, Song of Songs, Isaiah, Jeremiah, Lamentations,
|
15
|
+
Ezekiel, Daniel, Hosea, Joel, Amos, Obadiah, Jonah, Micah, Nahum,
|
16
|
+
Habakkuk, Zephaniah, Haggai, Zechariah, Malachi,
|
17
|
+
Matthew, Mark, Luke, John, Acts, Romans, 1 Corinthians,
|
18
|
+
2 Corinthians, Galatians, Ephesians, Philippians, Colossians,
|
19
|
+
1 Thessalonians, 2 Thessalonians, 1 Timothy, 2 Timothy, Titus,
|
20
|
+
Philemon, Hebrews, James, 1 Peter, 2 Peter, 1 John, 2 John, 3 John,
|
21
|
+
Jude, Revelation
|
22
|
+
END
|
23
|
+
|
24
|
+
# Array of regular expressions to match book names.
|
25
|
+
BOOKS_RES = BOOK_NAMES.map do |bn|
|
26
|
+
Regexp.new(bn.gsub(/([^1-3A-Z])/, '\1?').gsub('.', '\.') << '\b\s*')
|
27
|
+
end
|
28
|
+
|
29
|
+
# Regular expression to match a book.
|
30
|
+
BOOK_RE = Regexp.new(BOOKS_RES.map {|re| '(^' << re.to_s << ')' }.join('|'))
|
31
|
+
|
32
|
+
# Regular expression to match a separator between chapter and verse.
|
33
|
+
CV_SEP_RE = /:\s*/o
|
34
|
+
|
35
|
+
# Regular expression to match a hyphen.
|
36
|
+
HYPHEN_RE = /\s*-\s*/o
|
37
|
+
|
38
|
+
# Regular expression to match a separator between passages.
|
39
|
+
PASS_SEP_RE = /;\s*/o
|
40
|
+
|
41
|
+
# Regular expression to match a separator between verses.
|
42
|
+
VERSE_SEP_RE = /,\s*/o
|
43
|
+
|
44
|
+
# Regular expression to match addons for a verse.
|
45
|
+
VERSE_ADDON_RE = /([ab]|ff?)\s*/o
|
46
|
+
|
47
|
+
pass = '([1-3]\s*)?[A-Z][a-z]+\.?\s*(\d+\s*[,.\-]\s*)*\d+\s*'
|
48
|
+
|
49
|
+
# Regular expression to parse a reference
|
50
|
+
REFERENCE_RE = /#{pass}(;\s*#{pass})*/o
|
51
|
+
|
52
|
+
# Define instance methods for the mixin.
|
53
|
+
|
54
|
+
extend ConstReader
|
55
|
+
const_reader constants
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'scripref/const_reader'
|
3
|
+
|
4
|
+
module Scripref
|
5
|
+
|
6
|
+
# Mixin for parsing references in German.
|
7
|
+
module German
|
8
|
+
|
9
|
+
# Array of book names.
|
10
|
+
BOOK_NAMES = <<-END.strip.split(/,\s*/)
|
11
|
+
1. Mose, 2. Mose, 3. Mose, 4. Mose, 5. Mose, Josua, Richter, Ruth, 1. Samuel, 2. Samuel,
|
12
|
+
1. Könige, 2.Könige, 1. Chronika, 2. Chronika, Esra, Nehemia, Esther, Hiob, Psalm,
|
13
|
+
Sprüche, Prediger, Hohelied, Jesaja, Jeremia, Klagelieder, Hesekiel, Daniel, Hosea, Joel,
|
14
|
+
Amos, Obadja, Jona, Micha, Nahum, Habakuk, Zephanja, Haggai, Sacharja, Maleachi,
|
15
|
+
Matthäus, Markus, Lukas, Johannes, Apostelgeschichte, Römer, 1. Korinther, 2. Korinther,
|
16
|
+
Galater, Epheser, Philipper, Kolosser, 1. Thessalonicher, 2. Thessalonicher, 1. Timotheus,
|
17
|
+
2. Timotheus, Titus, Philemon, Hebräer, Jakobus, 1. Petrus, 2. Petrus, 1. Johannes,
|
18
|
+
2. Johannes, 3. Johannes, Judas, Offenbarung
|
19
|
+
END
|
20
|
+
|
21
|
+
# Array of regular expressions to match book names.
|
22
|
+
BOOKS_RES = BOOK_NAMES.map do |bn|
|
23
|
+
Regexp.new(bn.gsub(/([^1-5A-Z])/, '\1?').gsub('.', '\.') << '\b\s*')
|
24
|
+
end
|
25
|
+
|
26
|
+
# Regular expression to match a book.
|
27
|
+
BOOK_RE = Regexp.new(BOOKS_RES.map {|re| '(^' << re.to_s << ')' }.join('|'))
|
28
|
+
|
29
|
+
# Regular expression to match a separator between chapter and verse.
|
30
|
+
CV_SEP_RE = /,\s*/o
|
31
|
+
|
32
|
+
# Regular expression to match a hyphen.
|
33
|
+
HYPHEN_RE = /\s*-\s*/o
|
34
|
+
|
35
|
+
# Regular expression to match a separator between passages.
|
36
|
+
PASS_SEP_RE = /;\s*/o
|
37
|
+
|
38
|
+
# Regular expression to match a separator between verses.
|
39
|
+
VERSE_SEP_RE = /\.\s*/o
|
40
|
+
|
41
|
+
# Regular expression to match addons for a verse.
|
42
|
+
VERSE_ADDON_RE = /([ab]|ff?)\s*/o
|
43
|
+
|
44
|
+
pass = '([1-5]\.?\s*)?[A-Z][a-zäöü]+\.?\s*(\d+\s*[,.\-]\s*)*\d+\s*'
|
45
|
+
|
46
|
+
# Regular expression to parse a reference
|
47
|
+
REFERENCE_RE = /#{pass}(;\s*#{pass})*/o
|
48
|
+
|
49
|
+
# Define instance methods for the mixin.
|
50
|
+
|
51
|
+
extend ConstReader
|
52
|
+
const_reader constants
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'strscan'
|
3
|
+
|
4
|
+
module Scripref
|
5
|
+
|
6
|
+
class Parser < StringScanner
|
7
|
+
|
8
|
+
NUMBER_RE = /\d+\s*/
|
9
|
+
|
10
|
+
# @param mods on ore more modules to include
|
11
|
+
def initialize *mods
|
12
|
+
@mods = mods
|
13
|
+
mods.each do |m|
|
14
|
+
extend m
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Parsing a string of a scripture reference
|
19
|
+
# @param str string to parse
|
20
|
+
def parse str
|
21
|
+
self.string = str
|
22
|
+
@result = []
|
23
|
+
start
|
24
|
+
end
|
25
|
+
|
26
|
+
# start of parsing grammer
|
27
|
+
def start
|
28
|
+
@text = ''
|
29
|
+
b1 or []
|
30
|
+
end
|
31
|
+
|
32
|
+
# try to parse first book
|
33
|
+
def b1
|
34
|
+
s = scan(book_re) or return nil
|
35
|
+
@text << s
|
36
|
+
@b1 = @b2 = book2num(s)
|
37
|
+
@c1 = @v1 = 1
|
38
|
+
@c2 = @v2 = :max
|
39
|
+
|
40
|
+
epsilon or c1 or nil
|
41
|
+
end
|
42
|
+
|
43
|
+
# try parse first chapter
|
44
|
+
def c1
|
45
|
+
s = scan(NUMBER_RE) or return nil
|
46
|
+
@text << s
|
47
|
+
@c1 = @c2 = s.to_i
|
48
|
+
|
49
|
+
if cv_sep
|
50
|
+
v1 or nil
|
51
|
+
elsif hyphen
|
52
|
+
c2 or nil
|
53
|
+
elsif pass_sep
|
54
|
+
b1 or c1
|
55
|
+
else
|
56
|
+
epsilon or nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# try to parse first verse
|
61
|
+
def v1
|
62
|
+
s = scan(NUMBER_RE) or return nil
|
63
|
+
@text << s
|
64
|
+
@v1 = @v2 = s.to_i
|
65
|
+
|
66
|
+
if addon = verse_addon
|
67
|
+
case addon
|
68
|
+
when :f, :ff
|
69
|
+
@v2 = addon
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
if hyphen
|
74
|
+
if check(Regexp.new(NUMBER_RE.source + cv_sep_re.source))
|
75
|
+
c2
|
76
|
+
else
|
77
|
+
v2 or nil
|
78
|
+
end
|
79
|
+
elsif pass_sep
|
80
|
+
b1 or c1
|
81
|
+
elsif verse_sep
|
82
|
+
v1
|
83
|
+
else
|
84
|
+
epsilon or nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# try to parse second chapter
|
89
|
+
def c2
|
90
|
+
s = scan(NUMBER_RE) or return nil
|
91
|
+
@text << s
|
92
|
+
@c2 = s.to_i
|
93
|
+
|
94
|
+
if cv_sep
|
95
|
+
v2 or nil
|
96
|
+
else
|
97
|
+
epsilon or nil
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# try to parse second verse
|
102
|
+
def v2
|
103
|
+
s = scan(NUMBER_RE) or return nil
|
104
|
+
@text << s
|
105
|
+
@v2 = s.to_i
|
106
|
+
|
107
|
+
if verse_sep
|
108
|
+
v1
|
109
|
+
elsif pass_sep
|
110
|
+
b1 or c1
|
111
|
+
else
|
112
|
+
epsilon or nil
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# try to parse <tt>end of string</tt>
|
117
|
+
def epsilon
|
118
|
+
if eos?
|
119
|
+
push_passage
|
120
|
+
return @result
|
121
|
+
end
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
|
125
|
+
# try to parse separator or chapter and verse
|
126
|
+
def cv_sep
|
127
|
+
if s = scan(cv_sep_re)
|
128
|
+
@text << s
|
129
|
+
s
|
130
|
+
else
|
131
|
+
nil
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# try to parse hyphen
|
136
|
+
def hyphen
|
137
|
+
if s = scan(hyphen_re)
|
138
|
+
@text << s
|
139
|
+
s
|
140
|
+
else
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# try to parse separator between passages
|
146
|
+
def pass_sep
|
147
|
+
if s = scan(pass_sep_re)
|
148
|
+
push_passage
|
149
|
+
@result << s
|
150
|
+
s
|
151
|
+
else
|
152
|
+
nil
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# try to parse verse separator
|
157
|
+
def verse_sep
|
158
|
+
if s = scan(verse_sep_re)
|
159
|
+
push_passage
|
160
|
+
@result << s
|
161
|
+
s
|
162
|
+
else
|
163
|
+
nil
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# try to parse addons for verses
|
168
|
+
def verse_addon
|
169
|
+
if s = scan(verse_addon_re)
|
170
|
+
@text << s
|
171
|
+
s.to_sym
|
172
|
+
else
|
173
|
+
nil
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def push_passage
|
178
|
+
@result << Passage.new(@text, @b1, @c1, @v1, @b2, @c2, @v2)
|
179
|
+
@text = ''
|
180
|
+
end
|
181
|
+
|
182
|
+
def book2num str
|
183
|
+
return nil unless book_re =~str
|
184
|
+
books_res.each_with_index do |re, i|
|
185
|
+
if str =~ Regexp.new('^' << re.to_s << '$')
|
186
|
+
num = i + 1
|
187
|
+
return num
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def inspect
|
193
|
+
"#<#{self.class} #{@mods.inspect}>"
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'strscan'
|
3
|
+
require 'scripref/parser'
|
4
|
+
|
5
|
+
module Scripref
|
6
|
+
|
7
|
+
class Processor
|
8
|
+
|
9
|
+
include Enumerable
|
10
|
+
|
11
|
+
attr_accessor :text
|
12
|
+
|
13
|
+
# @param text text to parse
|
14
|
+
# @param mods on ore more modules to include in processor and parser
|
15
|
+
def initialize text=nil, *mods
|
16
|
+
@text = text
|
17
|
+
@mods = mods
|
18
|
+
mods.each do |m|
|
19
|
+
extend m
|
20
|
+
end
|
21
|
+
@parser = Parser.new(*mods)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Iterate over each parsed reference if block given, gets an iterator
|
25
|
+
# over each parsed reference otherwise.
|
26
|
+
def each_ref
|
27
|
+
if block_given?
|
28
|
+
scanner = StringScanner.new(text)
|
29
|
+
while scanner.scan_until(reference_re)
|
30
|
+
yield @parser.parse(scanner.matched)
|
31
|
+
end
|
32
|
+
self
|
33
|
+
else
|
34
|
+
enum_for :each_ref
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Iterate over each piece of <tt>str</tt> (text and parsed references)
|
39
|
+
# if block given, gets an iterator over the pieces otherwise.
|
40
|
+
def each
|
41
|
+
if block_given?
|
42
|
+
scanner = StringScanner.new(text)
|
43
|
+
while scanner.scan(/(.*?)(#{Regexp.new(reference_re.to_s)})/)
|
44
|
+
yield scanner[1]
|
45
|
+
yield @parser.parse(scanner[2])
|
46
|
+
end
|
47
|
+
yield scanner.rest if scanner.rest
|
48
|
+
self
|
49
|
+
else
|
50
|
+
enum_for :each
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def inspect
|
55
|
+
"#<#{self.class} #{@mods.inspect}>"
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/lib/scripref.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'scripref/parser'
|
3
|
+
require 'scripref/processor'
|
4
|
+
require 'scripref/english'
|
5
|
+
require 'scripref/german'
|
6
|
+
|
7
|
+
module Scripref
|
8
|
+
|
9
|
+
VERSION = '0.2.0'
|
10
|
+
|
11
|
+
Passage = Struct.new(:text, :b1, :c1, :v1, :b2, :c2, :v2)
|
12
|
+
|
13
|
+
class Passage
|
14
|
+
alias to_s text
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'test/unit'
|
3
|
+
require 'scripref/english'
|
4
|
+
|
5
|
+
class TestEnglish < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include Scripref::English
|
8
|
+
|
9
|
+
def test_book_re
|
10
|
+
assert_match 'Genesis', book_re
|
11
|
+
assert_match 'Exodus', book_re
|
12
|
+
assert_match 'Matthew', book_re
|
13
|
+
assert_match '2 Timothy', book_re
|
14
|
+
assert_not_match '2 2 Timothy', book_re
|
15
|
+
assert_match 'Revelation', book_re
|
16
|
+
assert_not_match 'something', book_re
|
17
|
+
assert_match 'Gen', book_re
|
18
|
+
assert_match 'Ex', book_re
|
19
|
+
assert_match 'Mat', book_re
|
20
|
+
assert_match '2 Tim', book_re
|
21
|
+
assert_match 'Rev', book_re
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_book2num
|
25
|
+
assert_book_num 1, 'Genesis'
|
26
|
+
assert_book_num 40, 'Matthew'
|
27
|
+
assert_book_num 66, 'Revelation'
|
28
|
+
assert_book_num 1, 'Gen'
|
29
|
+
assert_book_num 1, 'Ge'
|
30
|
+
assert_book_num 1, 'G'
|
31
|
+
assert_book_num 55, '2 Tim'
|
32
|
+
assert_book_num 55, '2Tim'
|
33
|
+
assert_book_num 55, '2Tm'
|
34
|
+
assert_book_num 40, 'Mat'
|
35
|
+
assert_book_num 66, 'Rev'
|
36
|
+
end
|
37
|
+
|
38
|
+
def assert_book_num num, str
|
39
|
+
@parser ||= Scripref::Parser.new(Scripref::English)
|
40
|
+
assert_equal num, @parser.parse(str).first.b1
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/test/test_german.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'test/unit'
|
3
|
+
require 'scripref/german'
|
4
|
+
|
5
|
+
class TestGerman < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include Scripref::German
|
8
|
+
|
9
|
+
def test_book_re
|
10
|
+
assert_match '1. Mose', book_re
|
11
|
+
assert_match '2. Mose', book_re
|
12
|
+
assert_match 'Matthäus', book_re
|
13
|
+
assert_match '2. Timotheus', book_re
|
14
|
+
assert_not_match '2. 2. Timotheus', book_re
|
15
|
+
assert_match 'Offenbarung', book_re
|
16
|
+
assert_not_match 'something', book_re
|
17
|
+
assert_match '1. Mo', book_re
|
18
|
+
assert_match '2.Mo', book_re
|
19
|
+
assert_match 'Mat', book_re
|
20
|
+
assert_match '2. Tim', book_re
|
21
|
+
assert_match 'Off', book_re
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_book2num
|
25
|
+
assert_book_num 1, '1. Mose'
|
26
|
+
assert_book_num 40, 'Matthäus'
|
27
|
+
assert_book_num 66, 'Offenbarung'
|
28
|
+
assert_book_num 1, '1. Mo'
|
29
|
+
assert_book_num 1, '1.Mo'
|
30
|
+
assert_book_num 1, '1M'
|
31
|
+
assert_book_num 40, 'Mat'
|
32
|
+
assert_book_num 66, 'Off'
|
33
|
+
end
|
34
|
+
|
35
|
+
def assert_book_num num, str
|
36
|
+
@parser ||= Scripref::Parser.new(Scripref::German)
|
37
|
+
assert_equal num, @parser.parse(str).first.b1
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/test/test_parser.rb
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'test/unit'
|
3
|
+
require 'scripref'
|
4
|
+
|
5
|
+
class TestParser < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@parser = Scripref::Parser.new(Scripref::German)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_only_book
|
12
|
+
text = 'Ruth'
|
13
|
+
assert_parsed_ast_for_text [pass(text, 8, 1, 1, 8, :max, :max)], text
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_book_and_chapter
|
17
|
+
text = 'Ruth 2'
|
18
|
+
assert_parsed_ast_for_text [pass(text, 8, 2, 1, 8, 2, :max)], text
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_book_chapter_and_verse
|
22
|
+
text = 'Ruth 2,5'
|
23
|
+
assert_parsed_ast_for_text [pass(text, 8, 2, 5, 8, 2, 5)], text
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_verse_range
|
27
|
+
text = 'Ruth 2,5-11'
|
28
|
+
assert_parsed_ast_for_text [pass(text, 8, 2, 5, 8, 2, 11)], text
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_chapter_verse_range
|
32
|
+
text = 'Ruth 2,5-3,7'
|
33
|
+
assert_parsed_ast_for_text [pass(text, 8, 2, 5, 8, 3, 7)], text
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_chapter_range
|
37
|
+
text = 'Ruth 2-3'
|
38
|
+
assert_parsed_ast_for_text [pass(text, 8, 2, 1, 8, 3, :max)], text
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_one_following_verse
|
42
|
+
text = 'Ruth 2,5f'
|
43
|
+
assert_parsed_ast_for_text [pass(text, 8, 2, 5, 8, 2, :f)], text
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_more_following_verse
|
47
|
+
text = 'Ruth 2,5ff'
|
48
|
+
assert_parsed_ast_for_text [pass(text, 8, 2, 5, 8, 2, :ff)], text
|
49
|
+
end
|
50
|
+
|
51
|
+
######################################################################
|
52
|
+
# more than one reference
|
53
|
+
######################################################################
|
54
|
+
|
55
|
+
def test_two_complete_refs
|
56
|
+
text = 'Ruth 2,1; Markus 4,8'
|
57
|
+
t1, t2 = text.split('; ')
|
58
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, 1), '; ', pass(t2, 41, 4, 8, 41, 4, 8)], text
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_two_refs_same_book
|
62
|
+
text = 'Ruth 2,1; 5,4'
|
63
|
+
t1, t2 = text.split('; ')
|
64
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, 1), '; ', pass(t2, 8, 5, 4, 8, 5, 4)], text
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_two_chapters_same_book
|
68
|
+
text = 'Ruth 2; 5'
|
69
|
+
t1, t2 = text.split('; ')
|
70
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, :max), '; ', pass(t2, 8, 5, 1, 8, 5, :max)], text
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_two_chapters_different_book
|
74
|
+
text = 'Ruth 2; Markus 4'
|
75
|
+
t1, t2 = text.split('; ')
|
76
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, :max), '; ', pass(t2, 41, 4, 1, 41, 4, :max)], text
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_two_verses
|
80
|
+
text = 'Ruth 2,5.11'
|
81
|
+
t1, t2 = text.split('.')
|
82
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 5, 8, 2, 5), '.', pass(t2, 8, 2, 11, 8, 2, 11)], text
|
83
|
+
end
|
84
|
+
|
85
|
+
######################################################################
|
86
|
+
# mixed variants of more than one reference
|
87
|
+
######################################################################
|
88
|
+
|
89
|
+
def test_verse_range_and_separated_verse
|
90
|
+
text = 'Ruth 2,1-3.11'
|
91
|
+
t1, t2 = text.split('.')
|
92
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, 3), '.', pass(t2, 8, 2, 11, 8, 2, 11)], text
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_separate_verse_and_verse_range
|
96
|
+
text = 'Ruth 2,1.3-11'
|
97
|
+
t1, t2 = text.split('.')
|
98
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, 1), '.', pass(t2, 8, 2, 3, 8, 2, 11)], text
|
99
|
+
end
|
100
|
+
|
101
|
+
def test_two_verse_ranges
|
102
|
+
text = 'Ruth 2,1-3.7-11'
|
103
|
+
t1, t2 = text.split('.')
|
104
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, 3), '.', pass(t2, 8, 2, 7, 8, 2, 11)], text
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_two_verse_range_different_books
|
108
|
+
text = 'Ruth 2,1-11; Markus 4,3-7'
|
109
|
+
t1, t2 = text.split('; ')
|
110
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, 11), '; ', pass(t2, 41, 4, 3,41, 4, 7)], text
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_two_verse_range_different_chapters
|
114
|
+
text = 'Ruth 2,1-11; 3,10-19'
|
115
|
+
t1, t2 = text.split('; ')
|
116
|
+
assert_parsed_ast_for_text [pass(t1, 8, 2, 1, 8, 2, 11), '; ', pass(t2, 8, 3, 10, 8, 3, 19)], text
|
117
|
+
end
|
118
|
+
|
119
|
+
######################################################################
|
120
|
+
# complex variants of references
|
121
|
+
######################################################################
|
122
|
+
|
123
|
+
def test_complex_example
|
124
|
+
text = 'Ruth 2,1-11.15; 3,7.9-12; Markus 4; 5,3.18-21'
|
125
|
+
t1, t2, t3, t4, t5, t6, t7 = text.split(/; |\./)
|
126
|
+
ast = [
|
127
|
+
pass(t1, 8, 2, 1, 8, 2, 11), '.',
|
128
|
+
pass(t2, 8, 2, 15, 8, 2, 15), '; ',
|
129
|
+
pass(t3, 8, 3, 7, 8, 3, 7), '.',
|
130
|
+
pass(t4, 8, 3, 9, 8, 3, 12), '; ',
|
131
|
+
pass(t5, 41, 4, 1, 41, 4, :max), '; ',
|
132
|
+
pass(t6, 41, 5, 3, 41, 5, 3), '.',
|
133
|
+
pass(t7, 41, 5, 18, 41, 5, 21)
|
134
|
+
]
|
135
|
+
assert_parsed_ast_for_text ast, text
|
136
|
+
end
|
137
|
+
|
138
|
+
protected
|
139
|
+
|
140
|
+
def pass *args
|
141
|
+
Scripref::Passage.new(*args)
|
142
|
+
end
|
143
|
+
|
144
|
+
def assert_equal_passage expected, actual
|
145
|
+
assert_equal expected.text, actual.text, 'Parsed text'
|
146
|
+
assert_equal expected.b1, actual.b1, 'First book'
|
147
|
+
assert_equal expected.c1, actual.c1, 'First chapter'
|
148
|
+
assert_equal expected.v1, actual.v1, 'First verse'
|
149
|
+
assert_equal expected.b2, actual.b2, 'Second book'
|
150
|
+
assert_equal expected.c2, actual.c2, 'Second chapter'
|
151
|
+
assert_equal expected.v2, actual.v2, 'Second verse'
|
152
|
+
end
|
153
|
+
|
154
|
+
def assert_parsed_ast_for_text expected_ast, text
|
155
|
+
res = @parser.parse(text)
|
156
|
+
assert_equal expected_ast.size, res.size, 'Array size of AST'
|
157
|
+
expected_ast.zip(res) do |expected_elem, actual_elem|
|
158
|
+
if !expected_elem.kind_of?(String)
|
159
|
+
assert_equal_passage expected_elem, actual_elem
|
160
|
+
else
|
161
|
+
assert_equal expected_elem, actual_elem
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# - encoding: utf-8 -
|
2
|
+
require 'test/unit'
|
3
|
+
require 'scripref'
|
4
|
+
|
5
|
+
class TestProcessor < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@text = 'Some text Mt 1,1 and Mr 2 and so on ...'
|
9
|
+
@mt = [Scripref::Passage.new('Mt 1,1 ', 40, 1, 1, 40, 1, 1)]
|
10
|
+
@mr = [Scripref::Passage.new('Mr 2 ', 41, 2, 1, 41, 2, :max)]
|
11
|
+
@processor = Scripref::Processor.new(@text, Scripref::German)
|
12
|
+
@chunks = ['Some text ', @mt, 'and ', @mr, 'and so on ...']
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_each_with_block
|
16
|
+
@processor.each do |chunk|
|
17
|
+
assert_equal @chunks.shift, chunk
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_each_without_block
|
22
|
+
enum = @processor.each
|
23
|
+
assert_kind_of Enumerator, enum
|
24
|
+
assert_equal @chunks, enum.to_a
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_each_ref_with_block
|
28
|
+
refs = @chunks.select {|c| c.kind_of? Array}
|
29
|
+
@processor.each_ref do |ref|
|
30
|
+
assert_equal refs.shift, ref
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_each_ref_without_block
|
35
|
+
enum = @processor.each_ref
|
36
|
+
refs = @chunks.select {|c| c.kind_of? Array}
|
37
|
+
assert_kind_of Enumerator, enum
|
38
|
+
assert_equal refs, enum.to_a
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scripref
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.2.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jan Friedrich
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-03-28 00:00:00 Z
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: ""
|
17
|
+
email:
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- CHANGELOG
|
26
|
+
- LICENSE
|
27
|
+
- Rakefile
|
28
|
+
- lib/scripref/const_reader.rb
|
29
|
+
- lib/scripref/english.rb
|
30
|
+
- lib/scripref/german.rb
|
31
|
+
- lib/scripref/parser.rb
|
32
|
+
- lib/scripref/processor.rb
|
33
|
+
- lib/scripref.rb
|
34
|
+
- test/test_english.rb
|
35
|
+
- test/test_german.rb
|
36
|
+
- test/test_parser.rb
|
37
|
+
- test/test_processor.rb
|
38
|
+
homepage: http://gitorious.org/scripref
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.8.19
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Library for parsing scripture references in real texts.
|
65
|
+
test_files: []
|
66
|
+
|