Der Tokenizer zerlegt eine Textzeile in einzelne Token. Dies ist notwendig, damit nachfolgende Attendees die Textdatei häppchenweise verarbeiten können.
Daten des Typs String (Textzeilen) z.B. von TextReader
Daten des Typs Token z.B. für Abbreviator, Wordsearcher
Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung). Alle anderen Parameter müssen zwingend angegeben werden.
Der Tokenizer benötigt zur Identifikation
einzelner Token Regeln, nach denen er arbeiten soll. Die benötigten Regeln
werden aufgrund des Umfangs nicht als Parameter, sondern in der
Sprachkonfiguration hinterlegt, die sich standardmäßig in der Datei
de.lang befindet (YAML-Format).
language: attendees: tokenizer: regulars: - _CHR_: '\wÄÖÜÁÂÀÉÊÈÍÎÌÓÔÒÚÛÙÝäöüáâàéêèíîìóôòúûùý' - NUMS: '[+-]?(\d{4,}|\d{1,3}(\.\d{3,3})*)(\.|(,\d+)?%?)' - URLS: '((mailto:|(news|http|https|ftp|ftps)://)\S+|^(www(\.\S+)+)|\S+([\._]\S+)+@\S+(\.\S+)+)' - ABRV: '(([_CHR_]+\.)+)[_CHR_]+' - ABRS: '(([_CHR_]{1,1}\.)+)(?!\.\.)' - WORD: '[_CHR_\d]+' - PUNC: '[!,\.:;?]' - OTHR: '[!\"#$%&()*\+,\-\./:;<=>?@\[\\]^_`{|}~´]' - HELP: '.*'
Die Regeln werden in der angegebenen Reihenfolge abgearbeitet, solange bis
ein Token erkannt wurde. Sollte keine Regel zutreffen, so greift die letzt
Regel HELP in jedem Fall. Regeln, deren Name in Unterstriche
eingefasst sind, werden als Makro interpretiert. Makros werden genutzt, um
lange oder sich wiederholende Bestandteile von Regeln einmalig zu
definieren und in den Regeln über den Makronamen eine Auflösung zu
forcieren. Makros werden selber nicht für die Erkennung von Token
eingesetzt.
Damit der nachfolgende Datenstrom einwandfrei verarbeitet werden kann, generiert der Tokenizer Kommandos, die mit in den Datenstrom eingefügt werden.
Kennzeichnet das Ende einer Textzeile, da die Information ansonsten
für nachfolgende Attendees verloren wäre.
Bei der Verarbeitung einer normalen Textdatei mit der Ablaufkonfiguration
t1.cfg
meeting:
attendees:
- text_reader: { out: lines, files: '$(files)' }
- tokenizer: { in: lines, out: token }
- debugger: { in: token, prompt: 'out>' }
ergibt die Ausgabe über den Debugger: lingo -c t1 test.txt
out> *FILE('test.txt')
out> :Dies/WORD:
out> :ist/WORD:
out> :eine/WORD:
out> :Zeile/WORD:
out> :./PUNC:
out> *EOL('test.txt')
out> :Dies/WORD:
out> :ist/WORD:
out> :noch/WORD:
out> :eine/WORD:
out> :./PUNC:
out> *EOL('test.txt')
out> *EOF('test.txt')
# File lib/lingo/attendee/tokenizer.rb, line 131 def control(cmd, param) case cmd when STR_CMD_FILE then @filename = param when STR_CMD_LIR then @filename = nil when STR_CMD_EOF then @cont = nil end end
# File lib/lingo/attendee/tokenizer.rb, line 102 def init @space = get_key('space', false) @tags = get_key('tags', true) @wiki = get_key('wiki', true) # default rules @rules = [['SPAC', %r^\s+/]] @rules << ['HTML', %r^<[^>]+>/] unless @tags @rules << ['WIKI', %r^\[\[.+?\]\]/] unless @wiki @rules.unshift(['WIKI', %r^=+.+=+$/]) unless @wiki get_key('regulars', []).each_with_object({}) { |rule, macros| expr = rule.values.first.gsub(%r_(\w+?)_/) { macros[$&] || begin Database::Source.const_get("UTF8_#{$1.upcase}") rescue NameError end } if (name = rule.keys.first) =~ %r^_\w+_$/ macros[name] = expr else @rules << [name, %r^#{expr}/] end } @filename = @cont = nil end
# File lib/lingo/attendee/tokenizer.rb, line 139 def process(obj) if obj.is_a?(String) inc('Anzahl Zeilen') tokenize(obj) { |form, attr| inc("Anzahl Muster #{attr}") inc('Anzahl Token') forward(Token.new(form, attr)) } forward(STR_CMD_EOL, @filename) if @filename else forward(obj) end end
tokenize(“Eine Zeile.”) -> [:Eine/WORD:, :Zeile/WORD:, :./PUNC:]
# File lib/lingo/attendee/tokenizer.rb, line 159 def tokenize(textline) case @cont when 'HTML' if textline =~ %r^[^<>]*>/ yield $&, @cont textline, @cont = $', nil else yield textline, @cont return end when 'WIKI' if textline =~ %r^[^\[\]]*\]\]/ yield $&, @cont textline, @cont = $', nil else yield textline, @cont return end when nil if !@tags && textline =~ %r<[^<>]*$/ yield $&, @cont = 'HTML' textline = $` end if !@wiki && textline =~ %r\[\[[^\[\]]*$/ yield $&, @cont = 'WIKI' textline = $` end end until textline.empty? @rules.each { |name, expr| if textline =~ expr yield $&, name if name != 'SPAC' || @space textline = $' break end } end end