views:

104

answers:

6

I want to provide some template for a code generator I am developing. A typical pattern for class is :

public ${class_type} ${class_name} extends ${super_class} implements ${interfaces} {

${class_body}

}

Problem is if super_class is blank or interfaces. I replace extends ${super_class} with empty string. But I get extra spaces. So a class with no super_class and interfaces end up like :

public class Foo    {  //see the extra spaces before {?

${class_body}

}

I know I can replace multiple spaces with single, but is there any better approach?

EDIT : I received some good answers, but it is not addressing the issue. I cannot specify the template, users will set it. Otherwise, what is the point? What if they like to to have :

public ${class_type} ${class_name} extends ${super_class} 
                                   implements ${interfaces} {

${class_body}

}

I guess I can always remove all white spaces between extends ${super_class} and implements ${interfaces} when either one is blank. It will still not be perfect but will be better.

+2  A: 

Include the preceding space in the string " extends ${super_class}" etc., so when you'll insert an empty string, it will not produce spaces at all.

Edit: obviously, you should remove the whitespaces between the strings in addition the the above fix.

Amir Rachum
+2  A: 
T.J. Crowder
+1  A: 

Just include the preceding space in your replacement pattern, i.e. _extends_${super_class} and _implements_${interfaces} can be replaced with empty strings (I used underscores to make it more explicit).

...${class_name}_extends_${super_class}_implements_${interfaces}_{
                \_____________________/\_______________________/
                    optional               optional

One way to think about the problem is to consider the space as what it is: a delimiter. Analogously, your problem is something like this:

You have A, B, and C that can appear in that order, except B and C are optional. You want to list them as a tuple, i.e. surrounded by ( and ), separated by ,. That is, these are all the valid tuples:

(A,B,C)
(A,B)
(A,C)
(A)

Now it's more obvious that you can attach the preceding comma to B and C. That is, the tuples consist of 4 parts (A + ,B + ,C + ), with the middle two being optional -- that way you don't get any extra delimiters.


Note: for reasons that include simpler facilitation of code generation, some grammars allow trailing commas at the end of variable-length list-like sentences. For example, in Java, this is a valid array initializer:

int[] arr = new int[] { 1, 2, }
                            ^
                           perfectly okay!

For these kinds of grammars, it makes more sense to attach the delimiter AFTER each part instead. You can make your code generation more complicated so that it doesn't ever produce trailing comma (maybe because you just don't like to see one), but the fact that lots of grammars do allow them sort of justify the use of this simplifying "shortcut".

polygenelubricants
Isn't that exactly what Amir said several minutes earlier? (http://stackoverflow.com/questions/2565335/string-replacement-problem/2565348#2565348)
T.J. Crowder
My internet is slow and unreliable, what can I do. You should've seen that one time I accidentally triple-posted an answer... that all have the same typo.
polygenelubricants
A: 

If you want a more powerful solution you could use an existing template engine like velocity or freemarker.

Karussell
A: 

I would add some way to represent options:

public ${class_type} ${class_name} [extends ${super_class} ][implements ${interfaces} ]{
    ${class_body}
}

So in stead of removing spaces, I'd not even include the spaces if the user doesn't specify an inheritance relation.

NomeN
+1  A: 

A good way will be to write a that blanks out a keyword with empty string and gobbles up the space upto the next keyword. The method signature will be :

void blankKeyword(String content, String keyword, String next);

It should not be too difficult to write.

javaguy