public function parse()
    {
        $this->lexer->moveNext();

        while (true) {
            if (!$this->lexer->lookahead) {
                break;
            }

            $this->lexer->moveNext();
            $thisLine = null;

            switch ($this->lexer->token['type']) {
                case Lexer::T_OPEN_PARENTHESIS:
                case Lexer::T_OPEN_BRACKET:
                case Lexer::T_OPEN_CURLY_BRACE:
                    $thisLine = '[';
                    $this->currentLevel++;
                    break;
                case Lexer::T_CLOSE_PARENTHESIS:
                case Lexer::T_CLOSE_BRACKET:
                case Lexer::T_CLOSE_CURLY_BRACE:
                    $thisLine = ']';
                    $this->currentLevel--;
                    break;
                case Lexer::T_STRING:
                    $thisLine = "'".str_replace("'", "\'", $this->lexer->token['value'])."'";
                    break;
                case Lexer::T_DOUBLEPOINT:
                    $thisLine = '=>';
                    break;
                case Lexer::T_COMMENT_PARAMSTART:
                    $paramName = $this->lexer->lookahead['value'];
                    $thisLine = '$this->getParam("'.$paramName.'")';
                    // scroll to end of param
                    while ($this->lexer->token['type'] != Lexer::T_COMMENT_PARAMEND) {
                        $this->lexer->moveNext();
                    }
                    break;
                case Lexer::T_COMMENT_IFPARAMSTART:
                case Lexer::T_COMMENT_IFNOTPARAMSTART:
                    $conditionalId = str_pad((string) $this->conditionalCounter, 5, '0', STR_PAD_LEFT);
                    $this->conditionalCounter++;

                    $isNegated = '';
                    if ($this->lexer->token['type'] == Lexer::T_COMMENT_IFNOTPARAMSTART) {
                        $isNegated = 'true';
                    }

                    $this->addContent('$this->getConditional'.$conditionalId.'('.$isNegated.'),');
                    $this->openConditional($conditionalId, $this->lexer->lookahead['value']);
                    break;
                case Lexer::T_COMMENT_IFPARAMEND:
                case Lexer::T_COMMENT_IFNOTPARAMEND:
                    $this->closeConditional();
                    break;
                case Lexer::T_DATE_EMPTY:
                    $thisLine = 'new '.$this->mongoDateClass.'()';
                    break;
                case Lexer::T_DATE_WITH_PARAM:
                    $paramName = $this->lexer->lookahead['value'];
                    $thisLine = '$this->getParam("'.$paramName.'")';
                    break;
                case Lexer::T_BOOLEAN_TRUE:
                    $thisLine = 'true';
                    break;
                case Lexer::T_BOOLEAN_FALSE:
                    $thisLine = 'false';
                    break;
                case Lexer::T_NULL:
                    $thisLine = 'null';
                    break;
                case Lexer::T_COMMA:
                case Lexer::T_NUMBER:
                case Lexer::T_DASH:
                    $thisLine = $this->lexer->token['value'];
                    break;
                default:
                    // nothing
            }

            if (!is_null($thisLine)) {
                $this->addContent($thisLine);
            }
        }

        return implode(PHP_EOL, $this->lines);
    }