#define _USE_MATH_DEFINES
#include <cstdio>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <complex>
#include <string>
#include <vector>
#include <array>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <limits>
#include <climits>
#include <cfloat>
#include <functional>
#include <iterator>
#include <memory>
#include <regex>
using namespace std;

template <class T1>
class Operators
{
public:
    template <class T2>
    const T1 operator+(const T2& right) const{
        T1 ans = static_cast<const T1&>( *this );
        return ans += right;
    }
    template <class T2>
    const T1 operator-(const T2& right) const{
        T1 ans = static_cast<const T1&>( *this );
        return ans -= right;
    }
    template <class T2>
    const T1 operator*(const T2& right) const{
        T1 ans = static_cast<const T1&>( *this );
        return ans *= right;
    }
    template <class T2>
    const T1 operator/(const T2& right) const{
        T1 ans = static_cast<const T1&>( *this );
        return ans /= right;
    }
    template <class T2>
    const T1 operator%(const T2& right) const{
        T1 ans = static_cast<const T1&>( *this );
        return ans %= right;
    }
    bool operator!=(const T1& right) const{
        const T1& left = static_cast<const T1&>( *this );
        return !(left == right);
    }
    bool operator>(const T1& right) const{
        const T1& left = static_cast<const T1&>( *this );
        return right < left;
    }
    bool operator<=(const T1& right) const{
        const T1& left = static_cast<const T1&>( *this );
        return !(right < left);
    }
    bool operator>=(const T1& right) const{
        const T1& left = static_cast<const T1&>( *this );
        return !(left < right);
    }
};

class Mod : public Operators<Mod>
{
private:
    static const int MOD = 2011;
    long long a;
public:
    Mod(){
        a = 0;
    }
    Mod(long long x){
        a = (x % MOD + MOD) % MOD;
    }
    Mod& operator+=(const Mod& x){
        a = (a + x.a) % MOD;
        return *this;
    }
    Mod& operator-=(const Mod& x){
        a = (a - x.a + MOD) % MOD;
        return *this;
    }
    Mod& operator*=(const Mod& x){
        a = (a * x.a) % MOD;
        return *this;
    }
    Mod& operator/=(const Mod& x){ // フェルマーの小定理、MODが素数である場合のみ有効
        int b = MOD - 2;
        long long c = x.a;
        while(b > 0){
            if(b & 1){
                a *= c;
                a %= MOD;
            }
            c *= c;
            c %= MOD;
            b >>= 1;
        }
        return *this;
    }
    bool operator==(const Mod& x) const{
        return a == x.a;
    }
    long long getValue(){
        return a;
    }
};

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

// 数式の構文木を作成する
class syntacticAnalysis
{
private:
    vector<int> unaryPriority;        // 単項演算子の優先順位（数値が小さいほど優先順位が高い）
    vector<int> binaryPriority;       // 二項演算子の優先順位（数値が小さいほど優先順位が高い）
    vector<bool> binaryAssociativity; // 二項演算子の結合規則（trueならば左結合）
    stack<Node*> stk;
    void deleteAllNodes()
    {
        while(!stk.empty()){
            delete stk.top();
            stk.pop();
        }
    }
    bool isValid(const Node* node){
        return node != NULL && (!node->s.empty() || node->right != NULL);
    }
    bool calc(int maxPriority)
    {
        Node* right = stk.top();
        if(!isValid(right))
            return false;
        stk.pop();
        while(stk.top() != NULL){
            Node* curr = stk.top();
            if(isValid(curr))
                break;
            stk.pop();
            // 二項演算子
            if(binaryPriority[curr->ope] != -1 && isValid(stk.top())){
                if(binaryPriority[curr->ope] > maxPriority ||
                    (binaryPriority[curr->ope] == maxPriority && !binaryAssociativity[curr->ope]))
                {
                    stk.push(curr);
                    break;
                }
                curr->right = right;
                curr->left = stk.top();
                stk.pop();
                right = curr;
            }
            // 単項演算子
            else if(unaryPriority[curr->ope] != -1){
                if(unaryPriority[curr->ope] > maxPriority){
                    stk.push(curr);
                    break;
                }
                curr->right = right;
                right = curr;
            }
            else{
                stk.push(curr);
                break;
            }
        }
        bool ret = (stk.top() == NULL);
        stk.push(right);
        return ret;
    }
public:
    enum OpeType{
        BINARY_LEFT,  // 二項演算子（左結合）
        BINARY_RIGHT, // 二項演算子（右結合）
        UNARY,        // 単項演算子
    };

