Pythonic способ реализовать токенизатор

Измените имя на name="edible[1]" и так далее. После отправки значения будут в массиве в

Измените имя на [110] и так далее. После отправки значения будут в массиве в [111]. Это можно затем суммировать с помощью array_sum().

POST. Это можно затем суммировать с помощью array_sum().

12
задан mipadi 27 March 2009 в 19:46
поделиться

11 ответов

Python берет, "мы все соглашаемся взрослые" подход к сокрытию информации. Нормально использовать переменные, как будто они были константами и полагают, что пользователи Вашего кода не сделают чего-то глупого.

29
ответ дан 2 December 2019 в 02:49
поделиться

Существует недокументированный класс в re модуль называют re.Scanner. Это очень просто для использования для токенизатора:

import re
scanner=re.Scanner([
  (r"[0-9]+",       lambda scanner,token:("INTEGER", token)),
  (r"[a-z_]+",      lambda scanner,token:("IDENTIFIER", token)),
  (r"[,.]+",        lambda scanner,token:("PUNCTUATION", token)),
  (r"\s+", None), # None == skip token.
])

results, remainder=scanner.scan("45 pigeons, 23 cows, 11 spiders.")
print results

приведет к

[('INTEGER', '45'),
 ('IDENTIFIER', 'pigeons'),
 ('PUNCTUATION', ','),
 ('INTEGER', '23'),
 ('IDENTIFIER', 'cows'),
 ('PUNCTUATION', ','),
 ('INTEGER', '11'),
 ('IDENTIFIER', 'spiders'),
 ('PUNCTUATION', '.')]

Я использовал ре. Сканер для записи довольно изящного синтаксического анализатора формата конфигурации/структурированных данных только в паре сотни строк.

56
ответ дан 2 December 2019 в 02:49
поделиться

"Есть ли лучшая альтернатива просто возврату списка кортежей?"

Нет. Это работает действительно хорошо.

4
ответ дан 2 December 2019 в 02:49
поделиться

Спасибо за Вашу справку я начал объединять эти идеи, и я придумал следующее. Есть ли что-либо ужасно неправильно с этой реализацией (особенно я обеспокоен передачей объекта файла к токенизатору):

class Tokenizer(object):

  def __init__(self,file):
     self.file = file

  def __get_next_character(self):
      return self.file.read(1)

  def __peek_next_character(self):
      character = self.file.read(1)
      self.file.seek(self.file.tell()-1,0)
      return character

  def __read_number(self):
      value = ""
      while self.__peek_next_character().isdigit():
          value += self.__get_next_character()
      return value

  def next_token(self):
      character = self.__peek_next_character()

      if character.isdigit():
          return self.__read_number()
7
ответ дан 2 December 2019 в 02:49
поделиться

Во многих ситуациях, экспорте при парсинге длинных входных потоков, можно найти более полезным реализовать Вас токенизатор как функция генератора. Таким образом, можно легко выполнить итерации по всем маркерам без потребности в большой памяти для создания списка маркеров сначала.

Поскольку генератор видит первоначальное предложение или другие документы онлайн

10
ответ дан 2 December 2019 в 02:49
поделиться

"Есть ли лучшая альтернатива просто возврату списка кортежей?"

Это - подход, используемый "маркировать" модулем для парсинга исходного кода Python. Возврат простого списка кортежей может работать очень хорошо.

2
ответ дан 2 December 2019 в 02:49
поделиться

Я недавно создал токенизатор также и прошел через некоторые Ваши проблемы.

Типы маркера объявляются как "константы", т.е. переменные с именами ALL_CAPS, на уровне модуля. Например,

_INTEGER = 0x0007
_FLOAT = 0x0008
_VARIABLE = 0x0009

и так далее. Я использовал подчеркивание перед именем, чтобы указать, что так или иначе те поля являются "частными" за модуль, но я действительно не знаю, типично ли это или желательно, даже сколько Pythonic. (Кроме того, я, вероятно, угроблю числа в пользу строк, потому что во время отладки они намного более читаемы.)

Маркеры возвращаются как названные кортежами.

from collections import namedtuple
Token = namedtuple('Token', ['value', 'type'])
# so that e.g. somewhere in a function/method I can write...
t = Token(n, _INTEGER)
# ...and return it properly

