String replacement problem
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.
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.
Two options:
One: Change your template:
public ${class_type} ${class_name}${super_block}${interfaces_block} {
${class_body}
}
...and always replace ${super_block}
and ${interfaces_block}
— either with the " extends SuperClass" (note the space at the front but not at the end) or with a blank string. (Similarly, the interfaces block would be " implements Foo" [again a space at the front] or a blank.)
Two: Be sure to include the space on the front when doing your replacement (edit: as Amir suggested). But this will get tricky when you deal with multiple blocks like both super and interfaces.
(Side note: Your quoted template has two spaces after the interfaces bit before the opening {
, which contributes to the problem.)
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".
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.
If you want a more powerful solution you could use an existing template engine like velocity or freemarker.
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.
精彩评论