    syntacticAnalysis(const vector<pair<string, OpeType> >& opeRule)
    {
        binaryPriority.assign(128, -1);
        binaryAssociativity.assign(128, false);
        unaryPriority.assign(128, -1);
        for(unsigned i=0; i<opeRule.size(); ++i){
            for(unsigned j=0; j<opeRule[i].first.size(); ++j){
                if(opeRule[i].second == UNARY){
                    unaryPriority[opeRule[i].first[j]] = i;
                }
                else{
                    binaryPriority[opeRule[i].first[j]] = i;
                    binaryAssociativity[opeRule[i].first[j]] = (opeRule[i].second == BINARY_LEFT);
                }
            }
        }
    }
    Node* makeTree(const string& s)
    {
        int n = s.size();
        int i = 0;
        stk.push(NULL);
        while(i < n){
            // 括弧の開始
            if(s[i] == '('){
                stk.push(NULL);
                ++ i;
            }
            // 括弧の終了
            else if(s[i] == ')'){
                // 括弧内の計算結果が不正、もしくは対応する括弧が無ければエラー終了
                if(!calc(INT_MAX) || stk.size() == 2){
                    deleteAllNodes();
                    return NULL;
                }
                Node* node = stk.top();
                stk.pop();
                stk.pop();
                stk.push(node);
                ++ i;
            }
            // 演算子
            else if(binaryPriority[s[i]] != -1 || unaryPriority[s[i]] != -1){
                // 現在の演算子よりも優先順位の高い演算子の計算を確定させる
                calc(binaryPriority[s[i]]);
                Node* node = new Node;
                node->ope = s[i];
                stk.push(node);
                ++ i;
            }
            // 被演算子
            else{
                Node* node = new Node;
                while(i < n && s[i] != '(' && s[i] != ')' && binaryPriority[s[i]] == -1 && unaryPriority[s[i]] == -1){
                    node->s += s[i];
                    ++ i;
                }
                stk.push(node);
            }
        }

        // 計算結果が不正だったらエラー終了
        if(!calc(INT_MAX) || stk.size() != 2){
            deleteAllNodes();
            return NULL;
        }

        Node* ret = stk.top();
        stk.pop();
        stk.pop();
        return ret;
    }
};

template <class T>
T power(T a, long long b)
{
    T ret = 1;
    T tmp = a;
    while(b > 0){
        if(b & 1)
            ret *= tmp;
        tmp *= tmp;
        b >>= 1;
    }
    return ret;
}

/******************************************************************/

class AsciiExpression
{
private:
    vector<string> grid;
    string s;

    void fit(int& y1, int& x1, int& y2, int& x2)
    {
        while(grid[y1].substr(x1, x2 - x1) == string(x2 - x1, '.'))
            ++ y1;
        while(grid[y2-1].substr(x1, x2 - x1) == string(x2 - x1, '.'))
            -- y2;
        for(;;){
            bool empty = true;
            for(int y = y1; y < y2; ++y){
                if(grid[y][x1] != '.')
                    empty = false;
            }
            if(!empty)
                break;
            ++ x1;
        }
        for(;;){
            bool empty = true;
            for(int y = y1; y < y2; ++y){
                if(grid[y][x2-1] != '.')
                    empty = false;
            }
            if(!empty)
                break;
            -- x2;
        }
    }

    void convert(int y1, int x1, int y2, int x2)
    {
        fit(y1, x1, y2, x2);

        int base = y1;
        while(grid[base][x1] == '.')
            ++ base;

        int x = x1;
        while(x < x2){
            if(grid[base][x] == '.'){
                if(base > y1 && grid[base-1][x] != '.'){
                    s += '^';
                    s += grid[base-1][x];
                }
                ++ x;
            }
            else if(grid[base].substr(x, 2) == "--"){
                int x3 = grid[base].find_first_not_of('-', x);
                if(x3 == string::npos)
                    x3 = x2;
                s += '(';
                convert(y1, x, base, x3);
                s += ")/(";
                convert(base + 1, x, y2, x3);
                s += ')';
                x = x3;
            }
            else{
                s += grid[base][x];
                ++ x;
            }
        }
    }

    Mod calc(const Node* node)
    {
        if(node->right == NULL)
            return stoi(node->s);
        else if(node->left == NULL)
            return calc(node->right) * -1;

        Mod a = calc(node->left);
        Mod b = calc(node->right);
        if(node->ope == '+')
            return a + b;
        else if(node->ope == '-')
            return a - b;
        else if(node->ope == '*')
            return a * b;
        else if(node->ope == '/')
            return a / b;
        else
            return power(a, b.getValue());
    }

public:
    Mod solve(const vector<string>& grid)
    {
        this->grid = grid;
        s.clear();
        convert(0, 0, grid.size(), grid[0].size());

        syntacticAnalysis sa({
            {"^", syntacticAnalysis::BINARY_LEFT},
            {"-", syntacticAnalysis::UNARY},
            {"*/", syntacticAnalysis::BINARY_LEFT},
            {"+-", syntacticAnalysis::BINARY_LEFT},
        });

        auto tmp = sa.makeTree("1^-1");

        Node* node = sa.makeTree(s);
        Mod ans = calc(node);
        delete node;

        return ans;
    }
};

int main()
{
    for(;;){
        int n;
        cin >> n;
        if(n == 0)
            return 0;

        vector<string> grid(n);
        for(int i=0; i<n; ++i)
            cin >> grid[i];

        AsciiExpression ae;
        cout << ae.solve(grid).getValue() << endl;
    }
}



Measured memory_bytes: 3160