lingo 1.8.0 → 1.8.1

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.
Files changed (100) hide show
  1. data/ChangeLog +13 -0
  2. data/README +49 -29
  3. data/Rakefile +28 -4
  4. data/TODO +2 -9
  5. data/bin/lingo +24 -0
  6. data/bin/lingoctl +24 -0
  7. data/de/lingo-dic.txt +559 -74
  8. data/info/gpl-hdr.txt +21 -24
  9. data/lib/lingo.rb +83 -112
  10. data/lib/lingo/agenda_item.rb +53 -0
  11. data/lib/lingo/attendee.rb +261 -0
  12. data/lib/lingo/attendee/abbreviator.rb +95 -97
  13. data/lib/lingo/attendee/debugger.rb +94 -93
  14. data/lib/lingo/attendee/decomposer.rb +76 -83
  15. data/lib/lingo/attendee/dehyphenizer.rb +141 -144
  16. data/lib/lingo/attendee/formatter.rb +65 -0
  17. data/lib/lingo/attendee/multi_worder.rb +302 -0
  18. data/lib/lingo/attendee/noneword_filter.rb +89 -84
  19. data/lib/lingo/attendee/object_filter.rb +91 -0
  20. data/lib/lingo/attendee/sequencer.rb +159 -158
  21. data/lib/lingo/attendee/synonymer.rb +81 -84
  22. data/lib/lingo/attendee/text_reader.rb +242 -0
  23. data/lib/lingo/attendee/text_writer.rb +169 -0
  24. data/lib/lingo/attendee/tokenizer.rb +192 -191
  25. data/lib/lingo/attendee/variator.rb +152 -156
  26. data/lib/lingo/attendee/vector_filter.rb +140 -135
  27. data/lib/lingo/attendee/word_searcher.rb +98 -0
  28. data/lib/lingo/buffered_attendee.rb +69 -0
  29. data/lib/lingo/cachable.rb +58 -0
  30. data/lib/lingo/call.rb +72 -0
  31. data/lib/lingo/cli.rb +26 -0
  32. data/lib/lingo/config.rb +23 -26
  33. data/lib/lingo/core_ext.rb +42 -0
  34. data/lib/lingo/ctl.rb +239 -173
  35. data/lib/lingo/database.rb +148 -496
  36. data/lib/lingo/database/crypter.rb +85 -0
  37. data/lib/lingo/database/gdbm_store.rb +49 -0
  38. data/lib/lingo/database/hash_store.rb +67 -0
  39. data/lib/lingo/database/libcdb_store.rb +58 -0
  40. data/lib/lingo/database/sdbm_store.rb +64 -0
  41. data/lib/lingo/database/show_progress.rb +81 -0
  42. data/lib/lingo/database/source.rb +134 -0
  43. data/lib/lingo/database/source/key_value.rb +62 -0
  44. data/lib/lingo/database/source/multi_key.rb +65 -0
  45. data/lib/lingo/database/source/multi_value.rb +65 -0
  46. data/lib/lingo/database/source/single_word.rb +60 -0
  47. data/lib/lingo/database/source/word_class.rb +64 -0
  48. data/lib/lingo/error.rb +122 -0
  49. data/lib/lingo/language.rb +78 -518
  50. data/lib/lingo/language/dictionary.rb +173 -0
  51. data/lib/lingo/language/grammar.rb +211 -0
  52. data/lib/lingo/language/lexical.rb +66 -0
  53. data/lib/lingo/language/lexical_hash.rb +88 -0
  54. data/lib/lingo/language/token.rb +48 -0
  55. data/lib/lingo/language/word.rb +130 -0
  56. data/lib/lingo/language/word_form.rb +83 -0
  57. data/lib/lingo/reportable.rb +59 -0
  58. data/lib/lingo/version.rb +1 -1
  59. data/lingo-all.cfg +14 -10
  60. data/lingo-call.cfg +5 -5
  61. data/lingo.cfg +14 -12
  62. data/lingo.rb +26 -0
  63. data/lir.cfg +13 -9
  64. data/spec/spec_helper.rb +1 -0
  65. data/test.cfg +11 -11
  66. data/test/attendee/ts_abbreviator.rb +0 -6
  67. data/test/attendee/ts_decomposer.rb +0 -6
  68. data/test/attendee/{ts_multiworder.rb → ts_multi_worder.rb} +1 -7
  69. data/test/attendee/ts_noneword_filter.rb +1 -7
  70. data/test/attendee/{ts_objectfilter.rb → ts_object_filter.rb} +1 -7
  71. data/test/attendee/ts_sequencer.rb +0 -6
  72. data/test/attendee/ts_synonymer.rb +0 -6
  73. data/test/attendee/{ts_textreader.rb → ts_text_reader.rb} +1 -7
  74. data/test/attendee/{ts_textwriter.rb → ts_text_writer.rb} +1 -7
  75. data/test/attendee/ts_tokenizer.rb +0 -6
  76. data/test/attendee/ts_variator.rb +0 -6
  77. data/test/attendee/ts_vector_filter.rb +1 -7
  78. data/test/attendee/{ts_wordsearcher.rb → ts_word_searcher.rb} +1 -7
  79. data/test/ref/artikel.non +2 -29
  80. data/test/ref/artikel.seq +13 -8
  81. data/test/ref/artikel.vec +30 -15
  82. data/test/ref/artikel.ven +29 -14
  83. data/test/ref/artikel.ver +58 -43
  84. data/test/ref/lir.csv +146 -145
  85. data/test/ref/lir.non +186 -210
  86. data/test/ref/lir.seq +54 -50
  87. data/test/test_helper.rb +41 -36
  88. data/test/ts_database.rb +12 -11
  89. data/test/ts_language.rb +118 -68
  90. metadata +67 -29
  91. data/lib/lingo/attendee/multiworder.rb +0 -301
  92. data/lib/lingo/attendee/objectfilter.rb +0 -86
  93. data/lib/lingo/attendee/textreader.rb +0 -237
  94. data/lib/lingo/attendee/textwriter.rb +0 -196
  95. data/lib/lingo/attendee/wordsearcher.rb +0 -96
  96. data/lib/lingo/attendees.rb +0 -289
  97. data/lib/lingo/const.rb +0 -131
  98. data/lib/lingo/modules.rb +0 -98
  99. data/lib/lingo/types.rb +0 -285
  100. data/lib/lingo/utilities.rb +0 -40
