program wp08zad4;

type DrzewoZnakow = ^WezelDrzewaZnakow;
     WezelDrzewaZnakow = record
         w : Char;
         lsyn, psyn : DrzewoZnakow
     end;
     DrzewoLiczb = ^WezelDrzewaLiczb;
     WezelDrzewaLiczb = record
         w : Integer;
         lsyn, psyn : DrzewoLiczb
     end;

var glowny : DrzewoZnakow;
    funkcja : array ['A'..'Z'] of DrzewoZnakow;
    zmienna : array ['a'..'z'] of Integer;
    nieujemne, ujemne : DrzewoLiczb;
    i : Integer;
    s : String;
    c : Char;

procedure test(b : Boolean; s : String);
begin
    if not b then begin
        writeln(s);
        halt
    end
end;

function szukaj(var p : DrzewoLiczb; adres : Integer) : DrzewoLiczb;
begin
    if p = nil then begin
        new(p);
        p^.w := 0;
        p^.lsyn := nil;
        p^.psyn := nil
    end;
    if adres = 0 then
        szukaj := p
    else if adres mod 2 = 0 then
        szukaj := szukaj(p^.lsyn, adres div 2)
    else
        szukaj := szukaj(p^.psyn, adres div 2)
end;

function komorka(adres : Integer) : DrzewoLiczb;
begin
    if adres >= 0 then
        komorka := szukaj(nieujemne, adres)
    else
        komorka := szukaj(ujemne, -adres)
end;

procedure wczytaj(var d : DrzewoZnakow);
begin
    test(i <= length(s), 'Nieoczekiwany koniec programu');
    new(d);
    d^.w := s[i];
    d^.lsyn := nil;
    d^.psyn := nil;
    i := i + 1;
    if not (d^.w in [' ', '@', 'a' .. 'z', 'A' .. 'Z', '0' .. '9']) then begin
        wczytaj(d^.lsyn);
        if not (d^.w in ['(', ')', '{', '}', '[', ']', '!', '$']) then
            wczytaj(d^.psyn)
    end;
    if d^.w in [':', '(', '{', '[', ']'] then
        test(d^.lsyn^.w in ['$', 'a' .. 'z'], 'Niepoprawna l-wartosc')
end;

function wartosc(d : DrzewoZnakow) : Integer; forward;

procedure przypisz(d : DrzewoZnakow; i : Integer);
var x : DrzewoLiczb;
begin
    if d^.w = '$' then begin
        x := komorka(wartosc(d^.lsyn));
        x^.w := i
    end else
        zmienna[d^.w] := i
end;

function wartosc(d : DrzewoZnakow) : Integer;
var arg, arg2 : Integer;
    c : Char;
    x : DrzewoLiczb;
begin
    if d = nil then
        halt
    else
        case d^.w of
            ' ':
                wartosc := 32;
            '@':
                wartosc := 10;
            '0'..'9':
                wartosc := ord(d^.w) - ord('0');
            'a'..'z':
                wartosc := zmienna[d^.w];
            'A'..'Z':
                wartosc := wartosc(funkcja[d^.w]);
            ':': begin
                arg := wartosc(d^.psyn);
                przypisz(d^.lsyn, arg);
                wartosc := arg
            end;
            '(': begin
                if eof then
                    arg := -1
                else begin
                    read(c);
                    arg := ord(c)
                end;
                przypisz(d^.lsyn, arg);
                wartosc := arg
            end;
            '{': begin
                read(arg);
                przypisz(d^.lsyn, arg);
                wartosc := arg
            end;
            '^': begin
                wartosc := 0;
                while wartosc(d^.lsyn) <> 0 do
                    wartosc := wartosc(d^.psyn)
            end;
            '~':
                repeat
                    wartosc := wartosc(d^.lsyn)
                until wartosc(d^.psyn) <> 0;
        else
            arg := wartosc(d^.lsyn);
            case d^.w of
                '!':
                    wartosc := 1 - ord(arg <> 0);
                ')': begin
                    write(chr(arg));
                    wartosc := arg
                end;
                '}': begin
                    write(arg);
                    wartosc := arg
                end;
                '$': begin
                    x := komorka(arg);
                    wartosc := x^.w
                end;
                '[': begin
                    przypisz(d^.lsyn, arg + 1);
                    wartosc := arg
                end;
                ']': begin
                    przypisz(d^.lsyn, arg - 1);
                    wartosc := arg - 1
                end;
                '&':
                    if arg = 0 then
                        wartosc := 0
                    else
                        wartosc := wartosc(d^.psyn);
                '|':
                    if arg <> 0 then
                        wartosc := arg
                    else
                        wartosc := wartosc(d^.psyn);
                '?':
                    if d^.psyn^.w = ',' then
                        if arg <> 0 then
                            wartosc := wartosc(d^.psyn^.lsyn)
                        else
                            wartosc := wartosc(d^.psyn^.psyn)
                    else begin
                        wartosc := arg;
                        if arg <> 0 then
                            arg := wartosc(d^.psyn)
                    end;
                '\': begin
                    wartosc:=arg;
                    if arg = 0 then
                        arg := wartosc(d^.psyn)
                end;
            else
                arg2 := wartosc(d^.psyn);
                case d^.w of
                    '+':
                        wartosc := arg + arg2;
                    '-':
                        wartosc := arg - arg2;
                    '*':
                        wartosc := arg * arg2;
                    '/':
                        wartosc := arg div arg2;
                    '%':
                        wartosc := arg mod arg2;
                    '<':
                        wartosc := ord(arg < arg2);
                    '>':
                        wartosc := ord(arg > arg2);
                    '=':
                        wartosc := ord(arg = arg2);
                    '#':
                        wartosc := 10 * arg + arg2;
                    ';':
                        wartosc := arg2;
                    ',':
                        wartosc := arg;
                else
                    test(false, 'Niepoprawne drzewo programu')
                end
            end
        end
end;

begin
    test(paramCount = 1, 'Program oczekuje jednego argumentu');
    s := paramStr(1);
    i := 1;
    for c := 'A' to 'Z' do
        funkcja[c] := nil;
    wczytaj(glowny);
    while i < length(s) do begin
        test(s[i] in ['A' .. 'Z'], 'Niepoprawna nazwa funkcji');
        i := i + 1;
        wczytaj(funkcja[s[i - 1]])
    end;
    for c := 'a' to 'z' do
        zmienna[c] := 0;
    nieujemne := nil;
    ujemne := nil;
    i := wartosc(glowny)
end.
