@SuppressWarnings({"unchecked", "rawtypes"}) private void foreach(boolean inheritedSkip) { ForEachToken feToken = (ForEachToken) tokenStream.currentToken(); Iterable iterable = (Iterable) feToken.evaluate(context); // begin a fresh iteration with a reset index feToken.setIterator(iterable.iterator()); feToken.resetIndex(); tokenStream.consume(); context.model.enterScope(); context.push(feToken); try { // in case we do not want to evaluate the body, we just do a quick // scan until the matching end if (inheritedSkip || !feToken.iterator().hasNext()) { Token contentToken; while ((contentToken = tokenStream.currentToken()) != null && !(contentToken instanceof EndToken)) { content(true); } if (contentToken == null) { engine.getErrorHandler().error("missing-end", feToken); } else { tokenStream.consume(); context.notifyProcessListener(contentToken, Action.END); } } else { while (feToken.iterator().hasNext()) { context.model.put(feToken.getVarName(), feToken.advance()); addSpecialVariables(feToken, context.model); // for each iteration we need to rewind to the beginning // of the for loop tokenStream.rewind(feToken); Token contentToken; while ((contentToken = tokenStream.currentToken()) != null && !(contentToken instanceof EndToken)) { content(false); } if (contentToken == null) { engine.getErrorHandler().error("missing-end", feToken); } else { tokenStream.consume(); context.notifyProcessListener(contentToken, Action.END); } if (!feToken.isLast()) { output.append(feToken.getSeparator()); } } } } finally { context.model.exitScope(); context.pop(); } }
private void content(boolean skip) { Token token = tokenStream.currentToken(); context.notifyProcessListener(token, skip ? Action.SKIP : Action.EVAL); if (token instanceof PlainTextToken) { tokenStream.consume(); if (!skip) { output.append(token.getText()); } } else if (token instanceof StringToken) { tokenStream.consume(); if (!skip) { String expanded = (String) token.evaluate(context); output.append(expanded); } } else if (token instanceof ForEachToken) { foreach(skip); } else if (token instanceof IfToken) { condition(skip); } else if (token instanceof ElseToken) { tokenStream.consume(); engine.getErrorHandler().error("else-out-of-scope", token); } else if (token instanceof EndToken) { tokenStream.consume(); engine.getErrorHandler().error("unmatched-end", token); } else if (token instanceof InvalidToken) { tokenStream.consume(); engine.getErrorHandler().error("invalid-expression", token); } else { tokenStream.consume(); // what ever else there may be, we just evaluate it String evaluated = (String) token.evaluate(context); output.append(evaluated); } }
private void condition(boolean inheritedSkip) { IfToken ifToken = (IfToken) tokenStream.currentToken(); tokenStream.consume(); context.push(ifToken); try { boolean localSkip; if (inheritedSkip) { localSkip = true; } else { localSkip = !(Boolean) ifToken.evaluate(context); } Token contentToken; while ((contentToken = tokenStream.currentToken()) != null && !(contentToken instanceof EndToken) && !(contentToken instanceof ElseToken)) { content(localSkip); } if (contentToken instanceof ElseToken) { tokenStream.consume(); // toggle for else branch if (!inheritedSkip) { localSkip = !localSkip; } context.notifyProcessListener(contentToken, inheritedSkip ? Action.SKIP : Action.EVAL); while ((contentToken = tokenStream.currentToken()) != null && !(contentToken instanceof EndToken)) { content(localSkip); } } if (contentToken == null) { engine.getErrorHandler().error("missing-end", ifToken); } else { tokenStream.consume(); context.notifyProcessListener(contentToken, Action.END); } } finally { context.pop(); } }