Я следующие последовательности в коде C:замена строки в Python
variable == T_CONSTANT
или
variable != T_CONSTANT
Использование Python, как я могу заменить их на SOME_MACRO(variable)
или !SOME_MACRO(variable)
, соответственно?
Я следующие последовательности в коде C:замена строки в Python
variable == T_CONSTANT
или
variable != T_CONSTANT
Использование Python, как я могу заменить их на SOME_MACRO(variable)
или !SOME_MACRO(variable)
, соответственно?
Очень простой и подверженным ошибкам методом является использование регулярных выражений:
>>> s = "a == T_CONSTANT"
>>> import re
>>> re.sub(r"(\w+)\s*==\s*T_CONSTANT", r"SOME_MACRO(\1)", s)
'SOME_MACRO(a)'
Подобное регулярное выражение можно использовать для !=
части.
ОК, я знаю, что вы уже приняли другой ответ. Тем не менее, я просто не мог не бросить это, потому что ваша проблема часто возникает, и регулярные выражения могут быть не всегда подходящими.
Этот фрагмент кода определяет крошечный ограниченный нерекурсивный Parsing Expression Grammar, который позволяет вам описать то, что вы ищете, с точки зрения серии скомпилированных регулярных выражений, альтернатив (кортежей различных совпадающих строк) и простых строк. Этот формат может быть более удобным, чем регулярное выражение для компьютерного языка, поскольку он похож на формальные спецификации синтаксиса языка. В основном, [varname, ("==", "!="), "T_CONSTANT"]
описывает то, что вы ищете, а функция action()
описывает, что вы хотите сделать, когда найдете ее.
Я включил корпус примера кода «С», чтобы продемонстрировать парсер.
import re
# The @match()@ function takes a parsing specification and a list of
# words and tries to match them together. It will accept compiled
# regular expressions, lists of strings or plain strings.
__matcher = re.compile("x") # Dummy for testing spec elements.
def match(spec, words):
if len(spec) > len(words): return False
for i in range(len(spec)):
if type(__matcher) is type(spec[i]):
if not spec[i].match(words[i]): return False
elif type(()) is type(spec[i]):
if words[i] not in spec[i]: return False
else:
if words[i] != spec[i]: return False
return True
# @parse()@ takes a parsing specification, an action to execute if the
# spec matches and the text to parse. There can be multiple matches in
# the text. It splits and rejoins on spaces. A better tokenisation
# method is left to the reader...
def parse(spec, action, text):
words = text.strip().split()
n = len(spec)
out = []
while(words):
if match(spec, words[:n+1]): out.append(action(words[:n+1])); words = words[n:]
else: out.append(words[0]); words = words[1:]
return " ".join(out)
# This code is only executed if this file is run standalone (so you
# can use the above as a library module...)
if "__main__" == __name__:
# This is a chunk of bogus C code to demonstrate the parser with:
corpus = """\
/* This is a dummy. */
variable == T_CONSTANT
variable != T_CONSTANT
/* Prefix! */ variable != T_CONSTANT
variable == T_CONSTANT /* This is a test. */
variable != T_CONSTANT ; variable == T_CONSTANT /* Note contrived placement of semi. */
x = 9 + g;
"""
# This compiled regular expression defines a legal C/++ variable
# name. Note "^" and "$" guards to make sure the full token is matched.
varname = re.compile("^[A-Za-z_][A-Za-z0-9_]*$")
# This is the parsing spec, which describes the kind of expression
# we're searching for.
spec = [varname, ("==", "!="), "T_CONSTANT"]
# The @action()@ function describes what to do when we have a match.
def action(words):
if "!=" == words[1]: return "!SOME_MACRO(%s)" % words[0]
else: return "SOME_MACRO(%s)" % words[0]
# Process the corpus line by line, applying the parser to each line.
for line in corpus.split("\n"): print parse(spec, action, line)
Вот результат, если вы запустите его:
/* This is a dummy. */
SOME_MACRO(variable)
!SOME_MACRO(variable)
/* Prefix! */ !SOME_MACRO(variable)
SOME_MACRO(variable) /* This is a test. */
!SOME_MACRO(variable) ; SOME_MACRO(variable) /* Note contrived placement of semi. */
x = 9 + g;
Ну что ж, мне было весело! ; -)
Я не вижу, как это было бы более надежным, чем простой регулярная версия? В конце концов, он не использует также синтаксический анализатор C, поэтому он будет делать те же ошибки, например, если макрос находится в комментарии или что-то в этом роде. То, что вы анализируете здесь, является обычной грамматикой (Chomsky-3), поэтому вы должны использовать ... регулярное выражение. –
Спасибо, вы можете дать объяснение? – ABRami
@ABRami: Это очень простой материал. Вы можете использовать [документацию модуля 're'] (http://docs.python.org/library/re.html) в качестве отправной точки для регулярных выражений в Python. Если у вас есть конкретные вопросы, продолжайте и спрашивайте :) –
Спасибо большое, я очень ценю это – ABRami