Source code for woob.tools.tokenizer
# Copyright(C) 2014 Oleg Plakhotniuk
#
# This file is part of woob.
#
# woob is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# woob is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with woob. If not, see <http://www.gnu.org/licenses/>.
import re
__all__ = ['ReTokenizer']
[docs]class ReTokenizer:
"""
Simple regex-based tokenizer (AKA lexer or lexical analyser).
Useful for PDF statements parsing.
1. There's a lexing table consisting of type-regex tuples.
2. Lexer splits text into chunks using the separator character.
3. Text chunk is sequentially matched against regexes and first
successful match defines the type of the token.
Check out test() function below for examples.
"""
def __init__(self, text, sep, lex):
self._lex = lex
self._tok = [ReToken(lex, chunk) for chunk in text.split(sep)]
[docs] def tok(self, index):
if 0 <= index < len(self._tok):
return self._tok[index]
else:
return ReToken(self._lex, eof=True)
[docs] def simple_read(self, token_type, pos, transform=lambda v: v):
t = self.tok(pos)
is_type = getattr(t, 'is_%s' % token_type)()
return (pos+1, transform(t.value())) if is_type else (pos, None)
class ReToken:
def __init__(self, lex, chunk=None, eof=False):
self._lex = lex
self._eof = eof
self._value = None
self._type = None
if chunk is not None:
for type_, regex in self._lex:
m = re.match(regex, chunk, flags=re.UNICODE)
if m:
self._type = type_
if len(m.groups()) == 1:
self._value = m.groups()[0]
elif m.groups():
self._value = m.groups()
else:
self._value = m.group(0)
break
def is_eof(self):
return self._eof
def value(self):
return self._value
def __getattr__(self, name):
if name.startswith('is_'):
return lambda: self._type == name[3:]
raise AttributeError()