#!/usr/bin/python
# -*- coding: Latin-1 -*-
def revision():
    return '$Revision: 7.3 $'.split()[1]

""" 

 flex-fr - module de flexion pour la langue française.
 Copyright (C) 2001-2004 Yves Ouvrard.

Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le
modifier conformément aux dispositions de la Licence Publique Générale GNU,
telle que publiée par la Free Software Foundation ; version 2 de la licence,
ou encore (à votre choix) toute version ultérieure.
Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE
GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D'ADAPTATION
A UN OBJET PARTICULIER.
Pour plus de détail, voir la Licence Publique Générale GNU .
Vous devez avoir reçu un exemplaire de la Licence Publique Générale GNU en même
temps que ce programme ; si ce n'est pas le cas, écrivez à la
Free Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis.
Pour tout contact avec l'auteur : yves.ouvrard@collatinus.org

UTILISATION : deux possibilités (en overload)
1. function Conjugue(
  inf, P, T, M, V : string; Pr : boolean) : string;

Conjugue le verbe d'infinitif inf
    à la personne P, au temps T, au mode M et à la voix V.
    Le pronom sujet est retourné si Pr est à true.
    Codes numériques pour la morphologie :
   actif = 1;
   passif = 2;

   ind = 1;
   subj = 2;
   cond = 3;
   imper = 4;
   infin = 5;
   part = 6;
   ger = 7;

   pres = 1;
   fut = 2;
   impf = 3;
   psimple = 4;
   pcompose = 5;
   futant = 6;
   pqp = 7;
   pant = 8;

2. conjugue (inf : string; P, T, M, V : integer; Pr : boolean) : string;
   Dans cette version, la fonction attend un appel sous forme de chaînes :
   exemple
   conjugue ('avoir', 'nous', 'présent', 'subjonctif', 'actif', true );
   liste des chaînes reconnues :

personne : 'je', 'tu', 'il', 'nous', 'vous', 'ils'
temps : 'présent', 'futur', 'imparfait', 'passé simple',
        'passé [composé]', 'futur antérieur',
        'plus-que-parfait', 'passé antérieur'
mode : 'indicatif', 'subjonctif', 'conditionnel', 'impératif',
       infinitif', 'participe', 'gérondif'
voix : 'actif', 'passif'.


 ERRATA 
   p.s. et pp : le v. simple seoir;
   participe : régler le pronominal pour le participe présent.
   verbes en -ayer : donner les deux possibilités
   en général, gérer les solutions multiples
   un lieu, des lieux ; un lieu (poisson), des lieus. Comment s'en sortir ?
"""

# Verbe est la classe de base. J'ai pris le premier groupe comme référence,
#   puisqu'il représente la majorité des verbes}

import string, re

# chaînes de champs morpho
personne = [' ', 'je', 'tu', 'il', 'nous', 'vous', 'ils']

temps = [' ', 'présent', 'futur', 'imparfait', 'passé simple',
    'passé [composé]', 'futur antérieur',
    'plus-que-parfait', 'passé antérieur']

mode = [' ', 'indicatif', 'subjonctif', 'conditionnel', 'impératif',
    'infinitif', 'participe', 'gérondif']

voix = [' ', 'actif', 'passif']

actif = 1
passif = 2

ind = 1
subj = 2
cond = 3
imper = 4
infin = 5
part = 6
ger = 7

pres = 1
fut = 2
impf = 3
psimple = 4
pcompose = 5
futant = 6
pqp = 7
pant = 8

