SymVar* Parser::ParseDeclarator(SymType* type, bool parseParams)
{
    SymVar* result = NULL;

    //pointer
    while (*lexer.Peek() == MULTIPLICATION)
    {
        type = new SymTypePointer(type);
        lexer.Get();
    }

    //direct-declarator
    if (*lexer.Peek() == ROUND_LEFT_BRACKET)
    {
        lexer.Get();
        result =  ParseDeclarator(type);
        Expected(lexer.Get()->GetSubType(), ROUND_RIGHT_BRACKET);
        return result;
    }

    Expected(parseParams || *lexer.Peek() == IDENTIFIER, "exepcted an identifier");

    if (parseParams && *lexer.Peek() != IDENTIFIER)
    {
        string n = to_string((long double)counter++);
        BaseToken* dummy = new BaseToken("abstract-"+n, 0, 0, IDENTIFIER, IDENTIFIER);
        result = new SymVar(dummy, type);
    }
    else
    {
        string msg = "redefinition: " + lexer.Peek()->GetText();
        Expected(!symStack.Top()->Find(lexer.Peek()->GetText()), &msg[0]);
        result = new SymVar(lexer.Get(), type);
    }

    BaseToken* token = lexer.Peek();
    if (*token == SQUARE_LEFT_BRACKET)
    {
        lexer.Get();
        Expected(*lexer.Peek() != SQUARE_RIGHT_BRACKET, "unknown size");

        SyntaxNode* index = ParseExpression();
        Expected(*index->token != IDENTIFIER, "expression must have a constant value");

        SymType* indexType = index->GetType();
        Expected(indexType == intType && indexType->CanConvertTo(intType),
                 "expression must be an integral constant expression");

        Expected(lexer.Get()->GetSubType(), SQUARE_RIGHT_BRACKET);

        int size = dynamic_cast<TokenVal <int> *>(index->token)->GetValue();
        result->SetType(new SymTypeArray(size, type));
    }
    else if (*token == ROUND_LEFT_BRACKET)
    {
        lexer.Get();
        SymTypeFunc* t = new SymTypeFunc(type);
        t->params->offset = 4;

        symStack.Push(t->params);
        ParseParameterList();
        symStack.Pop();

        if (*lexer.Peek() == FIGURE_LEFT_BRACKET)
        {
            parseFunc.push_back(t);
            t->body = ParseBlock();
            parseFunc.pop_back();
        }
        result->SetType(t);
    }

    return result;
}