2

I'm working on a cocos2dx project and recently we updated to the latest version of cocos2dx, this introduced a number of warnings which I'm cleaning up.

I have a lot of code like:

CCPoint somePoint = ccpAdd(this->getPosition(), _someRandomOffset);

The method ccpAdd is deprecated, in favour of the + operator, I want to replace such instances. I've tried searching on google, but I can't find out how to extract two strings using sed and build them back together.

CCPoint somePoint = this->getPosition() + _someRandomOffset;

My question is, how can I automate this replacement using some script against my source files?

Bonus points if the sed command can handle nested ccpAdd commands, like:

CCPoint somePoint = ccpAdd(this->getPosition(), ccpAdd(one, two));

Or maybe sed is the wrong tool for the job?

jonynz
  • 444
  • 3
  • 9
  • did you write your codes in some IDE? it would be safer to use its refactory feature. e.g your codes could be `...=ccpAdd(..);another statement without newline;` or `...=ccpAdd(func(func2(a,b),x),ccpAdd(foo,bar));` – Kent Sep 12 '13 at 07:58
  • I'm using Xcode... I'll take a look – jonynz Sep 12 '13 at 08:01
  • no go, looks like XCode only refactors C or objective C – jonynz Sep 12 '13 at 08:23

3 Answers3

1

I think

sed 's/ccpAdd(\(.*\),\(.*\))/\1+\2/g'

does the trick.

This will however not work for nested occurrences, and will produce strange results for multiple occurrences of the pattern on a single line.

Unfortunately, sed doesn't have non-greedy operators, so the second problem must be solved by switching to another tool, say perl:

perl -pe 's|ccpAdd\((.*?),(.*?)\)|\1 + \2|g'

To get the nesting right, you can just re-run the same perl command several times until there are no more matches (this works because of the non-greedy operators).

Community
  • 1
  • 1
Rody Oldenhuis
  • 37,726
  • 7
  • 50
  • 96
1

An altenative in using the module pyparsing with recursivity:

Assuming content of infile as:

CCPoint somePoint = ccpAdd(this->getPosition(), _someRandomOffset);
CCPoint somePoint = ccpAdd(this->getPosition(), ccpAdd(one, two));

And script.py as:

from pyparsing import *

parser = Forward()
parser << Literal('ccpAdd').suppress() \
    + Literal('(').suppress() \
    + ( parser | OneOrMore(CharsNotIn(',')) ) \
    + Literal(',').suppress() \
    + ( parser | OneOrMore(CharsNotIn(',)')) ) \
    + Literal(')').suppress()

parser.setParseAction(lambda t: ' + '.join(t))

with open('infile', 'r') as f:
    for line in f:
        r = parser.transformString(line)
        print(r, end='')

Run it like:

python3 script.py

That yields:

CCPoint somePoint = this->getPosition() +  _someRandomOffset;
CCPoint somePoint = this->getPosition() + one +  two;
Birei
  • 35,723
  • 2
  • 77
  • 82
  • @jonynz: Glad to read that, and thank you for the confirmation. I'm not used to this kind of parsing and it's fine to see that can be useful for someone. – Birei Sep 12 '13 at 10:55
-1

What I would do is to use

sed 's/regex to match the old string/new string/'

and then write it to a file. so it would be something like this:

sed 's/regex to match the old string/new string/' > file

and ofcourse to provide sed with input just redirect the standard output of cat:

cat thefile.txt | sed ...
Kokozaurus
  • 639
  • 7
  • 22
  • I would suggest you remove this answer before you get downvotes... it doesn't answer the question. – Kent Sep 12 '13 at 08:03
  • Yeah, many cases of ccpAdd use different variables, like ccpAdd(layer->getPosition(), offset), and ccpAdd(center, offVect), so it isn't generic enough – jonynz Sep 12 '13 at 08:04
  • i mean his answer isn't generic, but regex, yeah that will work, but I don't understand how to pull out the strings 1 and 2 (separated by the comma) – jonynz Sep 12 '13 at 08:05
  • 1
    The "Grouping and back-references in sed" section here: http://www.thegeekstuff.com/2009/10/unix-sed-tutorial-advanced-sed-substitution-examples/ would help you for that. – Kokozaurus Sep 12 '13 at 08:26