#!/usr/bin/python
# -*- coding:cp1252 -*-
# Découpage lexical avancé pour le français - 14.11.2004, version 1.1 du 12.07.2015, par Vincent Comiti, http://cadrat.saynete.net - Python 2 et 3.

import sys # Module des informations systèmes, pour compatibilité entre Python 2 et 3
import string # Module des chaînes de caractères
import re # Module des expressions régulières

# Compatibilité Python 2 et 3 - Détermine version
def SysVersionPython():
    return (sys.version_info[0])

# Compatibilité Python 2 et 3 - Transforme minuscule en majuscule 
def ChaineMajusculeSys(chaine):
    compatibillite = SysVersionPython()
    if (compatibillite==2):return string.upper(chaine)
    if (compatibillite==3):return chaine.upper()
    
def DecoupPonc(corp,lis):
# Découpage de forme, par Liste, boucle et remplacement.
# Chaque élément d'une liste est remplacé par celui immédiatement à droite, progressant de deux en deux.
# Le principe de la liste binome est pratique, donc réutilisable. Elle va essentiellement servir à la ponctuation.

    for m in range(0,len(lis),2): # Boucle
       corp=corp.replace(lis[m],lis[m+1]) # Remplacement d'un élément. 

    return corp # Renvoie la valeur corp modifiée (le corpus textuel).

def DecoupPonc_maj(corp,lis):
# Découpage de la ponctuation majuscule, par Liste, boucle et remplacement.
# Procédure semblable à DecoupPonc mais tenant compte d'une majusculee n début du mot.

    for m in range(0,len(lis),2): # Boucle où chaque élément d'une liste est remplacé par celui immédiatement à droite, progressant de deux en deux.
        lis_u=ChaineMajusculeSys(lis[m][0])+lis[m][1:len(lis[m])] # Pour la première forme, le premier caractère de la chaîne est changé en majuscule, et le reste recopié tel quel.
        lis_up=ChaineMajusculeSys(lis[m+1][0])+lis[m+1][1:len(lis[m+1])] # Idem que le précédent, pour la seconde forme.
        corp=corp.replace(lis_u,lis_up) # Remplacement d'un élément par un autre.

    return corp # Renvoie la valeur corp.

def DecoupComp(corp):
# Découpage des verbes et pronoms, par Liste, boucle et remplacement.
# La méthode consiste à remplacer chaque forme à trait d'union part des espaces, et entourer celle-ci : <->

# Liste des formes susceptibles d'être découpées 
    lis_com = ["nous","vous","les","la","là","leurs","je","tu","ils","elles","ci","mêmes","eux","lui","moi","toi","en","y","t","ce","on","-","il","elle","même","le","leur"]


    for n in range(len(lis_com)): # Boucle de parcours de la liste précédente.
        un="-"+lis_com[n]+"-" # Chaîne où une forme se trouve prise entre deux traits d'union.
        deux=" <-> "+lis_com[n]+ " <-> " # Chaîne avec les blancs et le trait d'union entouré.
        corp=corp.replace(un,deux) # Remplacement de la première chaîne par la deuxième.
        un_fin="-"+lis_com[n]+" " # Chaîne où une forme se trouve prise entre un trait d'union et un blanc.
        deux_fin=" <-> "+lis_com[n]+" " 
        corp=corp.replace(un_fin,deux_fin) 

    return corp # Renvoie la valeur corp (pour corpus) modifiée.


def DecoupAcro(corp):
# Découpage des acronymes et mots abrégés, par Expressions régulières.
# La méthode consiste à répérer les combinaisons majuscule + point + majuscule.
# Il s'agit de remplacer tout point qui n'est pas une ponctuation forte par le dièse. 

# En cas de cumul de ponctuation accolée, les points de suspension sont changés #. (De nombreuses combinaisons sont possibles)
    corp=corp.replace("...;","###;") 