class Verbe:
    def __init__(self, i):
       self.inf = i
       self.pronominal = 0

    def GetDesFut(self, index):
        D = ['', 'ai', 'as', 'a', 'ons', 'ez', 'ont']
        return D[index]
    
    def GetDesImpf(self, index): 
       D = ['', 'ais', 'ais', 'ait', 'ions', 'iez', 'aient']
       return D[index]
       
    def GetDesPsAi(self, index):
       D = ['', 'ai', 'as', 'a', 'âmes', 'âtes', 'èrent']
       return D[index]

    def GetDesPsI(self, index): 
       D = ['', 'is', 'is', 'it', 'îmes', 'îtes', 'irent']
       return D[index]
       
    def GetDesPsU(self, index):
       D = ['', 'us', 'us', 'ut', 'ûmes', 'ûtes', 'urent']
       return D[index]

    def GetDesSubjPres(self, index):
       D = ['', 'e', 'es', 'e', 'ions', 'iez', 'ent']
       return D[index]

    # utiles
    def circonflexe(self):
         result = self.IndPs(2)
         result = result[:-1] 
         der = result[-1] 
         if der == 'a': d = 'â'
         elif der == 'i' or der == 'î': d = 'î'
         elif der == 'u' or der == 'û': d = 'û'
         else : d = ''
         return result[:-1] + d
       
    # auxiliaire
    def auxiliaire(self): 
         if AuxEtre.find(self.inf) > -1: return 'être'
         return 'avoir'

   # radicaux
    def RadPres(self, P): 
       return self.inf[:-2]

    def RadFut(self): 
       if self.inf[-1] == 'r':
           return self.inf
       else : return self.inf[:-1]

    def RadPs(self):
       return self.inf[:-2]

   # manipulations : pronoms-radical-désinence
    def elide(self, A, B):
       voyelles = 'aâeéêiîoôuûy'
       if A[-1] == 'e' and voyelles.find(B[0]) > -1: 
           return "%s'%s" % (A[:-1], B)
       return "%s %s" % (A, B) 

    def Pron(self, P, F, refl): 
       PR = ['', 'me', 'te', 'se', 'nous', 'vous', 'se']
       result = personne[P]
       if refl : result = result + ' ' + PR[P]
       # élision
       return self.elide(result, F)

    def RD(self, R, D):
        """ RD joint radical et désinence en gérant 
        les -e- et les cédilles."""
        if (D > '') and 'oauâû'.find(D[0]) > -1:
           if R[-1] == 'c':
              R = R[:-1] + 'ç'
           elif R[-1] == 'g':
              R = R + 'e'
        return R + D

    def compose(self, A, P, T, M, V):
       partp = self.PP()
       if string.strip(partp) > '':
            aux = conjugue(A, P, T, M, V, False)
            if aux > '':
               result =  aux + ' ' + partp
            else: return ''
            if (P > 3) and (A == 'être') and (result[-1] != 's'):
               result = result + 's'
            return result
       return ''

    # temps
    def IndPres(self, P):
       R = self.RadPres(P) 
       if R == '': return ''
       D = ['', 'e', 'es', 'e', 'ons', 'ez', 'ent']
       return self.RD(R, D[P])

    def IndFut(self, P):
        return self.RD(self.RadFut(), self.GetDesFut(P))

    def IndImpf(self, P):
        return self.RD(self.RadPres(4), self.GetDesImpf(P))
       
    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsAi(P))

    def SubjPres(self, P):
       if P == 4 or P == 5: return self.RadPres(4) + self.GetDesSubjPres(P)
       return self.RD(self.RadPres(6) , self.GetDesSubjPres(P))

    def ImperPres(self, P):
       if P == 2:
          if self.inf[-2:] == 'er': return self.inf[:-1]
          return self.IndPres(2)
       elif P == 4 or P == 5:
          return self.IndPres(P)
       return ''

    def PartPres(self):
       return self.RadPres(4) + 'ant'

    def OteReflechi(self, F):
       # éliminer le pronom réfléchi.
       if F[:2] == "s'":
          return F[2:]
       elif F[:3] == "se ":
          return F[3:]
       return F

    def PP(self):
       return self.OteReflechi(self.inf[:-2] + 'é' )

    # procédure de flexion
    def conjugue(self, P, T, M, V, pr): 
       aux = ''
       PPPP = False
       result = ''
       # vérifier la validité du champ P(ersonne)

       # pronominal
       if self.inf[:2] == "s'" or self.inf[:3] == 'se ':
          self.pronominal = True
          aux = 'être'
       else:
          self.pronominal = False
          aux = self.auxiliaire()

       # prévoir le PPPP (part. présent ou passé pronominal)
       PPPP = (M == part) and self.pronominal

       # éliminer le pronom sujet
       if M == imper or M == part or M == self.inf:
           pr = False
       
       # 1. voix
       if V == actif:
              if M == ind:   # indicatif actif
                  if T == pres: result = self.IndPres(P)
                  elif T == fut: result = self.IndFut(P)
                  elif T == impf: result = self.IndImpf(P)
                  elif T == psimple: result = self.IndPs(P)
                  else : result = self.compose(aux, P, T - 4, ind, actif)
              elif M == subj: # subjonctif actif
                  if T == pres: result = self.SubjPres(P)
                  elif T == impf:
                      if self.RadPs() > '':
                         if P == 3:
                            result = self.circonflexe() + 't'
                         else: result = self.IndPs(2)+'s'+self.GetDesSubjPres(P)
                      else : result = ''
                  elif T == pcompose: 
                     result = self.compose(aux, P, pres, subj, actif)
                  elif T == pqp: result=self.compose(aux,P,impf,subj,actif)
                  else : result = ''
              elif M == cond:
                  if T == pres:
                       # calcul à partir du futur
                       result = self.RD(self.RadFut(), self.GetDesImpf(P))
                  elif T == pcompose: 
                       result = self.compose(aux, P, pres, cond, actif)
                  else : result = ''  # '-'
              elif M == imper:
                  if P == 1 or P == 3 or P == 6:
                     # result = '-'
                     result = ''
                  else :
                     if T == pres:
                       result = self.ImperPres(P)
                     elif T == pcompose: 
                       result = self.compose(aux, P, pres, imper, actif)
              elif M == infin:  #self.inf:
                  if T == pres: result =self.inf
                  elif T == pcompose: 
                     result = self.compose(aux, P, pres, infin, actif)
              elif M == part:
                  if T == pres : result = self.PartPres() 
                  elif T == pcompose : 
                      result = self.compose(aux, P, pres, part, actif)
       elif V == passif:
              if (self.PP() > '') and (aux == 'avoir') and (self.inf != 'être'):
                   result = self.compose('être', P, T, M, actif)
              else: result = ''
       if result == '': return ''
       # éliminer le pronom 
       if len(result) > 2:
          if result[:2] == "s'":
             result = result[2:]
          elif result[:3] == "se ":
             result = result[3:] 
       if pr: result = self.Pron(P, result, self.pronominal)
       elif PPPP : result = self.elide('se', result)
       return result

class TVeter(Verbe):
    def RD(self, R, D):
       # repérer le futur/conditionnel par la finale du radical
       desR = R[-1] == 'r'
       # repérer la dernière occurence de e dans le radical
       if desR: p = string.rfind(R, 'e', 0, -3)
       else: p = string.rfind(R, 'e', 0, -1)
       # transformer en è si l''initiale de D est e 
       # ou si la finale de R est r.
       if (D[0] == 'e' and D[-1] != 'z') or desR: #R[-1] == 'r':
          R = R[:p] + 'è' + R[p+1:]
       return R + D

class  TVettell(Verbe):
    """ Verbes en -eter et -eler qui doublent leur t (ou l) 
        devant  les désinences en -e """
    def RD(self, R, D):
       # repérer le futur/conditionnel par la finale du radical
       if R[-1] == 'r':
          R = R[:-2] + R[-3] + 'er'
       elif D[0] == 'e' and D[-1] != 'z':
          R = R + R[-1]
       return R + D
      
class  TVebrer(Verbe):
    def RD(self, R, D):
       # repérer la dernière occurence de é dans le radical
       p = string.rfind(R, 'é')
       # transformer en è si l''initiale de D est e.
       if (D[0] == 'e' and D[-1] != 'z') or R[-1] == 'r':
          R = R[0:p] + 'è' + R[p+1:]
       return R + D

class TVyer(Verbe):
    def RD(self, R, D):
       # transformer en i si l''initiale de D est e.
       if D[0] == 'e' and D[-1] != 'z':
          R = R[:-1] + 'i'
       return R + D
       
    def RadFut(self):
       return self.inf[:-3] + 'ier'

