Reputation: 9816
I am using a code generation tool and I need to convert method calls like this (it's java):
public MyObjectType MyObjectType(){
into a more java-fied version:
public MyObjectType myObjectType(){
I have this working snippet of Scala code that does that:
val pattern = """[\s]+public[\s]+[\w]+[\s]+([\w]+\(\))\{""".r
val tmp = pattern.findAllIn(s).matchData map { m =>
val x = m.group(1).replaceAll("\\(\\)", "\\\\(\\\\)")
s.replaceAll(x, firstLowerCase(x))
}
// if there is no match, return unmodified string,
// otherwise return the only match
val converted = if (tmp.isEmpty) s else tmp.next()
Where s
is one line of code, possible candidate for the transformation.
The function firstLowerCase
is defined as:
def firstLowerCase(s: String): String = {
val (first, rest) = s.splitAt(1)
first.toLowerCase + rest
}
The code above works fine, but I was wondering if it was possible to slim it down a bit (ideally to a single pattern match statement), e.g., by (somehow) removing the explicit conversion of ()
to \(\)
, doing the match and replace in one shot or incorporating the above function in the replacement. I am not a regex expert so maybe this is too much to ask. Ideas?
Upvotes: 2
Views: 1244
Reputation: 38217
This seems to be doing what you need. I've also made the pattern a bit more flexible e.g. in that spaces are allowed before the {
.
import scala.util.matching.Regex
// wingedsubmariner's answer actually has a better pattern
val Pattern = """(public\s+\w+\s+)(\w+)(\s*\(\)\s*\{)""".r
def firstLowerCase(s: String): String = {
val (first, rest) = s.splitAt(1)
first.toLowerCase + rest
}
val lines = List(
"public MyObjectType MyObjectTypeMeth(){",
" public MyObjectType MyObjectTypeMeth(){ ",
"public MyObjectType MyObjectTypeMeth() {",
"public MyObjectType MyObjectTypeMeth () {")
lines.foreach { s =>
val converted = Pattern.replaceAllIn(s, m => {
m.group(1) + firstLowerCase(m.group(2)) + m.group(3)
})
println(converted)
}
output:
public MyObjectType myObjectTypeMeth(){
public MyObjectType myObjectTypeMeth(){
public MyObjectType myObjectTypeMeth() {
public MyObjectType myObjectTypeMeth () {
Upvotes: 1
Reputation: 13667
Try this:
val pattern = """(public\s+\w+\s+)(\w)(?=\w*\(\)\{)""".r
val converted = pattern.replaceAllIn(s, m => m.group(1) + m.group(2).toLowerCase)
replaceAllIn
makes it unnecessary to do a findAllIn
and then go back and do a replaceAll
. We match the beginning part of the pattern, the character we need to lower case, and then handle the rest with a look ahead assertion (we don't need to replace it, only confirm that it is present). The replacement text is the beginning of the pattern and that single character made lowercase, firstLowerCase
isn't needed.
Upvotes: 5