# Mot abrégé, S.N.C.M.
# \w signifie n'importe quel caractère alphanumérique, \. signifie un point
# Les expressions entre paranthèses comme (\w) peuvent être conservées, afin d'être remplacée par elle-même. Elles deviennent \\1 dans l'instruction suivante (puis \\2 puis \\3...)

# Initiale et suite du mot abrégé, S.N 
    for a in range(2): # Répétition de l'instruction afin de compléter entièrement l'abréviation.
        mod=re.compile("(\w)\.(\w)") # La variable mod devient un (/w) suivi d'un point \. et d'un autre (\w)
        corp=mod.sub("\\1#\\2",corp) # mod est remplacé par le caractère entre paranthèse (\w) conservé, puis le second caractère le point permute avec le dièse, enfin le troisème (\w) est aussi conservé.

# Fin du mot abrégé, M.
    mod=re.compile("#(\w)\.")
    corp=mod.sub("#\\1#",corp)

# Abréviations G...
# Une majuscule plus point de suspension suivi d'un blanc et d'une minuscule est une abréviation.
# Ce découpage entraîne une erreur si une phrase commence sans majuscule (pour le point)
    mod=re.compile("([A-Z]|[À-Ý])\.\.\. ([a-z]|[à-ý]|[!-@])") # [A-Z]|[À-Ý] signifie tous les caractères entre A et Z, c'est à dire l'alphabet majuscule et | les mêmes avec les diacritiques
    corp=mod.sub("\\1### \\2",corp)

# Abréviations 18... (pour une date intentionnellement floue)
# Une majuscule plus point de suspension suivi d'un blanc et d'une minuscule est une abréviation.
    mod=re.compile("( [0-9][0-9])\.\.\. ([a-z]|[à-ý]|[!-@])")
    corp=mod.sub("\\1### \\2",corp)

# Abréviations G.
    mod=re.compile("([A-Z]|[À-Ý])\. ([a-z]|[à-ý])")
    corp=mod.sub("\\1# \\2",corp)

    return corp # Renvoie la valeur corp


def Format(corp):
# Découpage du texte corp, par appel des Procédures. 

    # Procédure principale usant de la découpe des mots-composés et de la ponctuation.
    corp=DecoupAcro(corp)

    # La méthode utilise le principe binome, c'est à dire une ponctuation remplacée par un blanc + elle-même.
    # La progression est importante, afin d'éviter le chevauchement du point et des points de suspension (pachopacho).
    mot_ponc=['"',' " ',"...","pachopacho","."," .","pachopacho"," ...",","," ,","(","( ",")"," )","'","' "]
    corp=DecoupPonc(corp,mot_ponc)

    # Première série d'exception. Le principe binome est appliqué pour recoller les mots composés à apostrophe, et les problèmes générés par le décollage. 
    mot_fus=["aujourd' hui","aujourd'hui","pin' s","pin's","presqu' île","presqu'île","m' as-tu-vu","m'as-tu-vu","prud' ","prud'","entr' ","entr'","jusqu' au-bout","jusqu'au-bout","je-m' en-","je-m'en-","-l' ","-l'","-d' ","-d'","d' abord","d'abord","quelqu' un","quelqu'un","mm .","mm.","MM .","MM.", "M .","M.","[ ...]","[...]"]
    corp=DecoupPonc(corp,mot_fus)
    corp=DecoupPonc_maj(corp,mot_fus)

    # Découpage des verbes et pronoms.
    corp=DecoupComp(corp)

    # Rétablissement des points de suspension par le point.
    corp=corp.replace("#",".")

    return corp # Renvoie la valeur corp (le corpus textuel) modifiée

corpus="""Aujourd'hui M. Jean s'est exclamé, en allumant sa T.S.F. : "Bonjour, Monde !".""" # Triple guillemets pour inclure les guillemets et les apostrophes.
corp=Format(corpus) # Lance la procédure principale

texte_sorti = "Content-type: text/html\n\n"
texte_sorti +=corp

print (texte_sorti)