class TVavoir(Verbe):

    def RadFut(self):
       return 'aur'

    def IndPres(self, P):
       D = ['', 'ai', 'as', 'a', 'avons', 'avez', 'ont']
       return D[P]

    def IndImpf(self, P):
       return self.RD('av', self.GetDesImpf(P))

    def IndPs(self, P): 
       return self.RD('e', self.GetDesPsU(P))

    def SubjPres(self, P):
       D = ['', 'aie', 'aies', 'ait', 'ayons', 'ayez', 'aient']
       return D[P]
       
    def ImperPres(self, P):
       D = ['', '', 'aie', '', 'ayons', 'ayez', ''] 
       return D[P]

    def PartPres(self):
       return 'ayant' 

    def PP(self):
       return 'eu'


class TVetre(Verbe):
    def RadFut(self):
       return 'ser'

    def RadPs(self):
       return 'f' 
       
    def IndPres(self, P):
       D = ['', 'suis', 'es', 'est', 'sommes', 'êtes', 'sont']
       return D[P]

    def IndImpf(self, P):
       return self.RD('ét', self.GetDesImpf(P))

    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def SubjPres(self, P):
       D = ['', 'sois', 'sois', 'soit', 'soyons', 'soyez', 'soient']
       return D[P]

    def ImperPres(self, P): 
       if P == 2 or P == 4 or P == 5: 
          return self.SubjPres(P)
       else : return ''

    def PartPres(self):
       return 'étant'

    def PP(self):
       return 'été' 

class TValler(Verbe):
    def RadFut(self):
       return self.inf[:-5] + 'ir' 

    def IndPres(self, P):
       D = ['', 'vais', 'vas', 'va', 'allons', 'allez', 'vont'] 
       return D[P]

    def SubjPres(self, P):
       D = self.GetDesSubjPres(P)
       if P == 4 or P == 5: return 'all' + D
       return 'aill' + D

    def ImperPres(self, P):
       if P == 2:
          return self.inf[:-5] + 'va'
       else: return Verbe.ImperPres(self, P)

class TVcueillir(Verbe):
    def PP(self):
       return self.OteReflechi(self.inf[:-2] + 'i' )
       

class TVsst(Verbe):
    def RadPres(self, P):
       return self.inf[:-2]

    def IndPres(self, P):
       R = self.RadPres(P)
       if R == None: return ''
       if P < 3: D = 's'
       elif P == 3: D = 't'
       else: return Verbe.IndPres(self, P)
       return self.RD(R, D)

    def IndPs(self, P):
      return self.RD(self.RadPs(), self.GetDesPsI(P))

    def PP(self):
       radical = self.RadPs() + 'i'
       return self.OteReflechi(radical)

# héritiers de TVsst

class TVaitre(TVsst): # paraître
    def RadPres(self, P):
       if P == 1 or P == 2: return self.inf[:-4] + 'i'
       if P == 3: return self.inf[:-3]
       return self.inf[:-4] + 'iss'

    def RadPs(self):
       return self.inf[:-5]

    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def PP(self):
       result = self.RadPs() + 'u'
       return self.OteReflechi(result)

class TVnaitre(TVaitre):
    def RadPres(self, P):
        if P < 3: return self.inf[:-4] + 'i'
        if P == 3 : return self.inf[:-3]
        return self.inf[:-4] + 'iss'
       
    def RadPs(self):
        return self.inf[:-4] + 'qu'

    def IndPs(self, P):
       return self.RadPs() + self.GetDesPsI(P) 

    def PP(self): 
       result = self.inf[:-5] + 'é' 
       return self.OteReflechi(result)

class TVpaitre(TVaitre):
    # distinguer repaître, qui a un pp.
    def IndPs(self, P):
        if self.inf == 'paître': return ''
        return self.RadPs() + self.GetDesPsU(P)

    def RadPs(self):
       return self.inf[:-5] 

    def PP(self):
       if self.inf == 'paître': return '' 
       return self.OteReflechi(self.RadPs() + 'u')

class TVboire(TVsst):
    def RadPres(self, P):
       if P < 4: return self.inf[:-2] 
       if P < 6: return self.inf[:-4] + 'uv'
       return self.inf[:-2] + 'v'

    def RadPs(self):
       return self.inf[:-4]

    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def SubjPres(self, P):
       if P == 4 or P == 5: return self.RadPres(4) + self.GetDesSubjPres(P) 
       return TVsst.SubjPres(P)

    def PP(self):
       return Self.OteReflechi(self.RadPs() + 'u')

class TVbouillir(TVsst):
    def RadPres(self, P):
       if P > 3:
          return self.inf[:-2]
       return self.inf[:-5]

class TVcevoir(TVsst):
    def RadPres(self, P):
       if P < 4: return self.inf[:-6] + 'çoi'
       if P < 6: return self.inf[:-3]
       return self.inf[:-6] + 'çoiv'

    def RadFut(self):
       return self.inf[:-3] + 'r'

    def RadPs(self):
       return self.inf[:-6] + 'c'

    def IndPs(self, P):
       return self.RD(self.RadPs(), DesPsU[P])

    def PP(self): 
       return self.OteReflechi(self.RD(self.RadPs(), 'u'))

class  TVchoir(TVsst):
    def RadPres(self, P):
       return self.inf[:-1] 

    def RadPs(self):
       return self.inf[:-3] 

    def IndPres(self, P):
       if self.inf == 'déchoir': 
          if P == 4: return self.inf[:-2] + 'yons'
          if P == 5: return self.inf[:-2] + 'yez'
       if P == 4 or P == 5: return ''
       return TVsst.IndPres(self, P)


    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsU(P)) 

    def SubjPres(self, P):
       if self.inf == 'échoir': return TVsst.SubjPres(P) 
       return ''

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVclore(TVsst):
    def RadPres(self, P):
       if P < 3: return self.inf[:-2]
       if P == 3: return self.inf[:-3] + 'ô'
       if P < 6:
          if self.inf != 'clore': return self.inf[:-2] + 's'
          return ''
       return self.inf[:-2] + 's'
    

    def IndPres(self, P):
       if self.RadPres(P) > '': return TVsst.IndPres(self, P) 
       return ''
       
    def IndPs(self, P):
       return ''

    def PP(self):
       return self.OteReflechi(self.inf[:-2] + 's' )

class TVclure(TVsst):
    def RadPs(self):
       return self.inf[:-3] 

    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u' )

