Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> разбить строку на токены, нубовский вопрос. 
V
    Опции темы
volatile
Дата 22.2.2011, 01:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: нет
Всего: 85



Python, изучаю недавно (всего несколько дней)
Хочу написать небольшой парсер С++ файлов. *.cpp; *.h
Нужно разбить строку на токены.
Код

fin = open('main.cpp')
for line in fin:
     # вот здесь line надо разбить на токены


упрощенный вариант: пока идут символы A-Z;a-z;0-9;_ считается одним токеном
как встретился другой символ, значит токен кончился.
как это можно организовать.
пока нашел только line.split(...), но там можно только один символ.

PM MAIL   Вверх
spSerg
Дата 22.2.2011, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 22.3.2007

Репутация: 4
Всего: 4



Вообще-то есть штатная батарейка: http://docs.python.org/library/tokenize.html
Только боюсь, для cpp она не очень.
PM   Вверх
volatile
Дата 22.2.2011, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: нет
Всего: 85



spSerg, спасибо. Но этот действительно похоже только для исходников самого пайтона.

Как я понял, нужно писать посимвольный ввод.
Думал на пайтоне можно сделать проще...

PM MAIL   Вверх
spSerg
Дата 23.2.2011, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 22.3.2007

Репутация: 4
Всего: 4



Еще можно попробовать что-то помощнее.
Например, ANTLR генератор парсеров:
http://www.antlr.org/

а тут сама грамматика C++:
http://www.antlr.org/grammar/cpp

Только это решение не на чистом пайтоне получится.

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

Это сообщение отредактировал(а) spSerg - 23.2.2011, 16:10
PM   Вверх
volatile
Дата 24.2.2011, 01:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: нет
Всего: 85



spSerg, спасибо за ссылки.
Но, вероятно, я не совсем корректно сформулировал вопрос.
Упростим задачу. Отвлечемся от токенов и с++.

Чистый пайтон.
Допустим есть строка "abc,def;gty-klp"
Как наиболее простым способом ее разбить на кортеж ("abc", "def", "gty", "klp") ?
Символы разделители допустим могут быть такие: "<=>!&|^+-*/%:;(),~{}[]" 




PM MAIL   Вверх
av0000
Дата 24.2.2011, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.2.2009

Репутация: 1
Всего: 2



В такой постановке - элементарно smile

Код

import re

s = "abc,def;gty-klp"
r = re.compile(r"<=>!&|^+\-*/%:;(),~{}\[\]+") # экранировать минимум знак "минус" и закрывающую квадратную скобку
ret = r.split(s) # тут будут результаты с пустыми строками вместо разделителей
# надо именно кортеж - 
ret2 = tuple([x for x in ret if x]) # а тут мы эти пустые строки "тупо" выкинем :)

print ret2




Это сообщение отредактировал(а) av0000 - 24.2.2011, 11:02
PM MAIL Jabber   Вверх
volatile
Дата 24.2.2011, 23:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: нет
Всего: 85



av0000, в том виде как вы привели вообще не работает
методом тыка удалось установить что еще '+' надо экранировать.
В итоге программку удалось запустить в таком виде:
Код
# -*- coding: windows-1251 -*-
import re
s = "abc,def;gty-klp"
r = re.compile(r"<=>!&|^\+\-/%:;(),~{}\[\]+")
ret = r.split(s) # тут будут результаты с пустыми строками вместо разделителей
ret2 = tuple([x for x in ret if x]) # а тут мы эти пустые строки "тупо" выкинем :)
print ret2

Но она ничего не делает.
выход:
Цитата

('abc,def;gty-klp',)

то есть как была строка так и осталась.
дальше разбираться не стал...

Добавлено через 10 минут и 9 секунд
а, re это - regular expressions?

в любом случае спасибо за наводку, av0000
PM MAIL   Вверх
spSerg
Дата 25.2.2011, 09:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 37
Регистрация: 22.3.2007

Репутация: 4
Всего: 4



Ну не проверил человек. С кем не бывает smile 
В регулярке квадратные скобки забыл.
Код

import re
s = "abc,def;gty-klp"
r = re.compile(r"[<=>!&|^\+\-/%:;(),~{}\[\]]+")
ret = r.split(s) #здесь получится список слов

PM   Вверх
av0000
Дата 25.2.2011, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 26
Регистрация: 11.2.2009

Репутация: 1
Всего: 2



Угу...

Перенабивал, поленившись копировать из консоли, — так не только квадратные скобки, а ещё и "лишнюю" группу "(.*?)" которая давала пустые строки (оттуда и коммент про пустые строки) забыл, вернее "удачно" убрал" ;)

Изначальная строчка была print re.split(r"(*.?)[<=>!&|^+\-*/%:;()~{}[\],]+",s)

В качестве компенсации офф-топика хочу поделиться наблюдением:
Неспешно делаю очередную версию напоминалки об обновлениях на СамИздат-е с парсингом страничек и местами автоматическим конвертированием в .fb2... Так вот, тесты показали, что регекспы в 3-8 раз медленнее аналогичной реализации "руками" через startswith/find/endswith и т.п. Поэтому, если важна скорость обработки - стОит очень внимательно подумать что окажется выгоднее - медленный, "осмысленный" регэксп или 5-30 строк "ручного" кода. Для примера - вот те регекспы. До всякой оптимизации - попробовал "руками" и плюнул.. 
Код

# ================ чистка текста ================
# сравнение скорости...
# ** 3x медленнее
RE_FONT1 = re.compile(ur'<font\s+color="?\#\d{3,6}"?\s*>?|<font\s+color="?\w+"?\s*>|</font>', re.I|re.U|re.S|re.M)
# ** 6x
#RE_RM1 = re.compile(ur"(<[/]?div.*?>)|(<[/]?body.*?>)|(<[/]?html.*?>)|(<[/]?xxx.*?>)|(<i></i>)|(<u></u>)|(<b></b>)", re.I | re.S | re.M | re.U)
# ** 1x (0.21s x 700Kb)
#RE_DD = re.compile(ur"(<dd>)(?:&nbsp;)*\s*(.*?)($\s*^(?=<))", re.I|re.M|re.S|re.U)
# ** 8x
#RE_ONOFF = re.compile(ur"<(\w+)>(.*?)</\1><\1>", re.I|re.M|re.U|re.S)
# ======================================


ЗЫ: Да и в сторону tokenize посмотреть не мешает... для более сложной грамматики, нежели разбивка по разделителям может оказаться проще, а то и быстрее...

Это сообщение отредактировал(а) av0000 - 25.2.2011, 11:42
PM MAIL Jabber   Вверх
volatile
Дата 25.2.2011, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: нет
Всего: 85



spSerg
av0000

Большое спасибо ребята!

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Python: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0751 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.