@@ -1,216 +1,217 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # LINGO ist ein Indexierungssystem mit Grundformreduktion, Kompositumzerlegung,
5
- # Mehrworterkennung und Relationierung.
6
- #
7
- # Copyright (C) 2005-2007 John Vorhauer
8
- # Copyright (C) 2007-2011 John Vorhauer, Jens Wille
9
- #
10
- # This program is free software; you can redistribute it and/or modify it under
11
- # the terms of the GNU Affero General Public License as published by the Free
12
- # Software Foundation; either version 3 of the License, or (at your option)
13
- # any later version.
14
- #
15
- # This program is distributed in the hope that it will be useful, but WITHOUT
16
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
- # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18
- # details.
19
- #
20
- # You should have received a copy of the GNU Affero General Public License along
21
- # with this program; if not, write to the Free Software Foundation, Inc.,
22
- # 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
23
- #
24
- # For more information visit http://www.lex-lingo.de or contact me at
25
- # welcomeATlex-lingoDOTde near 50°55'N+6°55'E.
26
- #
27
- # Lex Lingo rules from here on
4
+ ###############################################################################
5
+ # #
6
+ # Lingo -- A full-featured automatic indexing system #
7
+ # #
8
+ # Copyright (C) 2005-2007 John Vorhauer #
9
+ # Copyright (C) 2007-2012 John Vorhauer, Jens Wille #
10
+ # #
11
+ # Lingo is free software; you can redistribute it and/or modify it under the #
12
+ # terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # Lingo is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with Lingo. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
28
25
  #++
29
26
 
30
27
  class Lingo
31
28
 
