package org.krakenapps.logdb.query.parser;
import static org.krakenapps.bnf.Syntax.choice;
import static org.krakenapps.bnf.Syntax.k;
import static org.krakenapps.bnf.Syntax.ref;
import static org.krakenapps.bnf.Syntax.rule;
import org.krakenapps.bnf.Binding;
import org.krakenapps.bnf.Parser;
import org.krakenapps.bnf.Syntax;
import org.krakenapps.logdb.LogQueryParser;
import org.krakenapps.logdb.query.OptionPlaceholder;
import org.krakenapps.logdb.query.command.OptionChecker;
public class OptionCheckerParser implements LogQueryParser {
@Override
public void addSyntax(Syntax syntax) {
// @formatter:off
SingleOptionCheckerParser s = new SingleOptionCheckerParser();
MultipleOptionCheckerParser m = new MultipleOptionCheckerParser();
syntax.add("option_checker_single", s, choice(rule(k("("), ref("option_checker_single"), k(")")), new OptionPlaceholder()));
syntax.add("option_checker_multi1", m, choice(rule(k("("), ref("option_checker_multi1"), k(")")), rule(ref("option_checker_single"),
choice(k("and"), k("or")), choice(ref("option_checker_multi1"), ref("option_checker_single")))));
syntax.add("option_checker_multi2", m, choice(rule(k("("), ref("option_checker_multi2"), k(")")), rule(ref("option_checker_multi1"),
choice(k("and"), k("or")), choice(ref("option_checker_multi1"), ref("option_checker_single")))));
syntax.add("option_checker", this, choice(ref("option_checker_single"), ref("option_checker_multi1"), ref("option_checker_multi2")));
// @formatter:on
}
@Override
public Object parse(Binding b) {
return b.getValue();
}
private class SingleOptionCheckerParser implements Parser {
@Override
public Object parse(Binding b) {
if (b.getChildren() != null && b.getChildren().length == 3)
return b.getChildren()[1].getValue();
return b.getValue();
}
}
private class MultipleOptionCheckerParser implements Parser {
@Override
public Object parse(Binding b) {
if (b.getChildren()[0].getValue().equals("(")) {
OptionChecker result = (OptionChecker) b.getChildren()[1].getValue();
result.setBracket(true);
return result;
}
OptionChecker lh = (OptionChecker) b.getChildren()[0].getValue();
boolean isAnd = "and".equalsIgnoreCase((String) b.getChildren()[1].getValue());
OptionChecker rh = (OptionChecker) b.getChildren()[2].getValue();
if (isAnd) {
if (!lh.isHighPriority() && !rh.isHighPriority()) // {A|B}&{C|D}=>(A|(B&C))|D
return new OptionChecker(new OptionChecker(lh.getLh2(), false, new OptionChecker(lh.getRh2(), true, rh.getLh2())),
false, rh.getRh2());
else if (!lh.isHighPriority()) // {A|B}&C=>A|(B&C)
return new OptionChecker(lh.getLh2(), false, new OptionChecker(lh.getRh2(), true, rh));
else if (!rh.isHighPriority()) // A&{B|C}=>(A&B)|C
return new OptionChecker(new OptionChecker(lh, true, rh.getLh2()), false, rh.getRh2());
}
return new OptionChecker(lh, isAnd, rh);
}
}
}