2012-04-10 4 views
1

Я следующие последовательности в коде C:замена строки в Python

variable == T_CONSTANT 

или

variable != T_CONSTANT 

Использование Python, как я могу заменить их на SOME_MACRO(variable) или !SOME_MACRO(variable), соответственно?

ответ

1

Очень простой и подверженным ошибкам методом является использование регулярных выражений:

>>> s = "a == T_CONSTANT" 
>>> import re 
>>> re.sub(r"(\w+)\s*==\s*T_CONSTANT", r"SOME_MACRO(\1)", s) 
'SOME_MACRO(a)' 

Подобное регулярное выражение можно использовать для != части.

+0

Спасибо, вы можете дать объяснение? – ABRami

+0

@ABRami: Это очень простой материал. Вы можете использовать [документацию модуля 're'] (http://docs.python.org/library/re.html) в качестве отправной точки для регулярных выражений в Python. Если у вас есть конкретные вопросы, продолжайте и спрашивайте :) –

+0

Спасибо большое, я очень ценю это – ABRami

0

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

Этот фрагмент кода определяет крошечный ограниченный нерекурсивный 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; 

Ну что ж, мне было весело! ; -)

+0

Я не вижу, как это было бы более надежным, чем простой регулярная версия? В конце концов, он не использует также синтаксический анализатор C, поэтому он будет делать те же ошибки, например, если макрос находится в комментарии или что-то в этом роде. То, что вы анализируете здесь, является обычной грамматикой (Chomsky-3), поэтому вы должны использовать ... регулярное выражение. –

Смежные вопросы