/*
* Copyright (C) 2015 たんらる
*/
package fourthline.mmlTools.optimizer;
import fourthline.mmlTools.core.MMLTokenizer;
/**
* {@code "<c> -> b+"} と {@code ">b< -> c-"} を使った最適化を行います.
*/
public final class BpCmOptimizer implements MMLStringOptimizer.Optimizer {
private enum BpCmState {
NONE {
/**
* "<" -> B1
* ">" -> C1
*/
@Override
public BpCmState nextStatus(String token) {
if (token.equals("<")) {
return B1;
} else if (token.equals(">")) {
return C1;
}
return NONE;
}
},
B1 {
/**
* "<b" -> B2
*/
@Override
public BpCmState nextStatus(String token) {
if (isNoteWithoutR(token)) {
if (MMLTokenizer.noteNames(token)[0].toLowerCase().equals("b")) {
return B2;
}
return NONE;
} else if (token.equals(">")) {
return C1;
}
return B1;
}
},
B2 {
/**
* "<b>" -> B3
*/
@Override
public BpCmState nextStatus(String token) {
if (isNoteWithoutR(token)) {
return NONE;
} else if (token.equals(">")) {
return B3;
}
return B2;
}
},
B3 {
/**
* "<b>" -> "c-"
*/
@Override
public String optimize(StringBuilder sb) {
sb.deleteCharAt( sb.lastIndexOf("<") );
sb.deleteCharAt( sb.lastIndexOf(">") );
String s = sb.toString()
.replace("b", "c-")
.replace("B", "C-");
return s;
}
},
C1 {
/**
* ">c" -> C2
*/
@Override
public BpCmState nextStatus(String token) {
if (isNoteWithoutR(token)) {
if (MMLTokenizer.noteNames(token)[0].toLowerCase().equals("c")) {
return C2;
}
return NONE;
} else if (token.equals("<")) {
return B1;
}
return C1;
}
},
C2 {
/**
* ">c<" -> C3
*/
@Override
public BpCmState nextStatus(String token) {
if (isNoteWithoutR(token)) {
return NONE;
} else if (token.equals("<")) {
return C3;
}
return C2;
}
},
C3 {
/**
* ">c<" -> "b+"
*/
@Override
public String optimize(StringBuilder sb) {
sb.deleteCharAt( sb.lastIndexOf("<") );
sb.deleteCharAt( sb.lastIndexOf(">") );
String s = sb.toString()
.replace("c", "b+")
.replace("C", "B+");
return s;
}
};
public BpCmState nextStatus(String token) {
return NONE;
}
public String optimize(StringBuilder sb) {
throw new AssertionError();
}
private static boolean isNoteWithoutR(String token) {
char firstC = Character.toLowerCase( token.charAt(0) );
if ("abcdefg".indexOf(firstC) >= 0) {
return true;
}
return false;
}
}
private StringBuilder builder = new StringBuilder();
private StringBuilder optBuilder = new StringBuilder();
private BpCmState state = BpCmState.NONE;
@Override
public void nextToken(String token) {
BpCmState prevStatus = state;
state = state.nextStatus(token);
if (MMLStringOptimizer.getDebug()) {
System.out.println(prevStatus + " - > " + state + ": " + token);
}
if (state == BpCmState.NONE) {
builder.append(optBuilder);
optBuilder.setLength(0);
builder.append(token);
} else {
optBuilder.append(token);
if ( (state == BpCmState.B3) || (state == BpCmState.C3) ) {
builder.append( state.optimize( optBuilder ));
optBuilder.setLength(0);
state = state.nextStatus(token);
}
}
}
@Override
public String getMinString() {
builder.append(optBuilder);
optBuilder.setLength(0);
return builder.toString();
}
}