class TVconfire(TVsst):
    def RadPres(self, P):
       if P < 4: return self.inf[:-2]
       if self.inf != 'frire': return self.inf[:-2] + 's'
       return ''

    def RadPs(self):
       return self.inf[:-3]

    def PP(self):
       return self.OteReflechi(self.RadPs() + 'it')

class TVcourir(TVsst):
    def RadFut(self):
       return self.inf[:-2] + 'r' 

    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def PP(self):
       return self.OteReflechi(self.RadPs() + 'u')

class TVcroire(TVsst):
    def RadPres(self, P): 
       if P == 4 or P == 5: return self.inf[:-3] + 'y'
       return self.inf[:-2]

    def RadPs(self):
       return self.inf[:-4] 

    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsU(P)) 

    def PP(self):
       return self.OteReflechi(self.RadPs() + 'u')

class TVcroitre(TVsst):
    def RadPres(self, P):
       if P < 4: return self.inf[:-3] 
       return self.inf[:-4] + 'iss'

    def RadPs(self):
       return self.inf[:-5] + 'û' 

    def IndPs(self, P):
       D = ['', 's', 's', 't', 'mes', 'tes', 'rent']
       return self.RD(self.RadPs(), D[P])

    def PP(self):
       return self.OteReflechi(self.RadPs())

class TVdevoir(TVsst):
    def RadPres(self, P):
       if P < 4: return self.inf[:-5] + 'oi' 
       if P < 6: return self.inf[:-3]
       return self.inf[:-5] + 'oiv'

    def RadFut(self):
       return self.inf[:-3] + 'r'
       
    def RadPs(self):
       return self.inf[:-5]

    def IndPs(self, P):
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def PP(self):
       return self.OteReflechi(self.RadPs() + 'û')

class TVdire(TVsst):
    def RadPres(self, P):
       if P > 0 and P < 4 :
          return self.inf[:-2]
       return self.inf[:-2] + 's'

    def RadPs(self):
       return self.inf[:-3] 

    def IndPres(self, P):
       if self.inf == 'dire' and P == 5:
          return 'dites'
       return TVsst.IndPres(self, P)

    def PP(self):
       return self.OteReflechi(self.inf[:-2] + 't')

class TVdormir(TVsst):
    def RadPres(self, P):
       if P > 3: return self.inf[:-2]
       return self.inf[:-3]

class TVecrire(TVsst):
    def RadPres(self, P):
       if P > 3: return self.inf[:-2] + 'v'
       return self.inf[:-2] 

    def RadPs(self): 
       return self.RadPres(4)

    def PP(self): 
       return self.OteReflechi(self.inf[:-2] + 't')

class TVfaillir(TVsst):
    def IndPres(self, P):
       D = ['', 'faux', 'faux', 'faut', 'faillons', 'faillez', 'faillent']
       return D[P]

class TVfaire(TVsst):
    def RadPres(self, P):
       if P > 3: return TVsst.RadPres(self, P) + 's'
       return TVsst.RadPres(self, P) 

    def RadFut(self):
       return self.inf[:-4] + 'er'

    def RadPs(self):
       return self.inf[:-4] 

    def IndPres(self, P):
       if P == 5: return self.inf[:-2] + 'tes'
       if P == 6: return self.inf[:-4] + 'ont'
       return TVsst.IndPres(self, P)

    def SubjPres(self, P):
       return self.inf[:-3] + 'ss' + self.GetDesSubjPres(P)

    def PP(self):
       return self.OteReflechi(self.IndPres(3))

class TVfuir(TVsst):
    def RadPres(self, P): 
       if P == 4 or P == 5 : return self.inf[:-2] + 'y'
       return self.inf[:-1]

class TVgesir(TVsst):
    def RadPres(self, P): 
       if P < 3: return 'gi'
       if P == 3: return 'gî'
       return 'gis'
    def IndFut(self, P): 
       return ''
    def IndPs(self, P): 
       return ''
    def PP(self): 
       return ''

class TVindre(TVsst):
    def RadPres(self, P): 
       if P < 4:
           return self.inf[:-3]
       else : return self.inf[:-4] + 'gn'

    def RadPs(self): 
       return self.RadPres(4)

    def PP(self): 
       return self.OteReflechi(self.IndPres(3))

class TVir(TVsst):
    def RadPres(self, P): 
       result = self.inf[:-1]
       if P > 3: return result + 'ss'
       return result

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsI(P))

    def PP(self): 
       return self.OteReflechi(self.inf[:-2] + 'i')

class TVlire(TVsst):
    def RadPres(self, P): 
       if P > 3: return self.inf[:-2] + 's'
       return self.inf[:-2]

    def RadPs(self): 
       return self.inf[:-3] 

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU())

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVtaire(TVlire):
    def RadPs(self): 
       return self.inf[:-4] 

    def IndPs(self, P): 
       return self.RadPs() + self.GetDesPsU(P)

class TVmettre(TVsst):
    def RadPres(self, P): 
       if P == 1 or P == 2: return self.inf[:-3] 
       if P == 3: return self.inf[:-4]
       return self.inf[:-2]

    def RadPs(self): 
       return self.inf[:-5] 

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'is')

class TVmourir(TVsst):
    def RadPres(self, P): 
       if P == 4 or P == 5: return 'mour' 
       return 'meur'

    def RadFut(self): 
       return self.inf[:-2] + 'r' 

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def PP(self): 
       return 'mort'

class TVmouvoir(TVsst):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-6] + 'eu' 
       if P < 6: return self.inf[:-3]
       return self.inf[:-6] + 'euv'
       
    def RadFut(self): 
       return self.inf[:-3] + 'r' 

    def RadPs(self): 
       return self.inf[:-6]  

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU(P))
 
    def PP(self): 
       if self.inf == 'mouvoir': return 'mû'
       return self.OteReflechi(self.RadPs() + 'u')

class TVouir(TVsst):
    def RadPres(self, P): 
       if P == 4 or P == 5: return 'oy' 
       return 'oi'

    def IndPs(self, P): 
       D = ['', 'ouïs', 'ouïs', 'ouït', 'ouîmes', 'ouîtes', 'ouïrent'] 
       return D[P]

    def PP(self): 
       return 'ouï'