Я использовал названные кортежи, потому что клиентский код токенизатора (например, синтаксический анализатор) кажется немного более четким при использовании имен (например, token.value) вместо индексов (например, маркер [0]).

Наконец, я заметил, что иногда, особенно пишущий тесты, предпочитаю передавать строку токенизатору вместо объекта файла. Я называю это "читателем" и имею определенный метод, чтобы открыть его и позволить токенизатору получить доступ к нему через тот же интерфейс.

def open_reader(self, source):
    """
    Produces a file object from source.
    The source can be either a file object already, or a string.
    """
    if hasattr(source, 'read'):
        return source
    else:
        from io import StringIO
        return StringIO(source)
2
ответ дан 2 December 2019 в 02:49
поделиться

Когда я запускаю что-то новое в Python, я обычно смотрю сначала на некоторые модули или библиотеки для использования. Существует 90% + шанс, что уже существует что-то доступное.

Для токенизаторов и синтаксических анализаторов это, конечно, так. Вы посмотрели на PyParsing?

1
ответ дан 2 December 2019 в 02:49
поделиться

"Есть ли лучшая альтернатива просто возврату списка кортежей"

Я должен был реализовать токенизатор, но он потребовал более сложного подхода, чем список кортежей, поэтому я реализовал класс для каждого маркера. Можно затем возвратить список экземпляров класса, или если Вы хотите сохранить ресурсы, можно возвратиться, что-то, реализовывая итератор соединяет интерфейсом и генерирует следующий маркер, в то время как Вы прогрессируете в парсинге.

0
ответ дан 2 December 2019 в 02:49
поделиться

Я бы обратился к превосходной Обработке текста в Python Дэвида Мертца

1
ответ дан 2 December 2019 в 02:49
поделиться

Я реализовал токенизатор для C-подобного языка программирования. Я разделил создание токенов на два уровня:

  • сканер поверхности : он фактически считывает текст и использует регулярное выражение, чтобы разделить его только на самые простые токены (операторы , идентификаторы, числа, ...); этот дает кортежи (tokenname, scannedstring, startpos, endpos).
  • a tokenizer : он потребляет кортежи из первого уровня, превращая их в объекты-токены (я думаю, что именованные кортежи тоже подойдут. ). Его цель - обнаружить некоторые дальнодействующие зависимости в потоке токенов, особенно строки (с их открывающими и закрывающими кавычками) и комментарии (с их открывающими и закрывающими лексемами; - да, я хотел сохранить комментарии!) И объединить их в единый жетоны. Результирующий поток объектов токенов затем возвращается потребляющему синтаксическому анализатору.

Оба являются генераторами. Преимущества этого подхода заключались в следующем:

  • Чтение необработанного текста выполняется только самым примитивным способом, с простыми регулярными выражениями - быстро и чисто.
  • Второй уровень уже реализован как примитивный синтаксический анализатор для обнаружения строковых литералов. и комментарии - повторное использование технологии парсеров.
  • Вам не нужно напрягать поверхностный сканер сложными обнаружениями.
  • Но настоящий синтаксический анализатор получает токены на семантическом уровне анализируемого языка (опять же строки, комментарии).

Я вполне счастлив с этим многоуровневым подходом.

с простыми регулярными выражениями - быстро и чисто.
  • Второй уровень уже реализован как примитивный анализатор для обнаружения строковых литералов и комментариев - повторное использование технологии синтаксического анализатора.
  • Вам не нужно напрягать поверхностный сканер сложными обнаружениями.
  • Но настоящий синтаксический анализатор получает токены на семантическом уровне анализируемого языка (снова строки, комментарии).
  • Я вполне счастлив с этим многоуровневым подходом.

    с простыми регулярными выражениями - быстро и чисто.
  • Второй уровень уже реализован как примитивный анализатор для обнаружения строковых литералов и комментариев - повторное использование технологии синтаксического анализатора.
  • Вам не нужно напрягать поверхностный сканер сложными обнаружениями.
  • Но настоящий синтаксический анализатор получает токены на семантическом уровне анализируемого языка (опять же строки, комментарии).
  • Я вполне счастлив с этим многоуровневым подходом.

    1
    ответ дан 2 December 2019 в 02:49
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: