Просто включите предыдущий пробел в шаблон замены, то есть _extends_${super_class}
и _implements_${interfaces}
можно заменить пустыми строками (я использовал подчеркивание, чтобы сделать его более явным).
...${class_name}_extends_${super_class}_implements_${interfaces}_{
\_____________________/\_______________________/
optional optional
Один из способов осмыслить проблему состоит в том, чтобы рассматривать пространство как то, что оно есть: разделитель. Аналогично, ваша проблема выглядит примерно так:
У вас есть A
, B
и C
, которые могут появляться в этом порядке, за исключением того, что B
и C
являются необязательными. Вы хотите перечислить их как кортеж, то есть, окруженные (
и )
, разделенные ,
. То есть это все допустимые кортежи:
(A,B,C)
(A,B)
(A,C)
(A)
Теперь более очевидно, что вы можете прикрепить предыдущую запятую к B
и C
. Таким образом, кортежи состоят из 4 частей (A
+ ,B
+ ,C
+ )
, причем средние два являются необязательными - таким образом, вы не получите никаких дополнительных разделителей.
Примечание: по причинам, которые включают более простое упрощение генерации кода, некоторые грамматики допускают конечные запятые в конце списка, как предложения переменной длины. Например, в Java это допустимый инициализатор массива:
int[] arr = new int[] { 1, 2, }
^
perfectly okay!
Для этих видов грамматики более целесообразно вместо этого добавлять разделитель ПОСЛЕ каждой части. Вы можете сделать процесс генерации кода более сложным, чтобы он никогда не создавал запятую (возможно, потому что вам просто не нравится его видеть), но тот факт, что многие грамматики позволяют им как-то оправдывать использование этого упрощения "ярлык".