protected void optionalParam() throws ParseException {
    if (!fInput.hasNext()) return; // leere Lambda Liste

    if (fInput.next().getTyp() == TSExpression.SYMBOL) {
      Symbol symbol = (Symbol) fInput.current();
      if (symbol.getSymbolName().equalsIgnoreCase(TOKEN_OPTIONAL)) {

        // if(!fInput.hasNext()) { //&optional gesehen, aber kein weiteres symbol angegeben
        //	error("At least one &optional parameter must be specified",
        // fInput.getInputSExpression());
        // }
        // addOptional(varInit(fInput.next())); //mindesten ein Symbol ist angegeben

        while (true) {
          if (!fInput.hasNext()) {
            break;
          }

          SExpression next = fInput.next();
          if (isSpecialSymbol(next)) {
            fInput.pushBack();
            break;
          }

          addOptional(varInit(next));
        }

      } else {
        fInput.pushBack();
        return;
      }
    } else {
      error("Unknown symbol in optional parameter list: &optional expected", fInput.current());
    }
  }
  protected void keywordParam() throws ParseException {
    if (!fInput.hasNext()) return;

    if (fInput.next().getTyp() == TSExpression.SYMBOL) {
      Symbol symbol = (Symbol) fInput.current();
      if (symbol.getSymbolName().equalsIgnoreCase(TOKEN_KEY)) {

        while (true) {
          if (!fInput.hasNext()) {
            break;
          }

          SExpression next = fInput.next();
          if (isSpecialSymbol(next)) {
            fInput.pushBack();
            break;
          }

          addKey(varInit(next));
        }

        allowOtherKeys();
      } else {
        fInput.pushBack();
      }
    } else {
      error("Unknown symbol in key list: &key expected", fInput.getInputSExpression());
    }
  }
  protected void requiredParam() throws ParseException {
    if (!fInput.hasNext()) return; // leere Lambda List

    if (fInput.next().getTyp() == TSExpression.SYMBOL) {
      Symbol symbol = (Symbol) fInput.current();
      if (isSpecialSymbol(symbol)) {
        fInput.pushBack();
        return;
      }

      addRequired(symbol);
      requiredParam();

    } else {
      error("Unknown symbol in required parameter list", fInput.current());
    }
  }
  protected void bodyOrRest() throws ParseException {
    if (!fInput.hasNext()) return;

    if (fInput.next().getTyp() == TSExpression.SYMBOL) {
      Symbol symbol = (Symbol) fInput.current();
      if (symbol.getSymbolName().equalsIgnoreCase(TOKEN_BODY)) {
        fBody = readRestOrBodySymbol("body");
      } else if (symbol.getSymbolName().equalsIgnoreCase(TOKEN_REST)) {
        fRest = readRestOrBodySymbol("rest");
      } else {
        fInput.pushBack(); // evtl. &key
        return;
      }
    } else {
      error("Unknown symbol in rest or body list: &body or &rest expected", fInput.current());
    }
  }
  protected void rest() throws ParseException {
    if (!fInput.hasNext()) return; // testen ob ueberhaupt noch was vorhanden

    if (!isNextSymbol(TOKEN_REST)) { // Rest Symbol
      fInput.pushBack(); // nein, dann symbol wieder zuruecklegen, evtl. &key oder &aux
      return;
    }

    checkNextIsType(TSExpression.SYMBOL);
    fRest = (Symbol) fInput.current();
  }
  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());
    }
  }