32
- # Der Tokenizer zerlegt eine Textzeile in einzelne Token. Dies ist notwendig,
33
- # damit nachfolgende Attendees die Textdatei häppchenweise verarbeiten können.
34
- #
35
- # === Mögliche Verlinkung
36
- # Erwartet:: Daten des Typs *String* (Textzeilen) z.B. von Textreader
37
- # Erzeugt:: Daten des Typs *Token* z.B. für Abbreviator, Wordsearcher
38
- #
39
- # === Parameter
40
- # Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
41
- # Alle anderen Parameter müssen zwingend angegeben werden.
42
- # <b>in</b>:: siehe allgemeine Beschreibung des Attendee.
43
- # <b>out</b>:: siehe allgemeine Beschreibung des Attendee
44
- #
45
- # === Konfiguration
46
- # Der Tokenizer benötigt zur Identifikation einzelner Token Regeln, nach denen er
47
- # arbeiten soll. Die benötigten Regeln werden aufgrund des Umfangs nicht als Parameter,
48
- # sondern in der Sprachkonfiguration hinterlegt, die sich standardmäßig in der Datei
49
- # <tt>de.lang</tt> befindet (YAML-Format).
50
- # language:
51
- # attendees:
52
- # tokenizer:
53
- # regulars:
54
- # - _CHR_: '\wÄÖÜÁÂÀÉÊÈÍÎÌÓÔÒÚÛÙÝäöüáâàéêèíîìóôòúûùý'
55
- # - NUMS: '[+-]?(\d{4,}|\d{1,3}(\.\d{3,3})*)(\.|(,\d+)?%?)'
56
- # - URLS: '((mailto:|(news|http|https|ftp|ftps)://)\S+|^(www(\.\S+)+)|\S+([\._]\S+)+@\S+(\.\S+)+)'
57
- # - ABRV: '(([_CHR_]+\.)+)[_CHR_]+'
58
- # - ABRS: '(([_CHR_]{1,1}\.)+)(?!\.\.)'
59
- # - WORD: '[_CHR_\d]+'
60
- # - PUNC: '[!,\.:;?]'
61
- # - OTHR: '[—„!\"#$%&()*\+,\-\./:;<=>?@\[\\\]^_`{|}~´]'
62
- # - HELP: '.*'
63
- # Die Regeln werden in der angegebenen Reihenfolge abgearbeitet, solange bis ein Token
64
- # erkannt wurde. Sollte keine Regel zutreffen, so greift die letzt Regel +HELP+ in jedem
65
- # Fall.
66
- # Regeln, deren Name in Unterstriche eingefasst sind, werden als Makro interpretiert.
67
- # Makros werden genutzt, um lange oder sich wiederholende Bestandteile von Regeln
68
- # einmalig zu definieren und in den Regeln über den Makronamen eine Auflösung zu forcieren.
69
- # Makros werden selber nicht für die Erkennung von Token eingesetzt.
70
- #
71
- # === Generierte Kommandos
72
- # Damit der nachfolgende Datenstrom einwandfrei verarbeitet werden kann, generiert der Tokenizer
73
- # Kommandos, die mit in den Datenstrom eingefügt werden.
74
- # <b>*EOL(<dateiname>)</b>:: Kennzeichnet das Ende einer Textzeile, da die Information ansonsten
75
- # für nachfolgende Attendees verloren wäre.
76
- #
77
- # === Beispiele
78
- # Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration <tt>t1.cfg</tt>
79
- # meeting:
80
- # attendees:
81
- # - textreader: { out: lines, files: '$(files)' }
82
- # - tokenizer: { in: lines, out: token }
83
- # - debugger: { in: token, prompt: 'out>' }
84
- # ergibt die Ausgabe über den Debugger: <tt>lingo -c t1 test.txt</tt>
85
- # out> *FILE('test.txt')
86
- # out> :Dies/WORD:
87
- # out> :ist/WORD:
88
- # out> :eine/WORD:
89
- # out> :Zeile/WORD:
90
- # out> :./PUNC:
91
- # out> *EOL('test.txt')
92
- # out> :Dies/WORD:
93
- # out> :ist/WORD:
94
- # out> :noch/WORD:
95
- # out> :eine/WORD:
96
- # out> :./PUNC:
97
- # out> *EOL('test.txt')
98
- # out> *EOF('test.txt')
99
-
100
- class Attendee::Tokenizer < Attendee
101
-
102
- protected
103
-
104
- def init
105
- # Regular Expressions für Token-Erkennung einlesen
106
- regulars = get_key('regulars', '')
107
- forward(STR_CMD_ERR, 'regulars nicht definiert') unless regulars
108
-
109
- @space = get_key('space', false)
110
- @tags = get_key('tags', true)
111
- @wiki = get_key('wiki', true)
112
-
113
- # default rules
114
- @rules = [['SPAC', /^\s+/]]
115
- @rules << ['HTML', /^<[^>]+>/] unless @tags
116
- @rules << ['WIKI', /^\[\[.+?\]\]/] unless @wiki
117
- @rules.unshift(['WIKI', /^=+.+=+$/]) unless @wiki
118
-
119
- # Mit _xxx_ gekennzeichnete Makros anwenden und Expressions ergänzen und umwandeln
120
- macros = {}
121
-
122
- regulars.each { |rule|
123
- name = rule.keys[0]
124
- expr = rule.values[0].gsub(/_(\w+?)_/) {
125
- macros[$&] || begin
126
- Lingo.const_get("UTF_8_#{$1.upcase}")
127
- rescue NameError
29
+ class Attendee
30
+
31
+ # Der Tokenizer zerlegt eine Textzeile in einzelne Token. Dies ist notwendig,
32
+ # damit nachfolgende Attendees die Textdatei häppchenweise verarbeiten können.
33
+ #
34
+ # === Mögliche Verlinkung
35
+ # Erwartet:: Daten des Typs *String* (Textzeilen) z.B. von TextReader
36
+ # Erzeugt:: Daten des Typs *Token* z.B. für Abbreviator, Wordsearcher
37
+ #
38
+ # === Parameter
39
+ # Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
40
+ # Alle anderen Parameter müssen zwingend angegeben werden.
41
+ # <b>in</b>:: siehe allgemeine Beschreibung des Attendee.
42
+ # <b>out</b>:: siehe allgemeine Beschreibung des Attendee
43
+ #
44
+ # === Konfiguration
45
+ # Der Tokenizer benötigt zur Identifikation einzelner Token Regeln, nach denen er
46
+ # arbeiten soll. Die benötigten Regeln werden aufgrund des Umfangs nicht als Parameter,
47
+ # sondern in der Sprachkonfiguration hinterlegt, die sich standardmäßig in der Datei
48
+ # <tt>de.lang</tt> befindet (YAML-Format).
49
+ # language:
50
+ # attendees:
51
+ # tokenizer:
52
+ # regulars:
53
+ # - _CHR_: '\wÄÖÜÁÂÀÉÊÈÍÎÌÓÔÒÚÛÙÝäöüáâàéêèíîìóôòúûùý'
54
+ # - NUMS: '[+-]?(\d{4,}|\d{1,3}(\.\d{3,3})*)(\.|(,\d+)?%?)'
55
+ # - URLS: '((mailto:|(news|http|https|ftp|ftps)://)\S+|^(www(\.\S+)+)|\S+([\._]\S+)+@\S+(\.\S+)+)'
56
+ # - ABRV: '(([_CHR_]+\.)+)[_CHR_]+'
57
+ # - ABRS: '(([_CHR_]{1,1}\.)+)(?!\.\.)'
58
+ # - WORD: '[_CHR_\d]+'
59
+ # - PUNC: '[!,\.:;?]'
60
+ # - OTHR: '[—„!\"#$%&()*\+,\-\./:;<=>?@\[\\\]^_`{|}~´]'
61
+ # - HELP: '.*'
62
+ # Die Regeln werden in der angegebenen Reihenfolge abgearbeitet, solange bis ein Token
63
+ # erkannt wurde. Sollte keine Regel zutreffen, so greift die letzt Regel +HELP+ in jedem
64
+ # Fall.
65
+ # Regeln, deren Name in Unterstriche eingefasst sind, werden als Makro interpretiert.
66
+ # Makros werden genutzt, um lange oder sich wiederholende Bestandteile von Regeln
67
+ # einmalig zu definieren und in den Regeln über den Makronamen eine Auflösung zu forcieren.
68
+ # Makros werden selber nicht für die Erkennung von Token eingesetzt.
69
+ #
70
+ # === Generierte Kommandos
71
+ # Damit der nachfolgende Datenstrom einwandfrei verarbeitet werden kann, generiert der Tokenizer
72
+ # Kommandos, die mit in den Datenstrom eingefügt werden.
73
+ # <b>*EOL(<dateiname>)</b>:: Kennzeichnet das Ende einer Textzeile, da die Information ansonsten
74
+ # für nachfolgende Attendees verloren wäre.
75
+ #
76
+ # === Beispiele
77
+ # Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration <tt>t1.cfg</tt>
78
+ # meeting:
79
+ # attendees:
80
+ # - text_reader: { out: lines, files: '$(files)' }
81
+ # - tokenizer: { in: lines, out: token }
82
+ # - debugger: { in: token, prompt: 'out>' }
83
+ # ergibt die Ausgabe über den Debugger: <tt>lingo -c t1 test.txt</tt>
84
+ # out> *FILE('test.txt')
85
+ # out> :Dies/WORD:
86
+ # out> :ist/WORD:
87
+ # out> :eine/WORD:
88
+ # out> :Zeile/WORD:
89
+ # out> :./PUNC:
90
+ # out> *EOL('test.txt')
91
+ # out> :Dies/WORD:
92
+ # out> :ist/WORD:
93
+ # out> :noch/WORD:
94
+ # out> :eine/WORD:
95
+ # out> :./PUNC:
96
+ # out> *EOL('test.txt')
97
+ # out> *EOF('test.txt')
98
+
99
+ class Tokenizer < self
100
+
101
+ protected
102
+
103
+ def init
104
+ # Regular Expressions für Token-Erkennung einlesen
105
+ regulars = get_key('regulars', '')
106
+ raise NoConfigKeyError.new(:regulars) unless regulars
107
+
108
+ @space = get_key('space', false)
109
+ @tags = get_key('tags', true)
110
+ @wiki = get_key('wiki', true)
111
+
112
+ # default rules
113
+ @rules = [['SPAC', /^\s+/]]
114
+ @rules << ['HTML', /^<[^>]+>/] unless @tags
115
+ @rules << ['WIKI', /^\[\[.+?\]\]/] unless @wiki
116
+ @rules.unshift(['WIKI', /^=+.+=+$/]) unless @wiki
117
+
118
+ # Mit _xxx_ gekennzeichnete Makros anwenden und Expressions ergänzen und umwandeln
119
+ macros = {}
120
+
121
+ regulars.each { |rule|
122
+ name = rule.keys[0]
123
+ expr = rule.values[0].gsub(/_(\w+?)_/) {
124
+ macros[$&] || begin
125
+ Database::Source.const_get("UTF8_#{$1.upcase}")
126
+ rescue NameError
127
+ end
128
+ }
129
+
130
+ if name =~ /^_\w+_$/ # is a macro
131
+ macros[name] = expr if name =~ /^_\w+_$/
132
+ else
133
+ @rules << [name, Regexp.new('^'+expr)]
128
134
  end
129
135
  }
130
136
 
131
- if name =~ /^_\w+_$/ # is a macro
132
- macros[name] = expr if name =~ /^_\w+_$/
133
- else
134
- @rules << [name, Regexp.new('^'+expr)]
135
- end
136
- }
137
-
138
- # Der Tokenizer gibt jedes Zeilenende als Information weiter, sofern es sich
139
- # nicht um die Verarbeitung einer LIR-Datei handelt. Im Falle einer normalen Datei
140
- # wird der Dateiname gespeichert und als Kennzeichen für die Erzeugung von
141
- # Zeilenende-Nachrichten herangezogen.
142
- @filename = nil
143
- end
137
+ # Der Tokenizer gibt jedes Zeilenende als Information weiter, sofern es sich
138
+ # nicht um die Verarbeitung einer LIR-Datei handelt. Im Falle einer normalen Datei
139
+ # wird der Dateiname gespeichert und als Kennzeichen für die Erzeugung von
140
+ # Zeilenende-Nachrichten herangezogen.
141
+ @filename = nil
142
+ end
144
143
 
145
- def control(cmd, param)
146
- case cmd
147
- when STR_CMD_FILE then @filename = param
148
- when STR_CMD_LIR then @filename = nil
149
- when STR_CMD_EOF then @cont = nil
144
+ def control(cmd, param)
145
+ case cmd
146
+ when STR_CMD_FILE then @filename = param
147
+ when STR_CMD_LIR then @filename = nil
148
+ when STR_CMD_EOF then @cont = nil
149
+ end
150
150
  end
151
- end
152
151
 
153
- def process(obj)
154
- if obj.is_a?(String)
155
- inc('Anzahl Zeilen')
152
+ def process(obj)
153
+ if obj.is_a?(String)
154
+ inc('Anzahl Zeilen')
156
155
 
157
- tokenize(obj) { |form, attr|
158
- token = Token.new(form, attr)
156
+ tokenize(obj) { |form, attr|
157
+ token = Token.new(form, attr)
159
158
 
160
- inc('Anzahl Muster '+token.attr)
161
- inc('Anzahl Token')
159
+ inc('Anzahl Muster '+token.attr)
160
+ inc('Anzahl Token')
162
161
 
163
- forward(token)
164
- }
162
+ forward(token)
163
+ }
165
164
 
166
- forward(STR_CMD_EOL, @filename) if @filename
167
- else
168
- forward(obj)
165
+ forward(STR_CMD_EOL, @filename) if @filename
166
+ else
167
+ forward(obj)
168
+ end
169
169
  end
170
- end
171
170
 
172
- private
173
-
174
- # tokenize("Eine Zeile.") -> [:Eine/WORD:, :Zeile/WORD:, :./PUNC:]
175
- def tokenize(textline)
176
- case @cont
177
- when 'HTML'
178
- if textline =~ /^[^<>]*>/
179
- yield $~[0], @cont
180
- textline, @cont = $', nil
181
- else
182
- yield textline, @cont
183
- return
184
- end
185
- when 'WIKI'
186
- if textline =~ /^[^\[\]]*\]\]/
187
- yield $~[0], @cont
188
- textline, @cont = $', nil
189
- else
190
- yield textline, @cont
191
- return
192
- end
193
- when nil
194
- if !@tags && textline =~ /<[^<>]*$/
195
- yield $~[0], @cont = 'HTML'
196
- textline = $`
197
- end
171
+ private
172
+
173
+ # tokenize("Eine Zeile.") -> [:Eine/WORD:, :Zeile/WORD:, :./PUNC:]
174
+ def tokenize(textline)
175
+ case @cont
176
+ when 'HTML'
177
+ if textline =~ /^[^<>]*>/
178
+ yield $~[0], @cont
179
+ textline, @cont = $', nil
180
+ else
181
+ yield textline, @cont
182
+ return
183
+ end
184
+ when 'WIKI'
185
+ if textline =~ /^[^\[\]]*\]\]/
186
+ yield $~[0], @cont
187
+ textline, @cont = $', nil
188
+ else
189
+ yield textline, @cont
190
+ return
191
+ end
192
+ when nil
193
+ if !@tags && textline =~ /<[^<>]*$/
194
+ yield $~[0], @cont = 'HTML'
195
+ textline = $`
196
+ end
197
+
198
+ if !@wiki && textline =~ /\[\[[^\[\]]*$/
199
+ yield $~[0], @cont = 'WIKI'
200
+ textline = $`
201
+ end
202
+ end
198
203
 
199
- if !@wiki && textline =~ /\[\[[^\[\]]*$/
200
- yield $~[0], @cont = 'WIKI'
201
- textline = $`
202
- end
204
+ until textline.empty?
205
+ @rules.each { |name, expr|
206
+ if textline =~ expr
207
+ yield $~[0], name if name != 'SPAC' || @space
208
+ textline = $'
209
+ break
210
+ end
211
+ }
212
+ end
203
213
  end
204
214
 
205
- until textline.empty?
206
- @rules.each { |name, expr|
207
- if textline =~ expr
208
- yield $~[0], name if name != 'SPAC' || @space
209
- textline = $'
210
- break
211
- end
212
- }
213
- end
214
215
  end
215
216
 
216
217
  end
@@ -1,183 +1,179 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  #--
4
- # LINGO ist ein Indexierungssystem mit Grundformreduktion, Kompositumzerlegung,
5
- # Mehrworterkennung und Relationierung.
6
- #
7
- # Copyright (C) 2005-2007 John Vorhauer
8
- # Copyright (C) 2007-2011 John Vorhauer, Jens Wille
9
- #
10
- # This program is free software; you can redistribute it and/or modify it under
11
- # the terms of the GNU Affero General Public License as published by the Free
12
- # Software Foundation; either version 3 of the License, or (at your option)
13
- # any later version.
14
- #
15
- # This program is distributed in the hope that it will be useful, but WITHOUT
16
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
- # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
18
- # details.
19
- #
20
- # You should have received a copy of the GNU Affero General Public License along
21
- # with this program; if not, write to the Free Software Foundation, Inc.,
22
- # 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
23
- #
24
- # For more information visit http://www.lex-lingo.de or contact me at
25
- # welcomeATlex-lingoDOTde near 50°55'N+6°55'E.
26
- #
27
- # Lex Lingo rules from here on
4
+ ###############################################################################
5
+ # #
6
+ # Lingo -- A full-featured automatic indexing system #
7
+ # #
8
+ # Copyright (C) 2005-2007 John Vorhauer #
9
+ # Copyright (C) 2007-2012 John Vorhauer, Jens Wille #
10
+ # #
11
+ # Lingo is free software; you can redistribute it and/or modify it under the #
12
+ # terms of the GNU Affero General Public License as published by the Free #
13
+ # Software Foundation; either version 3 of the License, or (at your option) #
14
+ # any later version. #
15
+ # #
16
+ # Lingo is distributed in the hope that it will be useful, but WITHOUT ANY #
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS #
18
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for #
19
+ # more details. #
20
+ # #
21
+ # You should have received a copy of the GNU Affero General Public License #
22
+ # along with Lingo. If not, see <http://www.gnu.org/licenses/>. #
23
+ # #
24
+ ###############################################################################
28
25
  #++
29
26
 
30
27
  class Lingo
31
28
 
32
- # Der Variator ermöglicht bei nicht erkannten Wörtern den listenbasierten
33
- # Austausch einzelner Wortteile einchließlich erneuter Wörterbuchsuche zur
34
- # Verbesserung der Worterkennungsquote.
35
- #
36
- # Ursprünglich wurde der Variator entwickelt, um die mangelnde Qualität bei der
37
- # OCR-Erkennung altdeutscher 's'-Konsonanten zu optimieren. Er kann ebenso bei
38
- # alternativen Umlautschreibweisen z.B. zur Wandlung von 'Koeln' in 'Köln' dienen.
39
- #
40
- # === Mögliche Verlinkung
41
- # Erwartet:: Daten vom Typ *Word* (andere werden einfach durchgereicht) z.B. von Wordsearcher
42
- # Erzeugt:: Daten vom Typ *Word* zur Weiterleitung z.B. an Synonymer, Decomposer, Multiworder, Sequencer, Noneword_filter oder Vector_filter
43
- #
44
- # === Parameter
45
- # Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
46
- # Alle anderen Parameter müssen zwingend angegeben werden.
47
- # <b>in</b>:: siehe allgemeine Beschreibung des Attendee
48
- # <b>out</b>:: siehe allgemeine Beschreibung des Attendee
49
- # <b>source</b>:: siehe allgemeine Beschreibung des Dictionary
50
- # <b><i>mode</i></b>:: (Standard: all) siehe allgemeine Beschreibung des Dictionary
51
- # <b><i>^check</i></b>:: (Standard: WA_UNKNOWN) Gebrenzt die zu variierenden Worttypen
52
- # <b><i>marker</i></b>:: (Standard: '*') Kennzeichnung durch Variation erkannter Wörter
53
- # <b><i>max-var</i></b>:: (Standard: '10000') Begrenzung der maximal zu prüfenden Permutationen bei der vollständigen Kombination aller auf ein Wort anzuwendenen aufgelisteten Wortteile.
54
- #
55
- # === Beispiele
56
- # Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration <tt>t1.cfg</tt>
57
- # meeting:
58
- # attendees:
59
- # - textreader: { out: lines, files: '$(files)' }
60
- # - tokenizer: { in: lines, out: token }
61
- # - wordsearcher: { in: abbrev, out: words, source: 'sys-dic' }
62
- # - variator: { in: words, out: varios, source: 'sys-dic' }
63
- # - debugger: { in: varios, prompt: 'out>' }
64
- # ergibt die Ausgabe über den Debugger: <tt>lingo -c t1 test.txt</tt>
65
- # out> *FILE('test.txt')
66
- # out> <*Dies = [(dies/w)]>
67
- # out> <*ist = [(ist/t)]>
68
- # out> <ein = [(ein/t)]>
69
- # out> <*Tisch = [(tisch/s)]>
70
- # out> :./PUNC:
71
- # out> *EOL('test.txt')
72
- # out> *EOF('test.txt')
73
-
74
- class Attendee::Variator < Attendee
75
-
76
- protected
77
-
78
- def init
79
- # Parameter verarbeiten
80
- @marker = get_key('marker', '*')
81
- @max_var = get_key('max-var', '10000').to_i
82
- filter = get_array('check', WA_UNKNOWN)
83
-
84
- src = get_array('source')
85
- mod = get_key('mode', 'all')
86
-
87
- # Daten verarbeiten
88
- @var_strings = get_key('variations')
89
- forward(STR_CMD_ERR, 'Ocr-variator: Konfiguration <ocr-variator> ist leer') if @var_strings.size==0
90
-
91
- # Initialisierungen
92
- @check = Hash.new(false)
93
- filter.each { |s| @check[s.upcase] = true }
94
-
95
- # Wörterbuchzugriff
96
- @dic = Dictionary.new({'source'=>src, 'mode'=>mod}, @lingo)
97
- @gra = Grammar.new({'source'=>src, 'mode'=>mod}, @lingo)
98
-
99
- # Optimierungen
100
- if @max_var == 0
101
- forward( STR_CMD_WARN, 'Ocr-variator: max-var ist 0, setze es auf 10.000' )
102
- @max_var = 10000
103
- end
104
- end
29
+ class Attendee
105
30
 
106
- def control(cmd, par)
107
- # Status wird abgefragt
108
- if cmd == STR_CMD_STATUS
109
- # Eigenen Status um Status von Dictionary und Grammer erweitern
110
- @dic.report.each_pair { | k, v | set( k, v ) }
111
- @gra.report.each_pair { | k, v | set( k, v ) }
31
+ # Der Variator ermöglicht bei nicht erkannten Wörtern den listenbasierten
32
+ # Austausch einzelner Wortteile einchließlich erneuter Wörterbuchsuche zur
33
+ # Verbesserung der Worterkennungsquote.
34
+ #
35
+ # Ursprünglich wurde der Variator entwickelt, um die mangelnde Qualität bei der
36
+ # OCR-Erkennung altdeutscher 's'-Konsonanten zu optimieren. Er kann ebenso bei
37
+ # alternativen Umlautschreibweisen z.B. zur Wandlung von 'Koeln' in 'Köln' dienen.
38
+ #
39
+ # === Mögliche Verlinkung
40
+ # Erwartet:: Daten vom Typ *Word* (andere werden einfach durchgereicht) z.B. von Wordsearcher
41
+ # Erzeugt:: Daten vom Typ *Word* zur Weiterleitung z.B. an Synonymer, Decomposer, Multiworder, Sequencer, Noneword_filter oder Vector_filter
42
+ #
43
+ # === Parameter
44
+ # Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
45
+ # Alle anderen Parameter müssen zwingend angegeben werden.
46
+ # <b>in</b>:: siehe allgemeine Beschreibung des Attendee
47
+ # <b>out</b>:: siehe allgemeine Beschreibung des Attendee
48
+ # <b>source</b>:: siehe allgemeine Beschreibung des Dictionary
49
+ # <b><i>mode</i></b>:: (Standard: all) siehe allgemeine Beschreibung des Dictionary
50
+ # <b><i>^check</i></b>:: (Standard: WA_UNKNOWN) Gebrenzt die zu variierenden Worttypen
51
+ # <b><i>marker</i></b>:: (Standard: '*') Kennzeichnung durch Variation erkannter Wörter
52
+ # <b><i>max-var</i></b>:: (Standard: '10000') Begrenzung der maximal zu prüfenden Permutationen bei der vollständigen Kombination aller auf ein Wort anzuwendenen aufgelisteten Wortteile.
53
+ #
54
+ # === Beispiele
55
+ # Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration <tt>t1.cfg</tt>
56
+ # meeting:
57
+ # attendees:
58
+ # - text_reader: { out: lines, files: '$(files)' }
59
+ # - tokenizer: { in: lines, out: token }
60
+ # - word_searcher: { in: abbrev, out: words, source: 'sys-dic' }
61
+ # - variator: { in: words, out: varios, source: 'sys-dic' }
62
+ # - debugger: { in: varios, prompt: 'out>' }
63
+ # ergibt die Ausgabe über den Debugger: <tt>lingo -c t1 test.txt</tt>
64
+ # out> *FILE('test.txt')
65
+ # out> <*Dies = [(dies/w)]>
66
+ # out> <*ist = [(ist/t)]>
67
+ # out> <ein = [(ein/t)]>
68
+ # out> <*Tisch = [(tisch/s)]>
69
+ # out> :./PUNC:
70
+ # out> *EOL('test.txt')
71
+ # out> *EOF('test.txt')
72
+
73
+ class Variator < self
74
+
75
+ protected
76
+
77
+ def init
78
+ # Parameter verarbeiten
79
+ @marker = get_key('marker', '*')
80
+ @max_var = get_key('max-var', '10000').to_i
81
+ filter = get_array('check', WA_UNKNOWN)
82
+
83
+ # Daten verarbeiten
84
+ @var_strings = get_key('variations')
85
+ raise MissingConfigError.new(:variations) if @var_strings.empty?
86
+
87
+ # Initialisierungen
88
+ @check = Hash.new(false)
89
+ filter.each { |s| @check[s.upcase] = true }
90
+
91
+ set_dic
92
+ set_gra
93
+
94
+ if @max_var.zero?
95
+ @max_var = 10000
96
+ @lingo.warn "#{self.class}: max-var is 0, setting to #{@max_var}"
97
+ end
112
98
  end
113
- end
114
99
 
115
- def process(obj)
116
- # Zu prüfende Wörter filtern
117
- if obj.is_a?(Word) && @check[obj.attr]
118
- # Statistik für Report
119
- inc('Anzahl gesuchter Wörter')
120
-
121
- # Erzeuge Variationen einer Wortform
122
- variations = [obj.form]
123
- @var_strings.each do |switch|
124
- from, to = switch
125
- variations = variate(variations, from, to)
100
+ def control(cmd, par)
101
+ # Status wird abgefragt
102
+ if cmd == STR_CMD_STATUS
103
+ # Eigenen Status um Status von Dictionary und Grammer erweitern
104
+ @dic.report.each_pair { | k, v | set( k, v ) }
105
+ @gra.report.each_pair { | k, v | set( k, v ) }
126
106
  end
107
+ end
127
108
 
128
- # Prüfe Variation auf bekanntes Wort
129
- variations[0...@max_var].each do |var|
130
- # Variiertes Wort im Wörterbuch suchen
131
- word = @dic.find_word(var)
132
- word = @gra.find_compositum(var) if word.attr == WA_UNKNOWN
133
- next if word.attr == WA_UNKNOWN || (
134
- word.attr == WA_KOMPOSITUM && word.lexicals.any? { |lex|
135
- lex.attr[0..0] == LA_TAKEITASIS
136
- }
137
- )
138
-
139
- # Das erste erkannte Wort beendet die Suche
140
- inc('Anzahl gefundener Wörter')
141
- word.form = @marker + var
142
- forward(word)
143
- return
109
+ def process(obj)
110
+ # Zu prüfende Wörter filtern
111
+ if obj.is_a?(Word) && @check[obj.attr]
112
+ # Statistik für Report
113
+ inc('Anzahl gesuchter Wörter')
114
+
115
+ # Erzeuge Variationen einer Wortform
116
+ variations = [obj.form]
117
+ @var_strings.each do |switch|
118
+ from, to = switch
119
+ variations = variate(variations, from, to)
120
+ end
121
+
122
+ # Prüfe Variation auf bekanntes Wort
123
+ variations[0...@max_var].each do |var|
124
+ # Variiertes Wort im Wörterbuch suchen
125
+ word = @dic.find_word(var)
126
+ word = @gra.find_compositum(var) if word.unknown?
127
+ next if word.unknown? || (
128
+ word.attr == WA_KOMPOSITUM && word.lexicals.any? { |lex|
129
+ lex.attr[0..0] == LA_TAKEITASIS
130
+ }
131
+ )
132
+
133
+ # Das erste erkannte Wort beendet die Suche
134
+ inc('Anzahl gefundener Wörter')
135
+ word.form = @marker + var
136
+ forward(word)
137
+ return
138
+ end
144
139
  end
145
- end
146
140
 
147
- forward(obj)
148
- end
141
+ forward(obj)
142
+ end
149
143
 
150
- private
144
+ private
151
145
 
152
- # Variiere die Bestandteile eines Arrays gemäß den Austauschvorgaben.
153
- #
154
- # variate( 'Tiieh', 'ieh', 'sch' ) => ['Tiieh', 'Tisch']
155
- def variate(variation_list, from, to)
156
- # neue Varianten sammeln
157
- add_variations = []
158
- from_re = Regexp.new(from)
146
+ # Variiere die Bestandteile eines Arrays gemäß den Austauschvorgaben.
147
+ #
148
+ # variate( 'Tiieh', 'ieh', 'sch' ) => ['Tiieh', 'Tisch']
149
+ def variate(variation_list, from, to)
150
+ # neue Varianten sammeln
151
+ add_variations = []
152
+ from_re = Regexp.new(from)
159
153
 
160
- # alle Wörter in der variation_list permutieren
161
- variation_list.each do |wordform|
154
+ # alle Wörter in der variation_list permutieren
155
+ variation_list.each do |wordform|
162
156
 
163
- # Wortform in Teile zerlegen und anschließend Dimension feststellen
164
- wordpart = " #{wordform} ".split( from_re )
165
- n = wordpart.size - 1
157
+ # Wortform in Teile zerlegen und anschließend Dimension feststellen
158
+ wordpart = " #{wordform} ".split( from_re )
159
+ n = wordpart.size - 1
166
160
 
167
- # Austauschketten in Matrix hinterlegen
168
- change = [from, to]
161
+ # Austauschketten in Matrix hinterlegen
162
+ change = [from, to]
169
163
 
170
- # Austauschketten auf alle Teile anwenden
171
- (1..(2**n-1)).each do |i|
172
- variation = wordpart[0]
173
- # i[x] = Wert des x.ten Bit von Integer i
174
- (1..n).each { |j| variation += change[i[j-1]] + wordpart[j] }
164
+ # Austauschketten auf alle Teile anwenden
165
+ (1..(2**n-1)).each do |i|
166
+ variation = wordpart[0]
167
+ # i[x] = Wert des x.ten Bit von Integer i
168
+ (1..n).each { |j| variation += change[i[j-1]] + wordpart[j] }
175
169
 
176
- add_variations << variation.strip
170
+ add_variations << variation.strip
171
+ end
177
172
  end
173
+
174
+ variation_list + add_variations
178
175
  end
179
176
 
180
- variation_list + add_variations
181
177
  end
182
178
 
183
179
  end