class TVplaire(TVsst):
    def RadPres(self, P): 
       if P < 3: return self.inf[:-2] 
       if P == 3: return self.inf[:-3] + 'î'
       return self.inf[:-2] + 's'

    def RadPs(self): 
       return self.inf[:-4]

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVpleuvoir(TVsst):
    def IndPres(self, P): 
       if P == 3: return self.inf[:-4] + 't'
       if P == 6: return self.inf[:-3] + 'ent'
       return ''

    def RadPs(self): 
       return self.inf[:-6]

    def IndPs(self, P): 
       #if P == 3 or P == 6: return self.RD(self.RadPs(), self.GetDesPsU(P))
       return self.RD(self.RadPs(), self.GetDesPsU(P))
       return ''

    def SubjPres(self, P): 
       if P == 3 or P == 6: return self.inf[:-3] + self.GetDesSubjPres(P)
       return ''

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

    def conjugue(inf, P, T, M, V, Pr):
       if P == 3 or P == 6:
          return Verbe.conjugue(inf, P, T, M, V, Pr)
       return ''

class TVpouvoir(TVsst):
    def RadFut(self): 
       return self.inf[:-4] + 'rr'

    def RadPs(self): 
       return 'p'

    def IndPres(self, P): 
       D = ['', 'peux', 'peux', 'peut', 'pouvons', 'pouvez', 'peuvent']
       return D[P] 

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPSU(P))
       
    def SubjPres(self, P): 
       return 'puiss' + self.GetDesSubjPres(P)

    def PP(self): 
       return 'pu' 

class TVpourvoir(TVsst):
    def RadPres(self, P): 
       if P == 4 or P == 5: return self.inf[:-2] + 'y' 
       return self.inf[:-1]

    def RadPs(self): 
       return self.inf[:-3] 

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVvoir(TVsst):
    def RadPres(self, P): 
       if P == 4 or P == 5: return self.inf[:-2] + 'y' 
       return self.inf[:-1]

    def RadFut(self): 
        if self.inf == 'voir' or self.inf == 'revoir': return self.inf[:-4] + 'verr'
        return self.inf

    def RadPs(self): 
       return self.inf[:-3] 

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVquerir(TVsst):
    def RadPres(self, P): 
       R =self.inf[:-4]
       if P < 4: return R + 'ier'
       if P < 6: return R + 'ér'
       return R + 'ièr'

    def RadFut(self): 
       return self.inf[:-4] + 'err'

    def RadPs(self): 
       return self.inf[:-4]

    def PP(self): 
       return self.OteReflechi(self.IndPs(1))

class TVrire(TVsst):
    def RadPs(self): 
       return self.inf[:-3]

class TVsavoir(TVsst):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-4] + 'i' 
       return self.inf[:-3]

    def RadFut(self): 
       return self.inf[:-4] + 'ur' 

    def RadPs(self): 
       return self.inf[:-5] 

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def SubjPres(self, P):
       return self.inf[:-4] + 'ch' + self.GetDesSubjPres(P)

    def ImperPres(self, P): 
       D = ['', 'e', '', 'ons', 'ez', '']
       if D[P] > '': return self.inf[:-4] + 'ch' + D[P]
       return ''

    def PartPres(self): 
       return self.inf[:-4] + 'chant' 

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u' )

class TVservir(TVsst):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-3] 
       return self.inf[:-2]

class TVsoudre(TVsst):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-3]
       return self.inf[:-4] + 'lv'

    def RadPs(self): 
       return self.inf[:-4] + 'l'

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU(P))

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVsuivre(TVsst):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-3]
       return self.inf[:-2]

class TVvivre(TVsuivre):
    def RadPs(self): 
       return self.inf[:-4] + 'éc'

    def IndPs(self, P): 
       return self.RadPs() + self.GetDesPsU(P)

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVsurseoir(TVsst):
    def RadPres(self, P): 
       F = 'surso'
       if P == 4 or P == 5: return F + 'y'
       return F + 'i'

    def RadPs(self): 
       return self.inf[:-4]

    def IndPs(self, P): 
       if self.inf == 'seoir': return ''
       return TVsst.IndPs(P)

    def PP(self): 
       return self.OteReflechi(self.IndPs(1))

class TVvenir(TVsst):
    def RadFut(self): 
       return self.inf[:-4] + 'iendr'

    def circonflexe(self): 
       return self.inf[:-4] + 'în'

    def RadPres(self, P): 
       if P < 4: return self.inf[:-4] + 'ien'
       if P < 6: return self.inf[:-2]
       return self.inf[:-4] + 'ienn'

    def IndPs(self, P): 
       D = ['', 'ins', 'ins', 'int', 'înmes', 'întes', 'inrent']
       return self.inf[:-4] + D[P]

    def PP(self): 
       return self.OteReflechi(self.inf[:-2] + 'u')

# ne pas permuter les 2 suivants
class TVvetir(TVsst):
    def RadPres(self, P): 
       if P == 3: return self.inf[:-3] 
       return TVsst.RadPres(self, P)

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u' )

class TVtir(TVsst):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-3]
       return TVsst.RadPres(self, P)

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsI(P)) 
# ne pas permuter les 2 précédents

class TVuire(TVsst):
    def RadPres(self, P): 
       if P > 3: return TVsst.RadPres(self, P) + 's'
       return TVsst.RadPres(self, P)

    def RadPs(self): 
       return self.RadPres(4) 

    def PP(self): 
       if self.inf == 'luire' or self.inf == 'nuire':
          return self.OteReflechi(self.inf[:-2])
       return self.IndPres(3)

class TVtraire(TVsst):
    def RadPres(self, P): 
       if P == 4 or P == 5: return self.inf[:-3] + 'y'
       return self.inf[:-2] 

    def IndPs(self, P): 
       return ''

    def PP(self): 
       return self.OteReflechi(self.IndPres(3))

class TVvaincre(TVsst):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-2]
       return self.inf[:-3] + 'qu'

    def IndPres(self, P): 
       if P == 3: return self.RadPres(3)
       return TVsst.IndPres(self, P)

    def RadPs(self): 
       return self.RadPres(4)

    def PP(self): 
       return self.OteReflechi(self.inf[:-3] + 'u')

