#include <cstdio>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

class Node{
public:
    char ope;
    // string s;
    Node *left, *right;
    Node(){
        ope = '\0';
        left = right = NULL;
    }
};

void deleteNodesTree(Node* node){
    if(node != NULL){
        deleteNodesTree(node->left);
        deleteNodesTree(node->right);
        delete node;
    }
}

// binaryOpe     : 二項演算子の優先度（-1ならば、二項演算子ではない）
// associativity : 二項演算子の優先順位（trueならば、左から右に結合）
// unaryOpe      : 単項演算子
Node* syntacticAnalysis(const string& s, const vector<int>& binaryOpe,
                        const vector<bool>& associativity, const vector<bool>& unaryOpe)
{
    class Func{
    public:
        static bool calc(stack<pair<Node*, bool> >& stk, int maxPriority ,
                         const vector<int>& binaryOpe, const vector<bool>& associativity, const vector<bool>& unaryOpe)
        {
            if(!stk.top().second)
                return false;
            pair<Node*, bool> right = stk.top();
            stk.pop();
            while(stk.top().first != NULL){
                pair<Node*, bool> ope = stk.top();
                if(ope.second)
                    break;
                stk.pop();
                if(binaryOpe[ope.first->ope] != -1 && stk.top().second){
                    if(binaryOpe[ope.first->ope] > maxPriority ||
                            binaryOpe[ope.first->ope] == maxPriority && !associativity[binaryOpe[ope.first->ope]]){
                        stk.push(ope);
                        break;
                    }
                    ope.first->right = right.first;
                    ope.first->left = stk.top().first;
                    ope.second = true;
                    right = ope;
                    stk.pop();
                }else if(unaryOpe[ope.first->ope]){
                    ope.first->right = right.first;
                    ope.second = true;
                    right = ope;
                }else{
                    stk.push(ope);
                    break;
                }
            }
            bool ret = (stk.top().first == NULL);
            stk.push(right);
            return ret;
        }
        static void deleteAllNodes(stack<pair<Node*, bool> >& stk)
        {
            while(!stk.empty()){
                deleteNodesTree(stk.top().first);
                stk.pop();
            }
        }
    };

    int n = s.size();
    int i = 0;
    stack<pair<Node*, bool> > stk;
    stk.push(make_pair((Node*)NULL, false));
    while(i < n){
        if(s[i] == '('){
            stk.push(make_pair((Node*)NULL, false));
            ++ i;
        }else if(s[i] == ')'){
            if(!Func::calc(stk, INT_MAX, binaryOpe, associativity, unaryOpe) || stk.size() == 2){
                Func::deleteAllNodes(stk);
                return NULL;
            }
            pair<Node*, bool> node = stk.top();
            stk.pop();
            stk.pop();
            stk.push(node);
            ++ i;
        }else if(binaryOpe[s[i]] != -1 || unaryOpe[s[i]]){
            Func::calc(stk, binaryOpe[s[i]], binaryOpe, associativity, unaryOpe);
            Node* node = new Node;
            node->ope = s[i];
            stk.push(make_pair(node, false));
            ++ i;
        }else{
            Node* node = new Node;
            while(i < n && s[i] != '(' && s[i] != ')' && binaryOpe[s[i]] == -1 && !unaryOpe[s[i]]){
                // node->s += s[i];
                ++ i;
            }
            stk.push(make_pair(node, true));
        }
    }

    if(!Func::calc(stk, INT_MAX, binaryOpe, associativity, unaryOpe) || stk.size() != 2){
        Func::deleteAllNodes(stk);
        return NULL;
    }else{
        return stk.top().first;
    }
}

const int MOD = 1000000007;

vector<int> dfs(Node* node)
{
    if(node->ope == '~'){
        vector<int> ret = dfs(node->right);
        swap(ret[0], ret[1]);
        return ret;
    }else if(node->ope == '|'){
        vector<int> a = dfs(node->left);
        vector<int> b = dfs(node->right);
        vector<int> ret(2, 0);
        for(int i=0; i<2; ++i){
            for(int j=0; j<2; ++j){
                ret[i|j] = (ret[i|j] + (long long)a[i] * b[j]) % MOD;
            }
        }
        return ret;
    }else if(node->ope == '&'){
        vector<int> a = dfs(node->left);
        vector<int> b = dfs(node->right);
        vector<int> ret(2, 0);
        for(int i=0; i<2; ++i){
            for(int j=0; j<2; ++j){
                ret[i&j] = (ret[i&j] + (long long)a[i] * b[j]) % MOD;
            }
        }
        return ret;
    }else{
        vector<int> ret(2, 1);
        return ret;
    }
}

int main()
{
    string s;
    cin >> s;

    vector<int> binaryOpe(128, -1);
    vector<bool> associativity(2, true);
    vector<bool> unaryOpe(128, false);
    binaryOpe['&'] = 0;
    binaryOpe['|'] = 1;
    unaryOpe['~'] = true;

    Node* node = syntacticAnalysis(s, binaryOpe, associativity, unaryOpe);
    cout << dfs(node)[1] << endl;
    deleteNodesTree(node);

    return 0;
}