private String chooseAlternations ( final String expression ) { StrBuilder sb = new StrBuilder ( expression ) ; int i = 0 ; // Loop until an unescaped pipe symbol appears. while ( UNESCAPED_PIPE_PATTERN . matcher ( sb . toString ( ) ) . find ( ) ) { for ( ; i < sb . length ( ) ; ++ i ) { if ( sb . charAt ( i ) == ' ' ) { if ( sb . charAt ( i - 1 ) == ' ' ) { // escapet continue ; } int start = i ; // Backtrack until an opening bracket is found // to limit the context of alternatives. for ( int closingCount = 0 ; start >= 0 ; -- start ) { char c = sb . charAt ( start ) ; if ( c == ' ' ) { if ( closingCount == 0 ) { break ; } -- closingCount ; } else if ( c == ' ' ) { ++ closingCount ; } } if ( start >= 0 ) { // If an opening brace was found // search for a closing bracket. int end = i ; for ( int openingCount = 0 ; end < sb . length ( ) ; ++ end ) { char c = sb . charAt ( end ) ; if ( c == ' ' ) { ++ openingCount ; } else if ( c == ' ' ) { if ( openingCount == 0 ) { break ; } -- openingCount ; } } String alternative = random . getBoolean ( ) ? sb . substring ( start + 1 , i ) : sb . substring ( i + 1 , end ) ; sb . replace ( start , end + 1 , alternative ) ; i = start + alternative . length ( ) ; break ; } String alternative = random . getBoolean ( ) ? sb . substring ( 0 , i ) : sb . substring ( i + 1 ) ; sb . replace ( 0 , sb . length ( ) + 1 , alternative ) ; break ; } } } return sb . toString ( ) ; }
Resolves alternations by randomly choosing one at a time and adapting the pattern accordingly