@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 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();
    }
  }