<?php
/**
 * SeekQuarry/Yioop --
 * Open Source Pure PHP Search Engine, Crawler, and Indexer
 *
 * Copyright (C) 2009 - 2026  Chris Pollett chris@pollett.org
 *
 * LICENSE:
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * @author Chris Pollett chris@pollett.org
 * @license https://www.gnu.org/licenses/ GPL3
 * @link https://www.seekquarry.com/
 * @copyright 2009 - 2026
 * @filesource
 */
namespace seekquarry\yioop\locale\it\resources;

/**
 * Italian specific tokenization code. Typically, tokenizer.php
 * either contains a stemmer for the language in question or
 * it specifies how many characters in a char gram
 *
 * @author Chris Pollett
 */
class Tokenizer
{
    /**
     * Words we don't want to be stemmed
     * @var array
     */
    public static $no_stem_list = [];
    /**
     * A list of frequently occurring terms for this locale which should
     * be excluded from certain kinds of queries
     * @var array
     */
    public static $stop_words = [
        'http', 'https',
        "ad", "al", "allo", "ai", "agli", "all", "agl", "alla",
        "alle", "con", "col", "coi", "da", "dal", "dallo", "dai",
        "dagli", "dall", "dagl", "dalla", "dalle", "di", "del",
        "dello", "dei", "degli", "dell", "degl", "della", "delle",
        "in", "nel", "nello", "nei", "negli", "nell", "negl", "nella",
        "nelle", "su", "sul", "sullo", "sui", "sugli", "sull", "sugl",
        "sulla", "sulle", "per", "tra", "contro", "io", "tu", "lui",
        "lei", "noi", "voi", "loro", "mio", "mia", "miei", "mie", "tuo",
        "tua", "tuoi", "tue", "suo", "sua", "suoi", "sue", "nostro",
        "nostra", "nostri", "nostre", "vostro", "vostra", "vostri",
        "vostre", "mi", "ti", "ci", "vi", "lo", "la", "li", "le", "gli",
        "ne", "il", "un", "uno", "una", "ma", "ed", "se", "perché",
        "anche", "come", "dov", "dove", "che", "chi", "cui", "non", "più",
        "quale", "quanto", "quanti", "quanta", "quante", "quello", "quelli",
        "quella", "quelle", "questo", "questi", "questa", "queste", "si",
        "tutto", "tutti", "a", "c", "e", "i", "l", "o", "ho", "hai", "ha",
        "abbiamo", "avete", "hanno", "abbia", "abbiate", "abbiano", "avrò",
        "avrai", "avrà", "avremo", "avrete", "avranno", "avrei", "avresti",
        "avrebbe", "avremmo", "avreste", "avrebbero", "avevo", "avevi",
        "aveva", "avevamo", "avevate", "avevano", "ebbi", "avesti", "ebbe",
        "avemmo", "aveste", "ebbero", "avessi", "avesse", "avessimo",
        "avessero", "avendo", "avuto", "avuta", "avuti", "avute", "sono",
        "sei", "è", "siamo", "siete", "sia", "siate", "siano", "sarò",
        "sarai", "sarà", "saremo", "sarete", "saranno", "sarei", "saresti",
        "sarebbe", "saremmo", "sareste", "sarebbero", "ero", "eri", "era",
        "eravamo", "eravate", "erano", "fui", "fosti", "fu", "fummo",
        "foste", "furono", "fossi", "fosse", "fossimo", "fossero",
        "essendo", "faccio", "fai", "facciamo", "fanno", "faccia",
        "facciate", "facciano", "farò", "farai", "farà", "faremo",
        "farete", "faranno", "farei", "faresti", "farebbe", "faremmo",
        "fareste", "farebbero", "facevo", "facevi", "faceva", "facevamo",
        "facevate", "facevano", "feci", "facesti", "fece", "facemmo",
        "faceste", "fecero", "facessi", "facesse", "facessimo", "facessero",
        "facendo", "sto", "stai", "sta", "stiamo", "stanno", "stia",
        "stiate", "stiano", "starò", "starai", "starà", "staremo",
        "starete", "staranno", "starei", "staresti", "starebbe", "staremmo",
        "stareste", "starebbero", "stavo", "stavi", "stava", "stavamo",
        "stavate", "stavano", "stetti", "stesti", "stette", "stemmo",
        "steste", "stettero", "stessi", "stesse", "stessimo", "stessero",
        "stando"
    ];
    /**
     * Storage used in computing the stem
     * @var string
     */
    private static $buffer;
    /**
     * Storage used in computing the starting index of region R1
     * @var int
     */
    private static $r1_start;
    /**
     * Storage used in computing the starting index of region R2
     * @var int
     */
    private static $r2_start;
    /**
     * Storage used in computing the starting index of region RV
     * @var int
     */
    private static $rv_start;
    /**
     * Storage used in computing region R1
     * @var string
     */
    private static $r1_string;
    /**
     * Storage used in computing region R2
     * @var string
     */
    private static $r2_string;
    /**
     * Storage used in computing Region RV
     * @var string
     */
    private static $rv_string;
    /**
     * Storage for computing the starting position for the longest suffix
     * @var int
     */
    private static $max_suffix_pos;
    /**
     * Storage used in determinig if step1 removed any endings from the word
     * @var bool
     */
    private static $step1_changes;
    /**
     * This method currently does nothing. For some locales it could
     * used to split strings of the form "thisisastring" into a string
     * with the words separated: "this is a string"
     *
     * @param string $pre_segment string to be segmented
     * @return string after segmentation done (same string in this case)
     */
    public static function segment($pre_segment)
    {
        return $pre_segment;
    }
    /**
     * Removes the stop words from the page (used for Word Cloud generation)
     *
     * @param mixed $data either a string or an array of string to remove
     *      stop words from
     * @return mixed $data with no stop words
     */
    public static function stopwordsRemover($data)
    {
        static $pattern = "";
        if (empty($pattern)) {
            $pattern = '/\b(' . implode('|', self::$stop_words) . ')\b/u';
        }
        $data = preg_replace($pattern, '', $data);
        return $data;
    }
    /**
     * Computes the stem of an Italian word
     * Example guardando,guardandogli,guardandola,guardano all stem to guard
     *
     * @param string $word is the word to be stemmed
     * @return string stem of $word
     */
    public static function stem($word)
    {
        self::$buffer = $word;
        self::$step1_changes = false;
        self::$max_suffix_pos = -1;
        self::prelude();
        self::step0();
        self::step1();
        self::step2();
        self::step3a();
        self::step3b();
        self::postlude();
        return self::$buffer;
    }
    /**
     * Checks if a string is a suffix for another string
     *
     * @param $parent_string is the string in which we wish to find the suffix
     * @param $substring is the suffix we wish to check
     * @return int $pos as the starting position of the suffix $substring in
     * $parent_string if it exists, else false
     */
    private static function checkForSuffix($parent_string,$substring)
    {
        $pos = strrpos($parent_string,$substring);
        if ($pos !== false &&
           (strlen($parent_string) - $pos == strlen($substring)))
            return $pos;
        else
            return false;
    }
    /**
     * Checks if a string occurs in another string
     *
     * @param string $string is the parent string
     * @param string $substring is the string checked to be a sub-string
     *      of $string
     * @return bool if $substring is a substring of $string
     */
    private static function in($string, $substring)
    {
        $pos = strpos(($string ?? ""), $substring);
        if ($pos !== false) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * Computes the starting index for region R1
     *
     * @param string $string for which we wish to find the index
     * @return int $r1_start as the starting index for R1 for $string
     */
    private static function r1($string)
    {
       $r1_start = -1;
       for ($i = 0; $i < strlen($string); $i++){
           if ($i >= 1){
               if (self::isVowel($string[$i - 1]) &&
                  !self::isVowel($string[$i])){
                   $r1_start = $i + 1;
                    break;
                }
            }
        }
        if ($r1_start != -1){
            if ($r1_start > strlen($string) - 1)
                $r1_start = -1;
            else{
                if ($string[$r1_start] == "`")
                    $r1_start += 1;
            }
        }
        return $r1_start;
    }
    /**
     * Computes the starting index for region R2
     *
     * @param string $string for which we wish to find the index
     * @return int $r2_start as the starting index for R1 for $string
     */
    private static function r2($string)
    {
        $r2_start = -1;
        $r1_start = self::r1($string);
        if ($r1_start !== -1) {
            $len = strlen($string);
            for ($i = $r1_start; $i < $len; $i++) {
                if ($i >= $r1_start + 1){
                    if (self::isVowel($string[$i - 1]) &&
                       !self::isVowel($string[$i])) {
                        $r2_start = $i + 1;
                        break;
                    }
                }
            }
        }
        if ($r2_start != -1){
            if ($r2_start > strlen($string) - 1) {
                $r2_start = -1;
            } else {
                if ($string[$r2_start] == "`") {
                    $r2_start += 1;
                }
            }
        }

        return $r2_start;
    }
    /**
     * Computes the starting index for region RV
     *
     * @param string $string for which we wish to find the index
     * @return int $rv_start as the starting index for RV for $string
     */
    private static function rv($string)
    {
        $i = 0;
        $j = 1;
        $rv_start = -1;
        $length = strlen($string);
        if ($length <= 2)
            $rv_start = -1;
        else{
            if (self::isVowel($string[$j])){
                if (self::isVowel($string[$i])){
                    for ($k = $j + 1; $k < $length; $k++){
                        if (!self::isVowel($string[$k])){
                            $rv_start = $k + 1;
                            break;
                        }
                    }
                } else {
                    $rv_start = 3;
                }
            } else {
                for ($k = $j + 1; $k < $length; $k++){
                    if (self::isVowel($string[$k])){
                        $rv_start = $k + 1;
                        break;
                    }
                }
            }
        }
        if ($rv_start != -1){
            if ($rv_start >= $length)
                $rv_start = -1;
            else{
                if ($string[$rv_start] == "`")
                    $rv_start += 1;
            }
        }
        return $rv_start;
    }
    /**
     * Computes regions R1, R2 and RV in the form
     * strings. $r1_string, $r2_string, $r3_string for R1,R2 and R3
     * repectively
     */
    private static function getRegions()
    {
        if ((self::$r1_start = self::r1(self::$buffer)) != -1) {
            self::$r1_string = substr(self::$buffer, self::$r1_start);
        } else {
            self::$r1_string = null;
        }
        if ((self::$r2_start = self::r2(self::$buffer)) != -1) {
            self::$r2_string = substr(self::$buffer, self::$r2_start);
        } else {
            self::$r2_string = null;
        }
        if ((self::$rv_start = self::rv(self::$buffer)) != -1) {
            self::$rv_string = substr(self::$buffer, self::$rv_start);
        } else {
            self::$rv_string = null;
        }
    }
    /**
     * Checks if a character is a vowel or not
     *
     * @param string $char is the character to be checked
     * @return bool if $char is a vowel
     */
    private static function isVowel($char)
    {
        return match ($char) {
            "U", "I", "`" => false,
            "a", "e", "i", "o", "u" => true,
            default => null,
        };
    }
    /**
     * Computes the longest suffix for a given string from a given set of
     * suffixes
     *
     * @param string $string for which the maximum suffix is to be found
     * @param array $suffixes an array of suffixes
     * @return int $max_suffix is the longest suffix for $string
     */
    private static function maxSuffix($string, $suffixes)
    {
        $string ??= "";
        $max_length = 0;
        $max_suffix = "";
        foreach ($suffixes as $suffix) {
            $pos = strrpos($string, $suffix);
            if ($pos !== false) {
                $string_tail = substr($string, $pos);
                $suffix_length = strlen($suffix);
                if (!strcmp($string_tail, $suffix)){
                    if ($suffix_length > $max_length){
                        $max_suffix = $suffix;
                        $max_length = $suffix_length;
                        self::$max_suffix_pos = $pos;
                    }
                }
            }
        }
        return $max_suffix;
    }
    /**
     * Replaces all acute accents in a string by grave accents and also handles
     * accented characters
     *
     * @param string $string in which the acute accents are to be
     * replaced
     * @return string with changes
     */
    private static function acuteByGrave($string)
    {
        $pattern2 = ["/á/","/é/","/ó/","/ú/","/è/",
            "/ì/","/ò/","/ù/", "/à/","/í/"];
        $replacement = ["a`","e`","o`","u`","e`",
            "i`","o`","u`","a`","i`"];
        $string = preg_replace($pattern2,$replacement,$string);
        return($string);
    }
    /**
     * Performs the following functions:
     * Replaces acute accents with grave accents
     * Marks u after q and u,i preceded and followed by a vowel as a non vowel
     * by converting to upper case
     */
    private static function prelude()
    {
        $pattern_array = ["/Qu/","/qu/"];
        $replacement_array = ["QU","qU"];
        //Replace acute accents by grave accents
        self::$buffer = self::acuteByGrave(self::$buffer);
        /**
         * Convert u preceded by q and u,i preceded and followed by vowels
         * to upper case to mark them as non vowels
         */
        self::$buffer = preg_replace($pattern_array,$replacement_array,
                       self::$buffer);
        for ($i = 0; $i < strlen(self::$buffer) - 1; $i++){
            if ($i >= 1 && (self::$buffer[$i] == "i" ||
                           self::$buffer[$i] == "u")){
                if (self::isVowel(self::$buffer[$i-1]) &&
                   self::isVowel(self::$buffer[$i+1]) &&
                   self::$buffer[$i+1] !== '`')
                    self::$buffer[$i] = strtoupper(self::$buffer[$i]);
            }
        }
    }
    /**
     * Handles attached pronoun
     */
    private static function step0()
    {
        $max = 0;
        $suffixes = ["ci","gli","la","le","li","lo",
            "mi","ne","si","ti","vi","sene",
            "gliela","gliele","glieli","glielo",
            "gliene","mela","mele","meli","melo",
            "mene","tela","tele","teli","telo",
            "tene","cela","cele","celi","celo",
            "cene","vela","vele","veli","velo","vene"];
        $phrases = ["ando","endo","ar","er","ir"];
        //Get R1, R2, RV
        self::getRegions();
        //Find the maximum length suffix in the string
        $max_suffix = self::maxSuffix(self::$rv_string,$suffixes);
        if ($max_suffix != "") {
            $sub_string = substr(self::$rv_string, 0, -strlen($max_suffix));
            foreach ($phrases as $phrase) {
                if (self::checkForSuffix($sub_string,$phrase) !== false){
                    switch ($phrase) {
                        case "ando":
                        case "endo":
                            self::$buffer = substr_replace(self::$buffer, "",
                                self::$rv_start + self::$max_suffix_pos,
                                strlen($max_suffix));
                            break;
                        case "ar":
                        case "er":
                        case "ir":
                            self::$buffer = substr_replace(self::$buffer, "e",
                                self::$rv_start + self::$max_suffix_pos,
                                strlen($max_suffix));
                            break;
                    }
                }
            }
        }
    }
    /**
     * Handles standard suffixes
     */
    private static function step1()
    {
        $suffixes = ["anza","anze","ico","ici","ica",
            "ice","iche","ichi","ismo","ismi",
            "abile","abili","ibile","ibili","ista",
            "iste","isti","ista`","iste`","isti`",
            "oso","osi","osa","ose","mente","atrice",
            "atrici","ante","anti","azione","azioni",
            "atore","atori","logia","logie","uzione",
            "uzioni","usione","usioni","enza","enze",
            "amento","amenti","imento","imenti","amente",
            "ita`","ivo","ivi","iva","ive"];
        //Get R1,R2 and RV
        self::getRegions();
        //Find the longest suffix
        $max_suffix = self::maxSuffix(self::$buffer, $suffixes);
        //Handle suffix according
        switch ($max_suffix) {
            case "anza":
                // no break
            case "anze": case "ico": case "ici": case "ica":
            case "ice": case "iche": case "ichi": case "ismo": case "ismi":
            case "abile": case "abili": case "ibile": case "ibili":
            case "ista": case "iste": case "isti": case "ista`": case "iste`":
            case "isti`": case "oso": case"osi": case "osa": case "ose":
            case "mente": case "atrice": case "atrici": case "ante":
            case "anti":
                //Delete if in R2
                if (self::in(self::$r2_string, $max_suffix)){
                    self::$buffer = substr_replace(self::$buffer,"",
                        self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                break;
            case "azione":
                // no break
            case "azioni":
            case "atore":
            case "atori":
                //Delete if in R2
                if (self::in(self::$r2_string, $max_suffix)){
                    self::$buffer = substr_replace(self::$buffer, "",
                        self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                self::getRegions();
                //If preceded by ic, delete if in R2
                if (self::checkForSuffix(self::$buffer,"ic")) {
                    if (self::in(self::$r2_string, "ic")){
                        self::$buffer = str_replace("ic", "", self::$buffer);
                        self::$step1_changes = true;
                    }
                }
                break;
            case "logia":
                // no break
            case "logie":
                //Replace with log if in R2
                if (self::in(self::$r2_string, $max_suffix)) {
                    self::$buffer = substr_replace(self::$buffer, "log",
                        self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                break;
            case "uzione":
                // no break
            case "uzioni": case "usione": case "usioni":
                //Replace with u if in R2
                if (self::in(self::$r2_string, $max_suffix)) {
                    self::$buffer = substr_replace(self::$buffer,"u",
                        self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                break;
            case "enza":
                // no break;
            case "enze":
                //Replace with ente if in R2
                if (self::in(self::$r2_string, $max_suffix)) {
                    self::$buffer = substr_replace(self::$buffer,"ente",
                        self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                break;
            case "amento":
                // no break
            case "amenti": case "imento": case "imenti":
                //Delete if in RV
                if (self::in(self::$rv_string, $max_suffix)){
                    self::$buffer = substr_replace(self::$buffer,"",
                        self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                break;
            case "amente":
                //Delete if in R1
                if (self::in(self::$r1_string, $max_suffix)){
                    self::$buffer = substr_replace(self::$buffer,"",
                                    self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                self::getRegions();
                //Check if preceded by iv, if yes, delete if in R2
                if (self::checkForSuffix(self::$buffer,"iv")){
                    if (self::in(self::$r2_string, "iv")){
                        self::$buffer = str_replace("iv", "", self::$buffer);
                        self::$step1_changes = true;
                        if (self::checkForSuffix(self::$buffer,"at")){
                            if (self::in(self::$r2_string,"at")){
                                self::$buffer = str_replace("at","",
                                    self::$buffer);
                                self::$step1_changes = true;
                            }
                        }
                    }
                } else {
                    /**
                     * Otherwise check if preceded by os,ic or abil, if yes,
                     * delete if in r2
                     */
                    self::getRegions();
                    $further = ["os","ic","abil"];
                    foreach ($further as $suffix){
                        $pos = self::checkForSuffix(self::$buffer, $suffix);
                        if ($pos !== false){
                            if (self::in(self::$r2_string, $suffix)){
                                self::$buffer = substr_replace(self::$buffer,
                                    "",$pos);
                                self::$step1_changes = true;
                            }
                        }
                    }
                }
                break;
            case "ita`":
                //Delete if in R2
                if (self::in(self::$r2_string,$max_suffix)){
                    self::$buffer = substr_replace(self::$buffer,"",
                        self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                //If further preceded by abil,ic or iv, delete if in R2
                self::getRegions();
                $further = ["abil","ic","iv"];
                foreach ($further as $suffix){
                    if (self::checkForSuffix(self::$buffer,$suffix)){
                        if (self::in(self::$r2_string,$suffix)){
                            self::$buffer = str_replace($suffix,"",
                                self::$buffer);
                            self::$step1_changes = true;
                        }
                    }
                }
                // no break
            case "ivo":
                // no break
            case "ivi":
            case "iva":
            case "ive":
                //Delete if in R2
                if (self::in(self::$r2_string, $max_suffix)){
                    self::$buffer = substr_replace(self::$buffer,"",
                        self::$max_suffix_pos,strlen($max_suffix));
                    self::$step1_changes = true;
                }
                //If preceded by at, delete if in R2
                self::getRegions();
                $pos = self::checkForSuffix(self::$buffer,"at");
                if ($pos !== false){
                    if (self::in(self::$r2_string, "at")) {
                        self::$buffer = substr_replace(self::$buffer,
                            "", $pos, 2);
                        self::$step1_changes = true;
                        //If further preceded by ic, delete if in R2
                        self::getRegions();
                        $pos = self::checkForSuffix(self::$buffer, "ic");
                        if ($pos !== false) {
                            if (self::in(self::$r2_string, "ic")) {
                                self::$buffer = substr_replace(self::$buffer,
                                    "", $pos, 2);
                                self::$step1_changes = true;
                            }
                        }
                    }
                }
        }
    }
    /**
     * Handles verb suffixes
     */
    private static function step2()
    {
        $verb_suffixes = ["ammo","ando","ano","are","arono","asse",
            "assero","assi","assimo","ata","ate","ati",
            "ato","ava","avamo","avano","avate","avi","avo",
            "emmo","enda","ende","endi","endo","era`",
            "erai","eranno","ere","erebbe","erebbero",
            "erei","eremmo","eremo","ereste","eresti",
            "erete","ero`","erono","essero","ete","eva",
            "evamo","evano","evate","evi","evo","Yamo",
            "iamo","immo","ira`","irai","iranno","ire",
            "irebbe","irebbero","irei","iremmo","iremo",
            "ireste","iresti","irete","iro`","irono","isca",
            "iscano","isce","isci","isco","iscono","issero",
            "ita","ite","iti","ito","iva","ivamo","ivano",
            "ivate","ivi","ivo","ono","uta","ute","uti",
            "uto","ar","ir"];
        /**
         * If no ending was removed in step1, find the longest suffix from the
         * above suffixes and delete if in RV
         */
        if (!self::$step1_changes) {
            //Get R1,R2 and RV
            self::getRegions();
            $max_suffix = self::maxSuffix(self::$rv_string, $verb_suffixes);
            if ($max_suffix != "" && self::in(self::$rv_string, $max_suffix))
                self::$buffer = substr_replace(self::$buffer,"",
                    self::$rv_start + self::$max_suffix_pos,
                    strlen($max_suffix));
        }
    }
    /**
     * Deletes a final a,e,i,o,a`,e`,i`,o` and a preceding i if in RV
     */
    private static function step3a()
    {
        $vowels = array ("a","e","i","o","a`","e`","i`","o`");

        //Get R1,R2 and RV
        self::getRegions();

        //If a character from the above is found in RV, delete it
        foreach ($vowels as $character) {
            $pos = self::checkForSuffix(self::$buffer,$character);
            if ($pos !== false){
                if (self::in(self::$rv_string,$character)){
                    self::$buffer = substr_replace(self::$buffer, "", $pos,
                        strlen($character));
                    break;
                }
            }
        }
        //If preceded by i, delete if in RV
        self::getRegions();
        $pos = self::checkForSuffix(self::$buffer,"i");
        if ($pos !== false){
            if (self::in(self::$rv_string,"i"))
                self::$buffer = substr_replace(self::$buffer,"",$pos,1);
        }
    }
    /**
     * Replaces a final ch/gh by c/g if in RV
     */
    private static function step3b()
    {
        //Get R1,R2 and RV
        self::getRegions();
        //Replace final ch/gh with c/g if in RV
        $patterns = ["ch","gh"];
        foreach ($patterns as $pattern) {
            switch ($pattern) {
                case "ch":
                    $pos = self::checkForSuffix(self::$buffer,$pattern);
                    if ($pos !== false){
                        if (self::in(self::$rv_string,$pattern))
                            self::$buffer = substr_replace(self::$buffer,
                                "c",$pos);
                    }
                    break;
                case "gh":
                    $pos = self::checkForSuffix(self::$buffer,$pattern);
                    if ($pos !== false){
                        if (self::in(self::$rv_string,$pattern))
                            self::$buffer = substr_replace(self::$buffer,
                                "g",$pos);
                    }
                    break;
            }
        }
    }
    /**
     * Converts U and/or I back to lowercase
     */
    private static function postlude()
    {
        $pattern_array_1 = ["/U/","/I/"];
        $replacement_array_1 = ["u","i"];
        $pattern_array_2 = ["/a`/","/e`/","/i`/","/o`/","/u`/"];
        $replacement_array_2 = ["à","è","ì","ò","ù"];
        self::$buffer = preg_replace($pattern_array_1, $replacement_array_1,
            self::$buffer);
        self::$buffer = preg_replace($pattern_array_2, $replacement_array_2,
            self::$buffer);
    }
}
