私はCコードで次のシーケンスを持っています:
variable == T_CONSTANT
また
variable != T_CONSTANT
SOME_MACRO(variable)
Python を使用して、これらをそれぞれまたはで置き換えるにはどうすれば!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)'
この部分には、同様の正規表現を使用できます!=
。
OK、あなたはすでに他の答えを受け入れていることを知っています。ただし、あなたの問題は頻繁に発生するものであり、正規表現が常に適切であるとは限らないため、これを捨てずにはいられませんでした。
このコードのチャンクは、一連のコンパイルされた正規表現、代替 (さまざまな一致文字列のタプル)、および単純な文字列の観点から、検索対象を記述することができる小さな限定された非再帰構文解析式文法を定義します。この形式は、言語の構文の正式な仕様に似ているため、コンピューター言語の正規表現よりも便利です。基本的に、[varname, ("==", "!="), "T_CONSTANT"]
探しているものをaction()
説明し、機能は見つけたときに何をしたいかを説明します。
パーサーを説明するために、サンプルの「C」コードのコーパスを含めました。
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;
いやあ、楽しかったです!; - )