use of uk.me.parabola.mkgmap.osmstyle.function.GetTagFunction in project mkgmap by openstreetmap.
the class ExpressionReader method readConditions.
/**
* Read the conditions. They are terminated by a '[' or '{' character
* or by end of file.
* @param ifStack expressions of enclosing if / else
*/
public Op readConditions(Collection<Op[]> ifStack) {
boolean consumedNonBlank = false;
while (!scanner.isEndOfFile()) {
scanner.skipSpace();
if (scanner.checkToken("[") || scanner.checkToken("{") || scanner.checkToken("then"))
break;
consumedNonBlank = true;
WordInfo wordInfo = scanner.nextWordWithInfo();
if (isOperation(wordInfo)) {
saveOp(wordInfo.getText());
} else if (wordInfo.isQuoted()) {
pushValue(wordInfo.getText());
} else if (wordInfo.getText().charAt(0) == '$') {
String tagname = scanner.nextWord();
if (tagname.equals("{")) {
tagname = scanner.nextWord();
scanner.validateNext("}");
}
stack.push(new GetTagFunction(tagname));
} else if (scanner.checkToken("(")) {
// it is a function
// this requires a () after the function name
scanner.validateNext("(");
scanner.validateNext(")");
saveFunction(wordInfo.getText());
} else {
pushValue(wordInfo.getText());
}
}
// Complete building the tree
while (!opStack.isEmpty()) runOp(scanner);
if (consumedNonBlank && !ifStack.isEmpty() && stack.size() <= 1) {
// add expressions from enclosing if /else statements
Op op = null;
if (!stack.isEmpty())
op = stack.pop();
stack.push(appendIfExpr(op, ifStack));
}
// The stack should contain one entry which is the complete tree
if (stack.size() != 1) {
throw new SyntaxException(scanner, "Stack size is " + stack.size() + " (missing or incomplete expression)");
}
assert stack.size() == 1;
Op op = stack.pop();
if (op instanceof ValueOp)
throw new SyntaxException(scanner, "Incomplete expression, just a single symbol: " + op);
return op;
}
use of uk.me.parabola.mkgmap.osmstyle.function.GetTagFunction in project mkgmap by openstreetmap.
the class ExpressionReader method runOp.
/**
* Combine the operation at the top of its stack with its values.
* @param scanner The token scanner; used for line numbers.
*/
private void runOp(TokenScanner scanner) {
Op op = opStack.pop();
log.debug("Running op...", op.getType());
if (op instanceof BinaryOp) {
if (stack.size() < 2) {
throw new SyntaxException(scanner, String.format("Not enough arguments for '%s' operator", op.getType().toSymbol()));
}
Op arg2 = stack.pop();
Op arg1 = stack.pop();
if (arg1.isType(VALUE))
/*&& arg2.isType(VALUE)*/
arg1 = new GetTagFunction(arg1.getKeyValue());
// Deal with the case where you have: a & b=2. The 'a' is a syntax error in this case.
if (op.isType(OR) || op.isType(AND)) {
if (arg1.isType(VALUE) || arg1.isType(FUNCTION))
throw new SyntaxException(scanner, String.format("Value '%s' is not part of an expression", arg1));
if (arg2.isType(VALUE) || arg2.isType(FUNCTION))
throw new SyntaxException(scanner, String.format("Value '%s' is not part of an expression", arg2));
} else {
// type too.
if (!(arg1.isType(VALUE) || arg1.isType(FUNCTION)) || !(arg2.isType(VALUE) || arg2.isType(FUNCTION))) {
String msg = String.format("Invalid arguments to %s: %s (%s) and %s (%s)", op.getType(), arg1.getType(), arg1, arg2.getType(), arg2);
throw new SyntaxException(scanner, msg);
}
}
BinaryOp binaryOp = (BinaryOp) op;
binaryOp.setFirst(arg1);
binaryOp.setSecond(arg2);
// The combination foo=* is converted to exists(foo).
if (op.isType(EQUALS) && arg2.isType(VALUE) && ((ValueOp) arg2).isValue("*")) {
log.debug("convert to EXISTS");
op = new ExistsOp();
op.setFirst(arg1);
} else if (op.isType(NOT_EQUALS) && arg2.isType(VALUE) && ((ValueOp) arg2).isValue("*")) {
log.debug("convert to NOT EXISTS");
op = new NotExistsOp();
op.setFirst(arg1);
}
} else if (!op.isType(OPEN_PAREN)) {
if (stack.size() < 1)
throw new SyntaxException(scanner, String.format("Missing argument for %s operator", op.getType().toSymbol()));
op.setFirst(stack.pop());
}
Op first = op.getFirst();
if (first == null)
throw new SyntaxException(scanner, "Invalid expression");
if (first.isType(FUNCTION) && first.getKeyValue() != null) {
usedTags.add(first.getKeyValue());
}
stack.push(op);
}
use of uk.me.parabola.mkgmap.osmstyle.function.GetTagFunction in project mkgmap by openstreetmap.
the class RuleFileReader method readIf.
private boolean readIf(TokenScanner scanner, ExpressionReader expressionReader) {
// Take the 'if' token
Token tok = scanner.nextToken();
scanner.skipSpace();
// If 'if'' is being used as a keyword then it is followed by a '('.
Token next = scanner.peekToken();
if (next.getType() == TokType.SYMBOL && next.isValue("(")) {
Op origExpr = expressionReader.readConditions();
scanner.validateNext("then");
// add rule expr { set <ifVar> = true }
String ifVar = getNextIfVar();
ArrayList<Action> actions = new ArrayList<>(1);
actions.add(new AddTagAction(ifVar, "true", true));
ActionList actionList = new ActionList(actions, Collections.singleton(ifVar + "=true"));
saveRule(scanner, origExpr, actionList, null);
// create expression (<ifVar> = true)
EqualsOp safeExpr = new EqualsOp();
safeExpr.setFirst(new GetTagFunction(ifVar));
safeExpr.setSecond(new ValueOp("true"));
Op[] ifExpressions = { origExpr, safeExpr };
ifStack.addLast(ifExpressions);
return true;
} else {
// Wrong syntax for if statement, so push back token to allow a possible expression to be read
scanner.pushToken(tok);
}
return false;
}
Aggregations