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