# fin des héritiers de TVsst

class TVxxt(TVsst):
    def RadPs(self): 
       return self.inf[:-3]

    def IndPres(self, P): 
       if P < 3: return self.RadPres(P) + 'x'
       return TVsst.IndPres(self, P)

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU(P))

#  héritiers de TVxxt

class TVvaloir(TVxxt):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-4] + 'u' 
       return self.inf[:-3]

    def RadFut(self): 
       return self.inf[:-4] + 'udr'

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVvouloir(TVxxt):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-6] + 'eu'
       if P < 6: return self.inf[:-3]
       return self.inf[:-6] + 'eul'

    def RadFut(self): 
       return self.inf[:-4] + 'dr'

    def SubjPres(self, P): 
       D = self.GetDesSubjPres(P)
       if D[1] == 'e': R = 'veuill'
       else : R = 'voul'
       return R + D 

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVdre(Verbe):
    def IndPres(self, P): 
       if P < 3: D = 's'
       elif P == 3: D = ''
       else : return Verbe.IndPres(self, P)
       return self.RD(self.RadPres(P), D)

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsI(P))

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

class TVasseoir(TVdre):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-4] + 'ie' 
       return self.inf[:-3] + 'y'

    def RadPs(self): 
       return inf[:-4]

    def IndPres(self, P): 
       if P < 3: D = 'ds' 
       elif P == 3: D= 'd'
       else: return TVdre.IndPres(self, P)
       return self.RD(self.RadPres(P), D) 
       
    def PP(self): 
       return self.OteReflechi(self.radPs() + 'is')

class TVcoudre(TVdre):
    def RadPres(self, P): 
       if P < 4: return TVdre.RadPres(self, P) 
       return self.inf[:-3] + 's'

    def RadPs(self): 
       return self.RadPres(4)


class TVmoudre(TVdre):
    def RadPres(self, P): 
       if P < 4: return TVdre.RadPres(self, P) 
       return self.inf[:-3] + 'l'

    def RadPs(self): 
       return self.RadPres(4)

    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsU(P))

class TVprendre(TVdre):
    def RadPres(self, P): 
       if P < 4: return self.inf[:-2]
       if P < 6: return self.inf[:-3] 
       return self.inf[:-3] + 'n'

    def RadPs(self): 
       return self.inf[:-5]

    def SubjPres(self, P): 
       D = self.GetDesSubjPres(P) 
       R = self.RadPres(4)
       if D[0] == 'e':
          R += 'n'
       return R + D

    def PP(self): 
       return self.OteReflechi(self.IndPs(1))


class TVouvrir(Verbe):
    def IndPs(self, P): 
       return self.RD(self.RadPs(), self.GetDesPsI(P))

    def PP(self): 
       return self.OteReflechi(self.inf[:-3] + 'ert')

class TVbattre(TVtir):
    def RadPres(self, P): 
       if P == 3: return self.inf[:-4]
       return TVtir.RadPres(self, P)

    def PP(self): 
       return self.OteReflechi(self.RadPs() + 'u')

AuxEtre = " advenir aller arriver décéder devenir échoir enlaidir entrer "
AuxEtre += "intervenir mourir naître obvenir partir parvenir provenir "
AuxEtre += "redevenir rentrer reparaître repartir ressortir rester "
AuxEtre += "retomber retourner revenir sortir survenir tomber venir "

Eter = " acheter racheger bégueter corseter crocheter fileter "
Eter += "fureter haleter celer déceler receler ciseler démanteler "
Eter += "écarteler encasteler geler dégeler congeler surgeler marteler "
Eter += "modeler peler "

# listeEtre = []

def IsLast(chaine, mot):
   """ vrai si mot se termine par chaine"""
   return re.search(chaine + "$", mot)

