Разбор в Python: каков наиболее эффективный способ подавления / нормализации строк? - PullRequest
0 голосов
/ 11 мая 2009

Я анализирую исходный файл и хочу "подавить" строки. Под этим я подразумеваю преобразование каждой строки, такой как «bla bla bla + / *», в нечто вроде «строки», которая является детерминированной и не содержит никаких символов, которые могут запутать мой синтаксический анализатор, потому что меня не волнует значение строки. Одной из проблем здесь является форматирование строки с использованием, например, "% s", смотрите мое замечание по этому поводу ниже.

Возьмем, к примеру, следующий псевдокод, который может быть содержимым файла, который я анализирую. Предположим, что строки начинаются с ", а экранирование" символа выполняется "":

print(i)
print("hello**")
print("hel"+"lo**")
print("h e l l o "+
"hello\n")
print("hell""o")
print(str(123)+"h e l l o")
print(uppercase("h e l l o")+"g o o d b y e")

Должен быть преобразован в следующий результат:

print(i)
print("string")
print("string"+"string")
print("string"
"string")
print("string")
print(str(123)+"string")
print(uppercase("string")+"string")

В настоящее время я рассматриваю это как особый случай в коде (то есть обнаружение начала строки и «ручной» запуск до ее конца с несколькими дополнительными случаями в пути). Если есть функция библиотеки Python, которую я могу использовать, или хорошее регулярное выражение, которое может сделать мой код более эффективным, это было бы здорово.

Несколько замечаний:

  • Мне бы хотелось, чтобы символ «начало строки» был переменной, например "против".
  • На данном этапе я не разбираю код Python, но планирую, и там проблема, очевидно, становится более сложной, поскольку строки могут начинаться несколькими способами и должны заканчиваться способом, соответствующим началу. Я не пытаюсь разобраться с этим прямо сейчас, но если есть какие-то хорошо зарекомендовавшие себя лучшие практики, я бы хотел об этом узнать.
  • В этом «подавлении» меня больше всего беспокоит случай форматирования строк с подобными «% s», которые являются значимыми токенами. Я в настоящее время не имею дело с этим и не полностью продумал это, но если у кого-то из вас есть предложения о том, как справиться с этим, это было бы здорово. Обратите внимание, что меня не интересует конкретный тип или форматирование токенов в строке, мне достаточно знать, что в строке есть токены (сколько). Заметьте, что здесь может быть важно: мой токенизатор не является вложенным, потому что моя цель довольно проста (я ничего не собираю ...).
  • Я не совсем уверен насчет экранирования символа стартовой строки. Что бы вы сказали, как это распространено в большинстве языков программирования? Достаточно ли предположения о двойном вхождении (например, "") или любом наборе из двух символов (например, \ ")? Нужно ли рассматривать другие случаи (например, языки Java, C / C ++, PHP, C #) )

Ответы [ 3 ]

4 голосов
/ 11 мая 2009

Вариант 1. Для очистки исходного кода Python попробуйте встроенный модуль tokenize . Он может правильно найти строки и другие токены в любом исходном файле Python.

Вариант 3: Используйте pygments с выводом HTML и замените что-нибудь синим (и т. Д.) На "string". pygments поддерживает несколько десятков языков.

Вариант 2: Для большинства языков вы можете создать пользовательскую замену регулярного выражения. Например, следующее очищает исходный код Python (но он не работает, если исходный файл содержит """ или '''):

import re
sanitized = re.sub(r'(#.*)|\'(?:[^\'\\]+|\\.)*\'|"(?:[^"\\]+|\\.)*"',
    lambda match: match.group(1) or '"string"', source_code)

Приведенное выше регулярное выражение работает правильно, даже если строки содержат обратную косую черту (\", \\, \n, \\, \\", \\\" и т. Д. Все работают нормально).

Когда вы строите свое регулярное выражение, убедитесь, что совпадают комментарии (чтобы ваша замена регулярного выражения не касалась строк внутри комментариев) и литералов регулярных выражений (например, в Perl, Ruby и JavaScript), и обратите внимание, что вы сопоставляете обратную косую черту и символы новой строки правильно (например, в Perl и Ruby строка может содержать символ новой строки).

1 голос
/ 11 мая 2009

Используйте выделенный парсер для каждого языка - тем более что люди уже сделали эту работу для вас. Большинство из упомянутых вами языков имеют грамматику.

1 голос
/ 11 мая 2009

Нигде не упоминается, что вы используете подход, использующий лексер и парсер . Если на самом деле вы этого не сделаете, посмотрите, например, на. модуль tokenize (что, вероятно, вам и нужно) или сторонний модуль PLY (Python Lex-Yacc). Ваша проблема нуждается в систематическом подходе, и эти инструменты (и другие) обеспечивают ее.

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

...