in lucene/benchmark/src/java/org/apache/lucene/benchmark/byTask/utils/Algorithm.java [48:293]
public Algorithm(PerfRunData runData) throws Exception {
Config config = runData.getConfig();
taskPackages = initTasksPackages(config);
String algTxt = config.getAlgorithmText();
sequence = new TaskSequence(runData, null, null, false);
TaskSequence currSequence = sequence;
PerfTask prevTask = null;
StreamTokenizer stok = new StreamTokenizer(new StringReader(algTxt));
stok.commentChar('#');
stok.eolIsSignificant(false);
stok.quoteChar('"');
stok.quoteChar('\'');
stok.ordinaryChar('/');
stok.ordinaryChar('(');
stok.ordinaryChar(')');
boolean colonOk = false;
boolean isDisableCountNextTask = false; // only for primitive tasks
currSequence.setDepth(0);
while (stok.nextToken() != StreamTokenizer.TT_EOF) {
switch (stok.ttype) {
case StreamTokenizer.TT_WORD:
String s = stok.sval;
Constructor<? extends PerfTask> cnstr =
taskClass(config, s).asSubclass(PerfTask.class).getConstructor(PerfRunData.class);
PerfTask task = cnstr.newInstance(runData);
task.setAlgLineNum(stok.lineno());
task.setDisableCounting(isDisableCountNextTask);
isDisableCountNextTask = false;
currSequence.addTask(task);
if (task instanceof RepSumByPrefTask) {
stok.nextToken();
String prefix = stok.sval;
if (prefix == null || prefix.isEmpty()) {
throw new Exception("named report prefix problem - " + stok);
}
((RepSumByPrefTask) task).setPrefix(prefix);
}
// check for task param: '(' someParam ')'
stok.nextToken();
if (stok.ttype != '(') {
stok.pushBack();
} else {
// get params, for tasks that supports them - allow recursive parenthetical expressions
stok.eolIsSignificant(true); // Allow params tokenizer to keep track of line number
StringBuilder params = new StringBuilder();
stok.nextToken();
if (stok.ttype != ')') {
int count = 1;
BALANCED_PARENS:
while (true) {
switch (stok.ttype) {
case StreamTokenizer.TT_NUMBER:
{
params.append(stok.nval);
break;
}
case StreamTokenizer.TT_WORD:
{
params.append(stok.sval);
break;
}
case StreamTokenizer.TT_EOF:
{
throw new RuntimeException("Unexpected EOF: - " + stok);
}
case '"':
case '\'':
{
params.append((char) stok.ttype);
// re-escape delimiters, if any
params.append(
stok.sval.replaceAll("" + (char) stok.ttype, "\\\\" + (char) stok.ttype));
params.append((char) stok.ttype);
break;
}
case '(':
{
params.append((char) stok.ttype);
++count;
break;
}
case ')':
{
if (--count >= 1) { // exclude final closing parenthesis
params.append((char) stok.ttype);
} else {
break BALANCED_PARENS;
}
break;
}
default:
{
params.append((char) stok.ttype);
}
}
stok.nextToken();
}
}
stok.eolIsSignificant(false);
String prm = params.toString().trim();
if (prm.length() > 0) {
task.setParams(prm);
}
}
// ---------------------------------------
colonOk = false;
prevTask = task;
break;
default:
char c = (char) stok.ttype;
switch (c) {
case ':':
if (!colonOk) throw new Exception("colon unexpected: - " + stok);
colonOk = false;
// get repetitions number
stok.nextToken();
if ((char) stok.ttype == '*') {
((TaskSequence) prevTask).setRepetitions(TaskSequence.REPEAT_EXHAUST);
} else {
if (stok.ttype != StreamTokenizer.TT_NUMBER) {
throw new Exception("expected repetitions number or XXXs: - " + stok);
} else {
double num = stok.nval;
stok.nextToken();
if (stok.ttype == StreamTokenizer.TT_WORD && stok.sval.equals("s")) {
((TaskSequence) prevTask).setRunTime(num);
} else {
stok.pushBack();
((TaskSequence) prevTask).setRepetitions((int) num);
}
}
}
// check for rate specification (ops/min)
stok.nextToken();
if (stok.ttype != ':') {
stok.pushBack();
} else {
// get rate number
stok.nextToken();
if (stok.ttype != StreamTokenizer.TT_NUMBER)
throw new Exception("expected rate number: - " + stok);
// check for unit - min or sec, sec is default
stok.nextToken();
if (stok.ttype != '/') {
stok.pushBack();
((TaskSequence) prevTask).setRate((int) stok.nval, false); // set rate per sec
} else {
stok.nextToken();
if (stok.ttype != StreamTokenizer.TT_WORD)
throw new Exception("expected rate unit: 'min' or 'sec' - " + stok);
String unit = stok.sval.toLowerCase(Locale.ROOT);
if ("min".equals(unit)) {
((TaskSequence) prevTask).setRate((int) stok.nval, true); // set rate per min
} else if ("sec".equals(unit)) {
((TaskSequence) prevTask).setRate((int) stok.nval, false); // set rate per sec
} else {
throw new Exception("expected rate unit: 'min' or 'sec' - " + stok);
}
}
}
colonOk = false;
break;
case '{':
case '[':
// a sequence
// check for sequence name
String name = null;
stok.nextToken();
if (stok.ttype != '"') {
stok.pushBack();
} else {
name = stok.sval;
if (stok.ttype != '"' || name == null || name.isEmpty()) {
throw new Exception("sequence name problem - " + stok);
}
}
// start the sequence
TaskSequence seq2 = new TaskSequence(runData, name, currSequence, c == '[');
currSequence.addTask(seq2);
currSequence = seq2;
colonOk = false;
break;
case '&':
if (currSequence.isParallel()) {
throw new Exception("Can only create background tasks within a serial task");
}
stok.nextToken();
final int deltaPri;
if (stok.ttype != StreamTokenizer.TT_NUMBER) {
stok.pushBack();
deltaPri = 0;
} else {
// priority
deltaPri = (int) stok.nval;
}
if (prevTask == null) {
throw new Exception("& was unexpected");
} else if (prevTask.getRunInBackground()) {
throw new Exception("double & was unexpected");
} else {
prevTask.setRunInBackground(deltaPri);
}
break;
case '>':
currSequence.setNoChildReport(); /* intentional fallthrough */
case '}':
case ']':
// end sequence
colonOk = true;
prevTask = currSequence;
currSequence = currSequence.getParent();
break;
case '-':
isDisableCountNextTask = true;
break;
} // switch(c)
break;
} // switch(stok.ttype)
}
if (sequence != currSequence) {
throw new Exception("Unmatched sequences");
}
// remove redundant top level enclosing sequences
while (sequence.isCollapsable() && sequence.getRepetitions() == 1 && sequence.getRate() == 0) {
ArrayList<PerfTask> t = sequence.getTasks();
if (t != null && t.size() == 1) {
PerfTask p = t.get(0);
if (p instanceof TaskSequence) {
sequence = (TaskSequence) p;
continue;
}
}
break;
}
}