def conjugue(inf, P=1, T=1, M=1, V=1, Pr=0):
    #debog print inf, P, T, M, V, Pr
    Vb = None
    # lexique
    #  auxiliaires
    if inf == 'être':
         Vb = TVetre(inf)
    elif inf == 'avoir':
         Vb = TVavoir(inf)
    elif inf == 'pouvoir':
         Vb = TVpouvoir(inf)
    elif inf == 'vouloir':
         Vb = TVvouloir(inf)

    # autres verbes
    elif inf == 'aller':
         Vb = TValler(inf)
    elif inf == 'asservir':
         Vb = TVir(inf)
    elif inf == 'faillir':
         Vb = TVfaillir(inf)
    elif inf == 'frire' or inf == 'circoncire':
         Vb = TVconfire(inf)
    elif inf == 'gésir':
         Vb = TVgesir(inf)
    elif inf == 'mourir': 
         Vb = TVmourir(inf) 
    elif inf == 'offrir':
         Vb = TVouvrir(inf)
    elif inf == 'ouïr':
         Vb = TVouir(inf)
    elif inf == 'rire' or inf == 'sourire':
         Vb = TVrire(inf)
    elif inf == 'voir' or inf == 'prévoir' or inf == 'revoir':
         Vb = TVvoir(inf) 
    elif inf == 'se voir' or inf == 'se revoir':
         Vb = TVvoir(inf) 
    elif inf == 'surseoir':
         Vb = TVsurseoir(inf)
    elif inf == 'taire':
         Vb = TVtaire(inf)

    # variantes du premier groupe
    elif (Eter.find(' '+inf+' ') > -1) \
       or re.search("e([mnprsv]|vr)er$", inf):
         Vb = TVeter(inf)

    elif (IsLast('ébrer', inf)\
       or IsLast('écer', inf)\
       or IsLast('écher', inf) \
       or IsLast('écrer', inf) \
       or IsLast('éder', inf) \
       or IsLast('éger', inf) \
       or IsLast('égler', inf) \
       or IsLast('égner', inf) \
       or IsLast('égrer', inf) \
       or IsLast('éguer', inf) \
       or IsLast('éler', inf) \
       or IsLast('émer', inf) \
       or IsLast('éner', inf) \
       or IsLast('éper', inf) \
       or IsLast('équer', inf) \
       or IsLast('érer', inf) \
       or IsLast('éser', inf) \
       or IsLast('éter', inf) \
       or IsLast('étrer', inf) \
       or IsLast('évrer', inf) or IsLast('éyer', inf)):
         Vb = TVebrer(inf)

    elif (IsLast('eler', inf)) or (IsLast('eter', inf)):
       Vb = TVettell(inf)

    elif (IsLast('yer', inf)):
       Vb = TVyer(inf)

    # modèle général 1er groupe 
    elif (IsLast('er', inf)): 
       Vb = Verbe(inf)
       
    # naître, paître et paraître : ne pas séparer
    elif IsLast('naître', inf) and len(inf) < 7: 
       Vb = TVnaitre(inf)
    elif IsLast('paître', inf):
       Vb = TVpaitre(inf)
    elif IsLast('aître', inf):
       Vb = TVaitre(inf)
    # ne pas séparer les 3 précédentes

    elif IsLast('asseoir', inf):
       Vb = TVasseoir(inf)
    elif IsLast('battre', inf):
       Vb = TVbattre(inf)
    elif IsLast('boire', inf):
       Vb = TVboire(inf)
    elif IsLast('bouillir', inf):
       Vb = TVbouillir(inf)
    elif IsLast('cevoir', inf):
       Vb = TVcevoir(inf)
    elif IsLast('choir', inf):
       Vb = TVchoir(inf)
    elif IsLast('clore', inf):
       Vb = TVclore(inf)
    elif IsLast('clure', inf):
       Vb = TVclure(inf)
    elif IsLast('confire', inf):
       Vb = TVconfire(inf)
    elif IsLast('courir', inf):
       Vb = TVcourir(inf)
    elif IsLast('croire', inf):
       Vb = TVcroire(inf)
    elif IsLast('croître', inf):
       Vb = TVcroitre(inf)
    elif IsLast('cueillir', inf):
       Vb = TVcueillir(inf)
    elif IsLast('devoir', inf):
       Vb = TVdevoir(inf)
    elif IsLast('dire', inf):
       Vb = TVdire(inf)
    elif IsLast('dormir', inf):
       Vb = TVdormir(inf)
    elif IsLast('faire', inf):
       Vb = TVfaire(inf)
    elif IsLast('écrire', inf) or IsLast('scrire', inf):
       Vb = TVecrire(inf)
    elif IsLast('fuir', inf):
       Vb = TVfuir(inf)
    elif IsLast('lire', inf):
       Vb = TVlire(inf)
    elif IsLast('mouvoir', inf):
       Vb = TVmouvoir(inf)
    elif IsLast('ouvrir', inf):
       Vb = TVouvrir(inf)
    elif IsLast('mettre', inf):
       Vb = TVmettre(inf)
    elif IsLast('plaire', inf):
       Vb = TVplaire(inf)
    elif IsLast('pleuvoir', inf):
       Vb = TVpleuvoir(inf)
    elif IsLast('pourvoir', inf):
       Vb = TVpourvoir(inf)
    elif IsLast('prendre', inf):
       Vb = TVprendre(inf)
    elif IsLast('quérir', inf):
       Vb = TVquerir(inf)
    elif IsLast('saillir', inf):
       Vb = Verbe(inf)
    elif IsLast('savoir', inf):
       Vb = TVsavoir(inf)
    elif IsLast('servir', inf):
       Vb = TVservir(inf)
    elif IsLast('soudre', inf):
       Vb = TVsoudre(inf)
    elif IsLast('suivre', inf):
       Vb = TVsuivre(inf)
    elif IsLast('traire', inf):
       Vb = TVtraire(inf)
    elif IsLast('vaincre', inf):
       Vb = TVvaincre(inf)
    elif IsLast('venir', inf) or IsLast('tenir', inf):
       Vb = TVvenir(inf)
    elif IsLast('uire', inf):
       Vb = TVuire(inf)
    elif IsLast('valoir', inf):
       Vb = TVvaloir(inf)
    elif IsLast('vivre', inf):
       Vb = TVvivre(inf)

    # -dre
    elif IsLast('indre', inf):
      Vb = TVindre(inf)
    elif IsLast('coudre', inf):
      Vb = TVcoudre(inf)
    elif IsLast('moudre', inf):
      Vb = TVmoudre(inf)
    elif IsLast('dre', inf):
      Vb = TVdre(inf)
  
    # -tir
    elif IsLast('vêtir', inf):
      Vb = TVvetir(inf)
    elif IsLast('mentir', inf)\
      or IsLast('sentir', inf)\
      or IsLast('partir', inf)\
      or IsLast('repentir', inf)\
      or IsLast('sortir', inf):
         Vb = TVtir(inf)
  
    # 2ème groupe
    elif IsLast('ir', inf):
      Vb = TVir(inf)
  
    if Vb:
       return Vb.conjugue(P, T, M, V, Pr)
    return "je n'ai pas trouvé"
 
def conjnat(inf="aimer", P="je", T="présent", M="indicatif", V="actif", Pr=0):
    """ comme conjugue(), mais avec des paramètres chaîne 
        en langage naturel"""
    def num(C, A):
       return A.index(C)
    return conjugue(inf, num(P,personne),num(T, temps), 
         num(M, mode), num(V, voix), Pr) 

def tableau(verbe, voix):
     for m in range(1, 5):
         print "\n", mode[m]
         for t in range(1, 5):
            print string.ljust(string.upper(temps[t]), 20),
         print
         for p in range(1, 7): 
            for t in range(1, 4):
                print string.ljust(conjugue(verbe, p, t,m,voix,1), 20),
            print conjugue(verbe, p, 4,m,voix,1)
         print
         for t in range(5, 9):
            print string.ljust(string.upper(temps[t]), 20),
         print 
         for p in range(1, 7): 
            for t in range(5, 8):
               print string.ljust(conjugue(verbe, p, t,m,voix,1), 20),
            print conjugue(verbe, p, 8,m,voix,1)

# ------------------------------------------------------------            
#  Flexion des noms
# ------------------------------------------------------------            

class  Nom:
    def __init__(self, s):
       self.sing = s

    def pluriel(self):
       return self.sing + 's'

class NomSXZ(Nom):
    def pluriel(self):
       return self.sing

