private ParameterDefinition varInit(final SExpression varInit) throws ParseException {
    if (isSpecialSymbol(varInit)) {
      error("Unexpected symbol: " + ((Symbol) varInit).getSymbolName(), varInit);
    }

    if (varInit.getTyp() == TSExpression.SYMBOL) { // einfaches Symbol
      return new ParameterDefinition((Symbol) varInit, null, null);
    } else if (varInit.getTyp() == TSExpression.FORM) { // komplexe Vardeklaration
      return initForm((Form) varInit);
    } else {
      error("Illegal parameter definition", varInit);
      return null; // wird nie erreicht
    }
  }
  private void checkFirstAndSecond(final Form form) throws ParseException {
    SExpression initVal = form.getChild(1);

    // als init-Wert ist Symbol (oder Subtyp) oder eine Form erlaubt.
    // Nur s-expression reicht nicht aus
    if (!initVal.isNil() && !(initVal instanceof Symbol) && initVal.getTyp() != TSExpression.FORM) {
      error("form or symbol expected", form.getChild(1));
    }
  }
  protected void requiredParamDestructured() throws ParseException {
    if (!fInput.hasNext()) return;

    SExpression next = fInput.next();
    if (next.getTyp() == TSExpression.SYMBOL) {
      Symbol symbol = (Symbol) next;
      if (isSpecialSymbol(symbol)) {
        fInput.pushBack();
        return;
      }
      addRequired(symbol);
      requiredParamDestructured();
    } else if (next.getTyp() == TSExpression.SEXPRESSION
        || next instanceof Form) { // echte sexp oder form, Symbol wird oben abgefragt
      // String-, Key- oder Reader-Symbole = error
      addRequired(next);
      requiredParamDestructured();
    } else {
      error("Symbol or destructuring lambda list expected", fInput.current());
    }
  }
  private Symbol readRestOrBodySymbol(final String bodyRest) throws ParseException {
    if (!fInput.hasNext()) {
      error(bodyRest + " symbol expected", fInput.getInputSExpression());
    }

    SExpression symbol = fInput.next();
    if (symbol.getTyp() == TSExpression.SYMBOL && !isSpecialSymbol(symbol)) { // echtes symbol
      return (Symbol) symbol;
    }

    error(bodyRest + " symbol expected", symbol);
    return null; // wird nie erreicht
  }
  protected boolean isSpecialSymbol(final SExpression sexp) {
    if (sexp.getTyp() != TSExpression.SYMBOL) return false;

    Symbol symbol = (Symbol) sexp;
    String symName = symbol.getSymbolName();
    return symName.equalsIgnoreCase(TOKEN_OPTIONAL)
        || symName.equalsIgnoreCase(TOKEN_BODY)
        || symName.equalsIgnoreCase(TOKEN_KEY)
        || symName.equalsIgnoreCase(TOKEN_REST)
        || symName.equals(TOKEN_AUX)
        || symName.equals(TOKEN_ALLOW_OTHER_KEYS)
        || symName.equals(TOKEN_WHOLE)
        || symName.equals(TOKEN_ENVIRONMENT);
  }