/******************************************************/
/* This program evaluates an arithmetic expression    */
/* using recursion.  It contains an expanded version  */
/* of the GNT procedure that obtains an expression    */
/* containing separate tokens. EXP then recursively   */
/* evaluates the tokens in the input line.            */
/******************************************************/

expression:
    procedure options(main);

    %replace
        true by '1'b;

    declare 
       sysin file,
       value float,
       (token character(10), line character(80)) varying
       static initial('');

    on endfile(sysin)
       stop;

    on error(1) /* conversion or signal */
       begin;
         put skip list('Invalid Input at ',token);
         token = ''; line = '';
         goto restart;
       end;

    restart:

        do while('1'b);
           put skip(3) list('Type expression: ');
           value = exp();
           put edit('Value is: ',value) (skip,a,f(10,4));
        end;

    gnt:
       procedure; 
       declare 
          i fixed;

        line = substr(line,length(token)+1);
        do while(true);
           if line = '' then
              get edit(line) (a);
              i = verify(line,' ');
           if i = 0 then
              line = '';
           else
              do;
                line = substr(line,i);
                i = verify(line,'0123456789.');
                if i = 0 then
                   token = line;
                else
                if i = 1 then
                   token = substr(line,1,1);
                else
                   token = substr(line,1,i-1);
                return;
              end;
        end;
    end gnt;

    exp:
        procedure returns(float binary) recursive;
        declare x float binary;
        call gnt();
        if token = '(' then
           do;
             x  = exp();
             call gnt();
             if token = '+' then
                x = x + exp();
             else
             if token = '-' then
                x = x - exp();
             else
             if token = '*' then
                x = x * exp();
             else
             if token = '/' then
                x = x / exp();
             else
             signal error(1);
             call gnt();
             if token ^= ')' then
                signal error(1);
           end;
        else
            x = token;
        return(x);
    end exp;

end expression;

