Class: Lingo::Attendee::Tokenizer

Inherits:
Lingo::Attendee show all
Defined in:
lib/lingo/attendee/tokenizer.rb

Overview

– 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 einer Programmkonstanten hinterlegt. 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.

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

++

Constant Summary collapse

ALNUM =
"(?:#{CHAR}|#{DIGIT})"
PROTO =
'(?:news|https?|ftps?)://'
RULES =
[
  [TA_SPACE,
    /^\s+/],
  [TA_WIKI,
    /^=+.+=+|^__[A-Z]+__/],
  [TA_NUMBER,
    /^[+-]?(?:\d{4,}|\d{1,3}(?:\.\d{3,3})*)(?:\.|(?:,\d+)?%?)/],
  [TA_URL,
    /^(?:www\.|mailto:|#{PROTO}|\S+?[._]\S+?@\S+?\.)[^\s<>]+/],
  [TA_ABBREVIATION,
    /^(?:(?:(?:#{CHAR})+\.)+)(?:#{CHAR})+/],
  [TA_WORD,
    /^#{ALNUM}(?:-*#{ALNUM})*/],
  [TA_PUNCTUATION,
    /^[!,.:;?¡¿]+/]
]
OTHER =
[
  [TA_OTHER,
    /^[-"$#%&'()*+\/<=>@\[\\\]^_{|}~¢£¤¥¦§¨©«¬®¯°±²³´¶·¸¹»¼½¾×÷„“–]/],
  [TA_HELP,
    /^\S+/]
]
NESTS =
{
  TA_HTML               => ['<',   '>'],
  TA_WIKI + ':VARIABLE' => ['{{{', '}}}'],
  TA_WIKI + ':TEMPLATE' => ['{{',  '}}'],
  TA_WIKI + ':LINK_INT' => ['[[',  ']]'],
  TA_WIKI + ':LINK_EXT' => [/^\[\s*#{PROTO}/, ']']
}

Constants inherited from Lingo::Attendee

DEFAULT_SKIP, TERMINALS

Constants included from Language

Language::CHAR_PUNCT, Language::LA_SORTORDER, Language::TA_ABBREVIATION, Language::TA_HELP, Language::TA_HTML, Language::TA_NUMBER, Language::TA_OTHER, Language::TA_PUNCTUATION, Language::TA_SKIP, Language::TA_SPACE, Language::TA_URL, Language::TA_WIKI, Language::TA_WORD, Language::WA_COMPOUND, Language::WA_IDENTIFIED, Language::WA_MULTIWORD, Language::WA_SEQUENCE, Language::WA_UNKMULPART, Language::WA_UNKNOWN, Language::WA_UNSET

Instance Attribute Summary

Attributes inherited from Lingo::Attendee

#lingo, #subscribers

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Lingo::Attendee

#command, #forward, #initialize

Constructor Details

This class inherits a constructor from Lingo::Attendee

Class Method Details

.append(*rules) ⇒ Object



145
146
147
# File 'lib/lingo/attendee/tokenizer.rb', line 145

def append(*rules)
  _insert(-1, rules)
end

.delete(*names) ⇒ Object



133
134
135
# File 'lib/lingo/attendee/tokenizer.rb', line 133

def delete(*names)
  names.map { |name| rules(name).each { |rule| RULES.delete(rule) } }
end

.insert(*rules) ⇒ Object



141
142
143
# File 'lib/lingo/attendee/tokenizer.rb', line 141

def insert(*rules)
  _insert(0, rules)
end

.insert_after(name, *rules) ⇒ Object



153
154
155
# File 'lib/lingo/attendee/tokenizer.rb', line 153

def insert_after(name, *rules)
  _insert_name(name, rules, -1)
end

.insert_before(name, *rules) ⇒ Object



149
150
151
# File 'lib/lingo/attendee/tokenizer.rb', line 149

def insert_before(name, *rules)
  _insert_name(name, rules, 0)
end

.replace(name, expr = nil) ⇒ Object



137
138
139
# File 'lib/lingo/attendee/tokenizer.rb', line 137

def replace(name, expr = nil)
  rules(name).each { |rule| rule[1] = expr || yield(*rule) }
end

.rule(name) ⇒ Object



125
126
127
# File 'lib/lingo/attendee/tokenizer.rb', line 125

def rule(name)
  RULES.assoc(name)
end

.rules(name = nil) ⇒ Object



129
130
131
# File 'lib/lingo/attendee/tokenizer.rb', line 129

def rules(name = nil)
  name ? RULES.select { |rule,| rule == name } : RULES.map(&:first)
end

Instance Method Details

#control(cmd, filename = nil) ⇒ Object



202
203
204
205
206
207
208
209
# File 'lib/lingo/attendee/tokenizer.rb', line 202

def control(cmd, filename = nil, *)
  case cmd
    when :FILE then reset(filename)
    when :LIR  then reset(nil, nil)
    when :EOL  then @linenum += 1 if @linenum
    when :EOF  then @override.clear; @nest.clear
  end
end

#initObject



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/lingo/attendee/tokenizer.rb', line 171

def init
  @space = get_key('space', false)
  @tags  = get_key('tags',  false)
  @wiki  = get_key('wiki',  false)

  @skip_tags = get_ary('skip-tags', '', :downcase)
  @tags = true unless @skip_tags.empty?

  skip = []
  skip << TA_HTML unless @tags
  skip << TA_WIKI unless @wiki

  [@rules = RULES.dup, @nests = NESTS.dup].each { |hash|
    hash.delete_if { |name, _| skip.include?(Token.clean(name)) }
  }

  @override, @nest, nest_re = [], [], []

  @nests.each { |name, re|
    re.map!.with_index { |r, i| r.is_a?(Regexp) ?
      r : /^#{'.*?' if i > 0}#{Regexp.escape(r)}/ }

    nest_re << "(?<#{name}>#{Regexp.new(
      re[0].source.sub(/^\^/, ''), re[0].options)})"
  }

  @nest_re = /^(?<_>.*?)(?:#{nest_re.join('|')})/

  reset
end

#process(line, offset) ⇒ Object



211
212
213
214
215
# File 'lib/lingo/attendee/tokenizer.rb', line 211

def process(line, offset)
  @offset = offset
  tokenize(line)
  command(:EOL, @filename) if @filename
end