# Fonctions de manipulation de piles requises.
# ============================================

# CREATION D'UNE PILE (VIDE)
def stack_create():
    return []

# TEST SI UNE PILE EST VIDE
def stack_isempty(s):
    return len(s)==0

# PUSH (AJOUT) D'UN ELEMENT DANS UNE PILE
def stack_push(s,e):
    s.insert(0,e)

# POP D'UNE PILE (RENVOI ET SUPPRESSION DU SOMMET)
def stack_pop(s):
    x = s[0]
    del s[0]
    return x

# Fonction next_word.
# ===================

def next_word(s,pos):
    if pos >= len(s):
        return []
    else:
        # A-t-on affaire au premier caractère d'un mot ?
        # C'est le cas si (s[pos] est différent d'un blanc) et (pos = 0 ou (pos > 0 et s[pos-1] est un blanc).
        if s[pos] != ' ' and (pos == 0 or (pos > 0 and s[pos-1] == ' ')):
            s2 = s[pos]
            i = pos
            # Si ce caractère est le dernier, on le renvoie ...
            if i == len(s)-1:
                return [s2]
            # Sinon, on parcourt la chaîne et on s'arrête dès que l'on rencontre un (éventuel) blanc ...
            while i < len(s)-1:
                i += 1
                if s[i] != ' ':
                    s2 += s[i]
                    # la fin de la chaîne est atteinte, on renvoie seulement le mot ...
                    if i == len(s)-1:
                        return [s2]
                else:
                    # On finit par obtenir un blanc, on renvoie le mot ET la position du mot suivant.
                    return [s2,i+1]

# Fonction ValNPI.
# ================

def ValNPI(s):
    P = stack_create()
    # i est l'indice de la position du mot courant dans le calcul s.
    i = 0
    # On initialise la liste W avec n'importe quoi pour qu'elle ne soit pas vide.
    W = ['init']
    # Tant que la liste W n'est pas vide, on parcourt la chaîne s et on traite les mots renvoyés
    # par la fonction next_word.
    while W != []:
        W = next_word(s,i)
        # Cas d'un opérande.
        if W[0] != '+' and W[0] != '*':
            if len(W) ==1 and stack_isempty(P):
                return int(W[0])
            else:
                stack_push(P,int(W[0]))
        # Cas d'un opérateur.
        else:
            # on dépile deux éléments (opérandes) pour effectuer le calcul.
            a = stack_pop(P)
            b = stack_pop(P)
            if W[0] == '+':
                stack_push(P,a+b)
            else:
                stack_push(P,a*b)
            # Il n'y a pas d'autre mot, on renvoie le contenu de la pile qui est
            # simplement le résultat du calcul.
            if len(W) == 1:
                return stack_pop(P)
        i = W[1]

# Quelques calculs pour tester le script.
# =======================================

s = '34 13 + 5 *'
print('La valeur du calcul ' + s + ' est : ' + str(ValNPI(s)))
s = '21 5 8 * 7 13 * + *'
print('La valeur du calcul ' + s + ' est : ' + str(ValNPI(s)))
s = '7 12 + 5 11 2 35 19 + + * + *'
print('La valeur du calcul ' + s + ' est : ' + str(ValNPI(s)))
s = '34'
print('La valeur du calcul ' + s + ' est : ' + str(ValNPI(s)))
s = '1 2 3 4 5 6 * * * * *'
print('La valeur du calcul ' + s + ' est : ' + str(ValNPI(s)))