This is actually an interesting problem. What I would do is keep track of each elements position in the stack. You can do this using a cumulative sum:
select st.*,
sum(case when op = 'I' then 1 else -1 end) over (order by i) as pos
from stack_trace st;
Alas, at this point, I think you need a rather complicated join or subquery to figure out the most recent value that pos refers to. Here is one method:
with st as (
select st.*,
sum(case when op = 'I' then 1 else -1 end) over (order by i) as pos
from stack_trace st
)
select st.*,
(select val
from st st2
where st2.i <= st.id and st2.pos = st.pos and
st2.val is not null
order by i desc
fetch first 1 row only
) as top_of_stack_val
from st;