class Lingo::Attendee::Tokenizer

Der Tokenizer zerlegt eine Textzeile in einzelne Token. Dies ist notwendig, damit nachfolgende Attendees die Textdatei häppchenweise verarbeiten können.

Mögliche Verlinkung

Erwartet

Daten des Typs String (Textzeilen) z.B. von TextReader

Erzeugt

Daten des Typs Token z.B. für Abbreviator, Wordsearcher

Parameter

Kursiv dargestellte Parameter sind optional (ggf. mit Angabe der Voreinstellung). Alle anderen Parameter müssen zwingend angegeben werden.

in

siehe allgemeine Beschreibung des Attendee.

out

siehe allgemeine Beschreibung des Attendee

Konfiguration

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.

Generierte Kommandos

Damit der nachfolgende Datenstrom einwandfrei verarbeitet werden kann, generiert der Tokenizer Kommandos, die mit in den Datenstrom eingefügt werden.

*EOL(<dateiname>)

Kennzeichnet das Ende einer Textzeile, da die Information ansonsten

für nachfolgende Attendees verloren wäre.

Beispiele

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')

Protected Instance Methods

control(cmd, param) click to toggle source
# 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
init() click to toggle source
# 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
process(obj) click to toggle source
# 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

Private Instance Methods

tokenize(textline) { |$&, cont| ... } click to toggle source

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