class NomAL(Nom):
    def pluriel(self):
       return self.sing[:-2] + 'aux'

class NomAIL(Nom):
    def pluriel(self):
       return self.sing[:-3] + 'aux'

class NomAUEU(Nom):
    def pluriel(self):
       return self.sing + 'x'

def Pluriel(n):
    als = ['bal', 'cal', 'carnaval', 'cérémonial', 
           'chacal', 'festival', 'pal', 'récital', 'régal', 'santal']
    ail = ['bail', 'corail', 'émail', 'soupirail', 
           'travail', 'vantail', 'vitrail']
    aueus = ['landau', 'sarrau', 'bleu', 'pneu', 'émeu', 'lieu (poisson)']
    oux = ['bijou', 'caillou', 'chou', 'genou', 'hibou', 'joujou', 'pou']
    inex = 'pas de pluriel'
    nom = Nom(n)
    if ['s','x','z'].count(n[-1]) == 1: nom = NomSXZ(n)
    elif n[-2:] == 'al' and als.count(n) == 0: nom = NomAL(n)
    elif n == 'bétail': return inex 
    elif n == 'ail': return 'aulx'
    elif n[-3:] == 'ail' and ail.count(n) > 0: nom = NomAIL(n)
    elif (IsLast('eu', n) or IsLast('au', n)) and aueus.count(n) == 0: 
         nom = NomAUEU(n)
    elif oux.count(n) > 0: return n + 'x'
    elif n == 'oeil': return 'yeux'
    return nom.pluriel()

    
# ------------------------------------------------------------            
#  Flexion des adjectifs
# ------------------------------------------------------------            

class Adjectif:
    def __init__(self, a):
       self.graphie = a

    def feminin(self):
       irregs = {'bénin' : 'bénigne', 
                 'bon'   : 'bonne',
                 'doux'  : 'douce',
                 'favori':'favorite',
                 'fou'   : 'folle',
                 'frais' : 'fraîche',
                 'jaloux':'jalouse',
                 'long'  : 'longue',
                 'malin' : 'maligne',
                 'mou'   : 'molle',
                 'roux'  : 'rousse'
                 }
       if irregs.has_key(self.graphie):
           return irregs[self.graphie]
       if self.graphie[-1] == 'e':
           return self.graphie
       return "%se" % (self.graphie)

    def accorde(self, g, n):
        if g == 2:
            ret = self.feminin()
        else: ret = self.graphie
        if n > 1:
            ret = Pluriel(ret)
        return ret

# irrégularités : 
# gu - guë

class Aigu(Adjectif):
    def feminin(self):
        return "%së" % (self.graphie)

class ElEil(Adjectif):
    def feminin(self):
        return "%sle" % (self.graphie)

class Al(Adjectif):
    def accorde(self, g, n): 
        if n:
            if g: return Adjectif.accorde(self, g, n)
            if ['banal','bancal','fatal','final','glacial',
                'natal','naval'].count(self.graphie) > 0:
                  return Adjectif.accorde(self, g, n)
            return self.graphie[:-1] + 'ux'
        return Adjectif.accorde(self, g, n)

class Eux(Adjectif):
    def feminin(self):
       if self.graphie == 'vieux':
           return 'vieille'
       return self.graphie[:-1] + 'se'

class Er(Adjectif):
    def feminin(self):
        return self.graphie[:-2] + 'ère'

class AdjF(Adjectif):
    def feminin(self):
        return self.graphie[:-1] + 've'

class AdjC(Adjectif):
    def feminin(self):
        irregs = {'caduc': 'caduque',
                 'grec' : 'grecque',
                 'public':'publique',
                 'sec'  : 'sèche' }
        if irregs.has_key(self.graphie):
            return irregs[self.graphie]
        return self.graphie + 'he'

class Eau(Adjectif):
    def feminin(self):
        return self.graphie[:-2] + 'lle'

class Et(Adjectif):
    def feminin(self):
        if ['complet','concret','désuet','discret','incomplet',
            'indiscret','inquiet','quiet','replet',
            'secret'].count(self.graphie):
            return self.graphie[:-2] + 'ète'
        return self.graphie + 'te'

def Accorde(adj, g, n):
    if IsLast('el', adj) or IsLast('eil', adj)\
       or adj == 'gentil' or adj== 'nul':
       inst = ElEil(adj) 
    elif IsLast('al', adj):
       inst = Al(adj)
    elif IsLast('gu', adj):
       inst = Aigu(adj)
    elif IsLast('eux', adj):
       inst = Eux(adj)
    elif IsLast('er', adj):
       inst = Er(adj)
    elif IsLast('f', adj):
       inst = AdjF(adj)
    elif IsLast('c', adj):
       inst = AdjC(adj)
    elif IsLast('eau', adj):
       inst = Eau(adj)
    elif IsLast('et', adj):
       inst = Et(adj)
    else: inst = Adjectif(adj)
    return inst.accorde(g, n)

# ------------------------------------------------------------            
#  Test 
# ------------------------------------------------------------            

if __name__ == '__main__':
   choix = raw_input("Verbes ou noms ? [nAv]")
   if choix == '': choix = 'A'
   if ['N','n'].count(choix) > 0:
      # test de Pluriel
      n = ""
      while ['Q','q'].count(n) == 0:
         n = raw_input("nom ? (q pour quitter) : ")
         if ['Q','q'].count(n) == 0:  
            print Pluriel(n)
   elif ['A', 'a'].count(choix) > 0:
      adj = ""
      while ['Q', 'q'].count(adj) == 0:
          adj = raw_input("adjectif ? (q pour quitter) : ") 
          if ['Q', 'q'].count(adj) == 0:
              print Accorde(adj,0,0)
              print Accorde(adj,1,0)
              print Accorde(adj,0,1)
              print Accorde(adj,1,1)
   else:
      # test de Conjugue
      v = ""
      while v != "q":
         av = v
         v = raw_input("verbe ? (q pour quitter) [" + av + '] ')
         if v == '': v = av
         if v != 'q': 
            tableau(v, 1)
            affP = "O"
            affP = raw_input("afficher le passif (o/n) ? [o]")
            if "Oo".find(affP) > -1: tableau(v, 2) 
