lingo 1.8.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/.rspec +1 -0
- data/COPYING +663 -0
- data/ChangeLog +754 -0
- data/README +322 -0
- data/Rakefile +100 -0
- data/TODO +28 -0
- data/bin/lingo +5 -0
- data/bin/lingoctl +6 -0
- data/de.lang +121 -0
- data/de/lingo-abk.txt +74 -0
- data/de/lingo-dic.txt +56822 -0
- data/de/lingo-mul.txt +3209 -0
- data/de/lingo-syn.txt +14841 -0
- data/de/test_dic.txt +24 -0
- data/de/test_mul.txt +17 -0
- data/de/test_mul2.txt +2 -0
- data/de/test_singleword.txt +2 -0
- data/de/test_syn.txt +4 -0
- data/de/test_syn2.txt +1 -0
- data/de/user-dic.txt +10 -0
- data/en.lang +113 -0
- data/en/lingo-dic.txt +55434 -0
- data/en/lingo-mul.txt +456 -0
- data/en/user-dic.txt +5 -0
- data/info/Objekte.png +0 -0
- data/info/Typen.png +0 -0
- data/info/database.png +0 -0
- data/info/db_small.png +0 -0
- data/info/download.png +0 -0
- data/info/gpl-hdr.txt +27 -0
- data/info/kerze.png +0 -0
- data/info/language.png +0 -0
- data/info/lingo.png +0 -0
- data/info/logo.png +0 -0
- data/info/meeting.png +0 -0
- data/info/types.png +0 -0
- data/lib/lingo.rb +321 -0
- data/lib/lingo/attendee/abbreviator.rb +119 -0
- data/lib/lingo/attendee/debugger.rb +111 -0
- data/lib/lingo/attendee/decomposer.rb +101 -0
- data/lib/lingo/attendee/dehyphenizer.rb +167 -0
- data/lib/lingo/attendee/multiworder.rb +301 -0
- data/lib/lingo/attendee/noneword_filter.rb +103 -0
- data/lib/lingo/attendee/objectfilter.rb +86 -0
- data/lib/lingo/attendee/sequencer.rb +190 -0
- data/lib/lingo/attendee/synonymer.rb +105 -0
- data/lib/lingo/attendee/textreader.rb +237 -0
- data/lib/lingo/attendee/textwriter.rb +196 -0
- data/lib/lingo/attendee/tokenizer.rb +218 -0
- data/lib/lingo/attendee/variator.rb +185 -0
- data/lib/lingo/attendee/vector_filter.rb +158 -0
- data/lib/lingo/attendee/wordsearcher.rb +96 -0
- data/lib/lingo/attendees.rb +289 -0
- data/lib/lingo/cli.rb +62 -0
- data/lib/lingo/config.rb +104 -0
- data/lib/lingo/const.rb +131 -0
- data/lib/lingo/ctl.rb +173 -0
- data/lib/lingo/database.rb +587 -0
- data/lib/lingo/language.rb +530 -0
- data/lib/lingo/modules.rb +98 -0
- data/lib/lingo/types.rb +285 -0
- data/lib/lingo/utilities.rb +40 -0
- data/lib/lingo/version.rb +27 -0
- data/lingo-all.cfg +85 -0
- data/lingo-call.cfg +15 -0
- data/lingo.cfg +78 -0
- data/lingo.rb +3 -0
- data/lir.cfg +72 -0
- data/porter/stem.cfg +311 -0
- data/porter/stem.rb +150 -0
- data/spec/spec_helper.rb +0 -0
- data/test.cfg +79 -0
- data/test/attendee/ts_abbreviator.rb +35 -0
- data/test/attendee/ts_decomposer.rb +31 -0
- data/test/attendee/ts_multiworder.rb +390 -0
- data/test/attendee/ts_noneword_filter.rb +19 -0
- data/test/attendee/ts_objectfilter.rb +19 -0
- data/test/attendee/ts_sequencer.rb +43 -0
- data/test/attendee/ts_synonymer.rb +33 -0
- data/test/attendee/ts_textreader.rb +58 -0
- data/test/attendee/ts_textwriter.rb +98 -0
- data/test/attendee/ts_tokenizer.rb +32 -0
- data/test/attendee/ts_variator.rb +24 -0
- data/test/attendee/ts_vector_filter.rb +62 -0
- data/test/attendee/ts_wordsearcher.rb +119 -0
- data/test/lir.csv +3 -0
- data/test/lir.txt +12 -0
- data/test/lir2.txt +12 -0
- data/test/mul.txt +1 -0
- data/test/ref/artikel.mul +1 -0
- data/test/ref/artikel.non +159 -0
- data/test/ref/artikel.seq +270 -0
- data/test/ref/artikel.syn +16 -0
- data/test/ref/artikel.vec +928 -0
- data/test/ref/artikel.ven +928 -0
- data/test/ref/artikel.ver +928 -0
- data/test/ref/lir.csv +328 -0
- data/test/ref/lir.mul +1 -0
- data/test/ref/lir.non +274 -0
- data/test/ref/lir.seq +249 -0
- data/test/ref/lir.syn +94 -0
- data/test/test_helper.rb +113 -0
- data/test/ts_database.rb +269 -0
- data/test/ts_language.rb +396 -0
- data/txt/artikel-en.txt +157 -0
- data/txt/artikel.txt +170 -0
- data/txt/lir.txt +1317 -0
- metadata +211 -0
@@ -0,0 +1,237 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
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
|
28
|
+
#++
|
29
|
+
|
30
|
+
%w[filemagic mime/types hpricot pdf-reader].each { |lib|
|
31
|
+
begin
|
32
|
+
require lib
|
33
|
+
rescue LoadError
|
34
|
+
end
|
35
|
+
}
|
36
|
+
|
37
|
+
class Lingo
|
38
|
+
|
39
|
+
# Der Textreader ist eine klassische Datenquelle. Er liest eine oder mehrere Dateien
|
40
|
+
# und gibt sie Zeilenweise in den Ausgabekanal. Der Start bzw. Wechsel einer Datei
|
41
|
+
# wird dabei über den Kommandokanal angekündigt, ebenso wie das Ende.
|
42
|
+
#
|
43
|
+
# Der Textreader kann ebenfalls ein spezielles Dateiformat verarbeiten, welches zum
|
44
|
+
# Austausch mit dem LIR-System dient. Dabei enthält die Datei Record-basierte Informationen,
|
45
|
+
# die wie mehrere Dateien verarbeitet werden.
|
46
|
+
#
|
47
|
+
# === Mögliche Verlinkung
|
48
|
+
# Erzeugt:: Daten des Typs *String* (Textzeile) z.B. für Tokenizer, Textwriter
|
49
|
+
#
|
50
|
+
# === Parameter
|
51
|
+
# Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
|
52
|
+
# Alle anderen Parameter müssen zwingend angegeben werden.
|
53
|
+
# <b>out</b>:: siehe allgemeine Beschreibung des Attendee
|
54
|
+
# <b>files</b>:: Es können eine oder mehrere Dateien angegeben werden, die nacheinander
|
55
|
+
# eingelesen und zeilenweise weitergeleitet werden. Die Dateien werden mit
|
56
|
+
# Komma voneinander getrennt, z.B.
|
57
|
+
# files: 'readme.txt'
|
58
|
+
# files: 'readme.txt,lingo.cfg'
|
59
|
+
# <b><i>lir-record-pattern</i></b>:: Mit diesem Parameter wird angegeben, woran der Anfang
|
60
|
+
# eines neuen Records erkannt werden kann und wie die
|
61
|
+
# Record-Nummer identifiziert wird. Das Format einer
|
62
|
+
# LIR-Datei ist z.B.
|
63
|
+
# [00001.]
|
64
|
+
# 020: ¬Die Aufgabenteilung zwischen Wortschatz und Grammatik.
|
65
|
+
#
|
66
|
+
# [00002.]
|
67
|
+
# 020: Nicht-konventionelle Thesaurusrelationen als Orientierungshilfen.
|
68
|
+
# Mit der Angabe von
|
69
|
+
# lir-record-pattern: "^\[(\d+)\.\]"
|
70
|
+
# werden die Record-Zeilen erkannt und jeweils die Record-Nummer +00001+,
|
71
|
+
# bzw. +00002+ erkannt.
|
72
|
+
#
|
73
|
+
# === Generierte Kommandos
|
74
|
+
# Damit der nachfolgende Datenstrom einwandfrei verarbeitet werden kann, generiert der Textreader
|
75
|
+
# Kommandos, die mit in den Datenstrom eingefügt werden.
|
76
|
+
# <b>*FILE(<dateiname>)</b>:: Kennzeichnet den Beginn der Datei <dateiname>
|
77
|
+
# <b>*EOF(<dateiname>)</b>:: Kennzeichnet das Ende der Datei <dateiname>
|
78
|
+
# <b>*LIR_FORMAT('')</b>:: Kennzeichnet die Verarbeitung einer Datei im LIR-Format (nur bei LIR-Format).
|
79
|
+
# <b>*RECORD(<nummer>)</b>:: Kennzeichnet den Beginn eines neuen Records (nur bei LIR-Format).
|
80
|
+
# === Beispiele
|
81
|
+
# Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration <tt>t1.cfg</tt>
|
82
|
+
# meeting:
|
83
|
+
# attendees:
|
84
|
+
# - textreader: { out: lines, files: '$(files)' }
|
85
|
+
# - debugger: { in: lines, prompt: 'out>' }
|
86
|
+
# ergibt die Ausgabe über den Debugger: <tt>lingo -c t1 test.txt</tt>
|
87
|
+
# out> *FILE('test.txt')
|
88
|
+
# out> "Dies ist eine Zeile."
|
89
|
+
# out> "Dies ist noch eine."
|
90
|
+
# out> *EOF('test.txt')
|
91
|
+
# Bei der Verarbeitung einer LIR-Datei mit der Ablaufkonfiguration <tt>t2.cfg</tt>
|
92
|
+
# meeting:
|
93
|
+
# attendees:
|
94
|
+
# - textreader: { out: lines, files: '$(files)', lir-record-pattern: "^\[(\d+)\.\]" }
|
95
|
+
# - debugger: { in: lines, prompt: 'out>'}
|
96
|
+
# ergibt die Ausgabe mit <tt>lingo -c t2 lir.txt</tt>
|
97
|
+
# out> *LIR-FORMAT('')
|
98
|
+
# out> *FILE('lir.txt')
|
99
|
+
# out> *RECORD('00001')
|
100
|
+
# out> "020: \254Die Aufgabenteilung zwischen Wortschatz und Grammatik."
|
101
|
+
# out> *RECORD('00002')
|
102
|
+
# out> "020: Nicht-konventionelle Thesaurusrelationen als Orientierungshilfen."
|
103
|
+
# out> *EOF('lir.txt')
|
104
|
+
|
105
|
+
class Attendee::Textreader < Attendee
|
106
|
+
|
107
|
+
protected
|
108
|
+
|
109
|
+
# TODO: FILE und LIR-FILE
|
110
|
+
# TODO: lir-record-pattern abkürzen
|
111
|
+
# Interpretation der Parameter
|
112
|
+
def init
|
113
|
+
@files = Array(get_key('files', '-'))
|
114
|
+
@rec_pat = Regexp.new(get_key('lir-record-pattern', ''))
|
115
|
+
@is_LIR_file = has_key?('lir-record-pattern')
|
116
|
+
@chomp = get_key('chomp', true)
|
117
|
+
@filter = get_key('filter', false)
|
118
|
+
end
|
119
|
+
|
120
|
+
def control(cmd, param)
|
121
|
+
if cmd==STR_CMD_TALK
|
122
|
+
forward(STR_CMD_LIR, '') if @is_LIR_file
|
123
|
+
@files.each { |filename| spool(filename) }
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
# Gibt eine Datei zeilenweise in den Ausgabekanal
|
130
|
+
def spool(filename)
|
131
|
+
unless stdin?(filename)
|
132
|
+
FileTest.exist?(filename) || forward(STR_CMD_ERR, "Datei #{filename} nicht gefunden")
|
133
|
+
|
134
|
+
inc('Anzahl Dateien')
|
135
|
+
add('Anzahl Bytes', File.stat(filename).size)
|
136
|
+
end
|
137
|
+
|
138
|
+
forward(STR_CMD_FILE, filename)
|
139
|
+
|
140
|
+
filter(filename) { |line|
|
141
|
+
inc('Anzahl Zeilen')
|
142
|
+
line.chomp! if @chomp
|
143
|
+
line.gsub!(/\303\237/, "ß")
|
144
|
+
### HACK
|
145
|
+
if @is_LIR_file && line =~ @rec_pat
|
146
|
+
forward(STR_CMD_RECORD, $1)
|
147
|
+
else
|
148
|
+
forward(line) if line.size>0
|
149
|
+
end
|
150
|
+
}
|
151
|
+
|
152
|
+
forward(STR_CMD_EOF, filename)
|
153
|
+
end
|
154
|
+
|
155
|
+
def filter(filename, &block)
|
156
|
+
file = stdin?(filename) ?
|
157
|
+
@lingo.config.stdin.set_encoding(ENC) :
|
158
|
+
File.open(filename, 'rb', encoding: ENC)
|
159
|
+
|
160
|
+
file = case @filter == true ? file_type(filename, file) : @filter.to_s
|
161
|
+
when /html/ then filter_html(file)
|
162
|
+
when /xml/ then filter_html(file, true)
|
163
|
+
when /pdf/ then filter_pdf(file, &block) or return
|
164
|
+
else file
|
165
|
+
end if @filter
|
166
|
+
|
167
|
+
file.each_line(&block)
|
168
|
+
end
|
169
|
+
|
170
|
+
def filter_pdf(file, &block)
|
171
|
+
if Object.const_defined?(:PDF) && PDF.const_defined?(:Reader)
|
172
|
+
PDFFilter.filter(file, &block)
|
173
|
+
nil
|
174
|
+
else
|
175
|
+
warn "PDF filter not available. Please install `pdf-reader'."
|
176
|
+
file
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def filter_html(file, xml = false)
|
181
|
+
if Object.const_defined?(:Hpricot)
|
182
|
+
Hpricot(file, xml: xml).inner_text
|
183
|
+
else
|
184
|
+
warn "#{xml ? 'X' : 'HT'}ML filter not available. Please install `hpricot'."
|
185
|
+
file
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def file_type(filename, file)
|
190
|
+
if Object.const_defined?(:FileMagic) && file.respond_to?(:rewind)
|
191
|
+
type = FileMagic.fm(:mime, simplified: true).buffer(file.read(256))
|
192
|
+
file.rewind
|
193
|
+
type
|
194
|
+
elsif Object.const_defined?(:MIME) && MIME.const_defined?(:Types)
|
195
|
+
if type = MIME::Types.of(filename).first
|
196
|
+
type.content_type
|
197
|
+
else
|
198
|
+
warn 'Filters not available. File type could not be determined.'
|
199
|
+
nil
|
200
|
+
end
|
201
|
+
else
|
202
|
+
warn "Filters not available. Please install `ruby-filemagic' or `mime-types'."
|
203
|
+
nil
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def stdin?(filename)
|
208
|
+
%w[STDIN -].include?(filename)
|
209
|
+
end
|
210
|
+
|
211
|
+
class PDFFilter
|
212
|
+
|
213
|
+
def self.filter(file, &block)
|
214
|
+
PDF::Reader.new.parse(file, new(&block))
|
215
|
+
end
|
216
|
+
|
217
|
+
def initialize(&block)
|
218
|
+
@block = block
|
219
|
+
end
|
220
|
+
|
221
|
+
def show_text(string, *params)
|
222
|
+
@block[string << '|']
|
223
|
+
end
|
224
|
+
|
225
|
+
alias_method :super_show_text, :show_text
|
226
|
+
alias_method :move_to_next_line_and_show_text, :show_text
|
227
|
+
alias_method :set_spacing_next_line_show_text, :show_text
|
228
|
+
|
229
|
+
def show_text_with_positioning(params, *)
|
230
|
+
params.each { |param| show_text(param) if param.is_a?(String) }
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
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
|
28
|
+
#++
|
29
|
+
|
30
|
+
class Lingo
|
31
|
+
|
32
|
+
# Der Textwriter ermöglicht die Umleitung des Datenstroms in eine Textdatei. Dabei werden
|
33
|
+
# Objekte, die nicht vom Typ String sind in eine sinnvolle Textrepresentation gewandelt.
|
34
|
+
# Der Name der Ausgabedatei wird durch den Namen der Eingabedatei (des Textreaders) bestimmt.
|
35
|
+
# Es kann lediglich die Extension verändert werden. Der Textwriter kann auch das LIR-Format
|
36
|
+
# erzeugen.
|
37
|
+
#
|
38
|
+
# === Mögliche Verlinkung
|
39
|
+
# Erwartet:: Daten verschiedenen Typs
|
40
|
+
#
|
41
|
+
# === Parameter
|
42
|
+
# Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung).
|
43
|
+
# Alle anderen Parameter müssen zwingend angegeben werden.
|
44
|
+
# <b>in</b>:: siehe allgemeine Beschreibung des Attendee
|
45
|
+
# <b>out</b>:: siehe allgemeine Beschreibung des Attendee
|
46
|
+
# <b><i>ext</i></b>:: (Standard: txt2) Gibt die Dateinamen-Erweiertung für die Ausgabedatei an.
|
47
|
+
# Wird z.B. dem Textreader die Datei <tt>Dokument.txt</tt> angegeben und
|
48
|
+
# über die Lingo-Konfiguration alle Indexwörter herausgefiltert, kann mit
|
49
|
+
# <tt>ext: 'idx'</tt> der Textwriter veranlasst werden, die Indexwörter in
|
50
|
+
# die Datei <tt>Dokument.idx</tt> zu schreiben.
|
51
|
+
# <b><i>sep</i></b>:: (Standard: ' ') Gibt an, mit welchem Trennzeichen zwei aufeinanderfolgende
|
52
|
+
# Objekte in der Ausgabedatei getrennt werden sollen. Gängige Werte sind auch
|
53
|
+
# noch '\n', welches die Ausgabe jedes Objektes in eine Zeile ermöglicht.
|
54
|
+
# <b><i>lir-format</i></b>:: (Standard: false) Dieser Parameter hat keinen Wert. Wird er angegeben,
|
55
|
+
# dann wird er als true ausgewertet. Damit ist es möglich, die Ausgabedatei
|
56
|
+
# im für LIR lesbarem Format zu erstellen.
|
57
|
+
#
|
58
|
+
# === Beispiele
|
59
|
+
# Bei der Verarbeitung der oben angegebenen Funktionsbeschreibung des Textwriters mit der Ablaufkonfiguration <tt>t1.cfg</tt>
|
60
|
+
# meeting:
|
61
|
+
# attendees:
|
62
|
+
# - textreader: { out: lines, files: '$(files)' }
|
63
|
+
# - tokenizer: { in: lines, out: token }
|
64
|
+
# - wordsearcher: { in: token, out: words, source: 'sys-dic' }
|
65
|
+
# - vector_filter: { in: words, out: filtr, sort: 'term_rel' }
|
66
|
+
# - textwriter: { in: filtr, ext: 'vec', sep: '\n' }
|
67
|
+
# ergibt die Ausgabe in der Datei <tt>test.vec</tt>
|
68
|
+
# 0.03846 name
|
69
|
+
# 0.01923 ausgabedatei
|
70
|
+
# 0.01923 datenstrom
|
71
|
+
# 0.01923 extension
|
72
|
+
# 0.01923 format
|
73
|
+
# 0.01923 objekt
|
74
|
+
# 0.01923 string
|
75
|
+
# 0.01923 textdatei
|
76
|
+
# 0.01923 typ
|
77
|
+
# 0.01923 umleitung
|
78
|
+
|
79
|
+
class Attendee::Textwriter < Attendee
|
80
|
+
|
81
|
+
protected
|
82
|
+
|
83
|
+
def init
|
84
|
+
@ext = get_key('ext', 'txt2')
|
85
|
+
@lir = get_key('lir-format', false)
|
86
|
+
@sep = @lir ? ' ' : eval("\"#{@config['sep'] || ' '}\"")
|
87
|
+
@no_sep, @no_puts = true, false
|
88
|
+
end
|
89
|
+
|
90
|
+
def control(cmd, par)
|
91
|
+
case cmd
|
92
|
+
when STR_CMD_LIR
|
93
|
+
@lir = true
|
94
|
+
when STR_CMD_FILE
|
95
|
+
@no_sep = true
|
96
|
+
|
97
|
+
if stdout?(@ext)
|
98
|
+
@filename = @ext
|
99
|
+
@file = @lingo.config.stdout
|
100
|
+
else
|
101
|
+
@filename = par.sub(/(\.[^.]+)?$/, '.'+@ext)
|
102
|
+
@file = File.new(@filename,'w')
|
103
|
+
inc('Anzahl Dateien')
|
104
|
+
end
|
105
|
+
|
106
|
+
@lir_rec_no = ''
|
107
|
+
@lir_rec_buf = Array.new
|
108
|
+
when STR_CMD_RECORD
|
109
|
+
@no_sep = true
|
110
|
+
if @lir
|
111
|
+
flush_lir_buffer
|
112
|
+
@lir_rec_no = par
|
113
|
+
end
|
114
|
+
when STR_CMD_EOL
|
115
|
+
@no_sep = true
|
116
|
+
unless @lir
|
117
|
+
@file.puts unless @no_puts # unless @sep=="\n"
|
118
|
+
inc('Anzahl Zeilen')
|
119
|
+
end
|
120
|
+
when STR_CMD_EOF
|
121
|
+
flush_lir_buffer if @lir
|
122
|
+
|
123
|
+
unless stdout?(@filename)
|
124
|
+
@file.close
|
125
|
+
add('Anzahl Bytes', File.stat(@filename).size)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def process(obj)
|
131
|
+
if @lir
|
132
|
+
@lir_rec_buf << (obj.kind_of?(Token) ? obj.form : obj.to_s)
|
133
|
+
else
|
134
|
+
@file.print @sep unless @no_sep
|
135
|
+
@no_sep=false if @no_sep
|
136
|
+
if obj.is_a?(Word) || obj.is_a?(Token)
|
137
|
+
@file.print obj.form
|
138
|
+
else
|
139
|
+
@file.print obj
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def flush_lir_buffer
|
147
|
+
unless @lir_rec_no.empty? || @lir_rec_buf.empty?
|
148
|
+
if @sep =~ /\n/
|
149
|
+
@file.print '*', @lir_rec_no, "\n", @lir_rec_buf.join(@sep), "\n"
|
150
|
+
else
|
151
|
+
@file.print @lir_rec_no, '*', @lir_rec_buf.join(@sep), "\n"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
@lir_rec_no = ''
|
155
|
+
@lir_rec_buf.clear
|
156
|
+
end
|
157
|
+
|
158
|
+
def stdout?(filename)
|
159
|
+
%w[STDOUT -].include?(filename)
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
|
164
|
+
class Attendee::Formatter < Attendee::Textwriter
|
165
|
+
|
166
|
+
protected
|
167
|
+
|
168
|
+
def init
|
169
|
+
super
|
170
|
+
|
171
|
+
@ext = get_key('ext', '-')
|
172
|
+
@format = get_key('format', '%s')
|
173
|
+
@map = get_key('map', Hash.new { |h, k| h[k] = k })
|
174
|
+
|
175
|
+
@no_puts = true
|
176
|
+
end
|
177
|
+
|
178
|
+
def process(obj)
|
179
|
+
if obj.is_a?(Word) || obj.is_a?(Token)
|
180
|
+
str = obj.form
|
181
|
+
|
182
|
+
if obj.respond_to?(:lexicals)
|
183
|
+
lex = obj.lexicals.first # TODO
|
184
|
+
att = @map[lex.attr] if lex
|
185
|
+
str = @format % [str, lex.form, att] if att
|
186
|
+
end
|
187
|
+
else
|
188
|
+
str = obj.to_s
|
189
|
+
end
|
190
|
+
|
191
|
+
@lir ? @lir_rec_buf << str : @file.print(str)
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
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
|
28
|
+
#++
|
29
|
+
|
30
|
+
class Lingo
|
31
|
+
|
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
|
128
|
+
end
|
129
|
+
}
|
130
|
+
|
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
|
144
|
+
|
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
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def process(obj)
|
154
|
+
if obj.is_a?(String)
|
155
|
+
inc('Anzahl Zeilen')
|
156
|
+
|
157
|
+
tokenize(obj) { |form, attr|
|
158
|
+
token = Token.new(form, attr)
|
159
|
+
|
160
|
+
inc('Anzahl Muster '+token.attr)
|
161
|
+
inc('Anzahl Token')
|
162
|
+
|
163
|
+
forward(token)
|
164
|
+
}
|
165
|
+
|
166
|
+
forward(STR_CMD_EOL, @filename) if @filename
|
167
|
+
else
|
168
|
+
forward(obj)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
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
|
198
|
+
|
199
|
+
if !@wiki && textline =~ /\[\[[^\[\]]*$/
|
200
|
+
yield $~[0], @cont = 'WIKI'
|
201
|
+
textline = $`
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
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
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|