
/*
 *      Eindeutige Angaben:
 *          das Buch                "Buch", neuter             
 *          (der) Georg             "Georg", male proper
 *          der rote Ball           "rot@00 Ball", male
 *          [d]ein alter Stock      "alt@00 Stock" male
 *          [d]ein neues Auto       "neu@00 Auto", neuter
 *          eine Strickjacke        "Strickjacke", female
 *          die anderen Leute       "ander@00", pluralname
 *          die schwere Eisentür    "schwer@00 Eisentür", female
 *          die Zeitung             "Zeitung" female, wegen -ung
 *      
 *      Mehrdeutige Angaben:
 *          Holzscheite             pluralname (female)
 *          die Taschenuhr          female (pluralname)
 *          mein Hut                male (neuter)
 *
 *      Zusatzangaben:
 *          meine Mundharmonika     article yours
 *          DAS Buch der Weisheit   article definite
 *          das (etwas) Wasser      article no_article
 *          die (etwas) H-Milch     article no_article
 *
 *      Endungen
 *          der Beamt(e)            "Beamt@00"
 *          Regale(n)               "Regale@01"
 *          der Mensch(en)          "Mensch@02"
 *          das Messer(s)           "Messer@03
 *          das Haus(es)            "Haus@04"
 *          
 *      Trennungen:
 *          die Haus=tür            "Haustür", 'haustuer' 'tuer'
 *          das CDU-Plakat          "CDU-Plakat", 'cdu-plakat' 'plakat'
 *          das rot-weiße Hemd      "rot-weiß@00 Hemd" 
 *                                  'rot' 'weiss' 'rot-weiss' 'hemd'
 *          der blau=grüne See      "blaugrün@00 See" 
 *                                  'blau' 'gruen' 'braugruen' 'see'
 */
 
var example = -1;

var defaults = [
    "mein abgewetzter Geld=beutel/das alte Portemonnaie/das Portmonee/die Geld=börse",
    "die \"Bild der Frau\"/das Frauen=magazin/die Frauen=zeitschrift",
    "ein schon arg verrostetes Schaufel=blatt/die Schaufel",
    "der 15er Schrauben=schlüssel",
    "der Oberschenkelknochen eines Rinds/der Ober=schenkel des Rinds/der Rinder=knochen",
    "die (etwas) H-Milch",
    "(etwas) säuberlich gestapeltes Brenn=holz",
    "der Schlüssel für Zimmer Nummer 4/der Zimmerschlüssel #4",
    "(die) Hans' Mund=harmonika/die original Hohner von Hans",
    "verschiedene Kisten und Kartons",
    "DIE \"Andrea Doria\"/das Passagier=schiff/das Linienschiff",
    "der hohe Aussichts=turm",
    "der trockene Rotwein, 2003er Lese/roter Wein",
    "DIE obere Schublade/das Schub=fach",
    "der linke Garten=handschuh",
    "der rosa Plüschelefant(en)/das große Plüsch=tier/das Kuscheltier",
    "das Modell eines Dreimasters in einer Flasche/Flaschenschiff/Buddel=schiff/Segelschiff/Buddel/Bark/Schiffsmodell",
    "die kleine, leicht zu bedienende Kamera/der Foto=apparat",
    "das Q aus einem Scrabble-Spiel/der Buchstabe(n)",
    "der Jura=student(en)",
    "der VWL-Student(en)",
    "Klein=gärtnerin",
    "der Bus nach Eckmannshausen/die Linie 62",
    "das Ångström-Mess=gerät",
    "die Salade Niçoise/der Nizza-Salat",
    "(der) Herr Becker/der Mann",
    "(die) Felicitas Freifrau zu Hohenstein",
    "das große Glas frisch gepresster Orangensaft",
    "der Bote(n) des Zaren/der Reiter/(der) Michail Strogoff",
    "Holz=bretter(n)/Holz=latten/das holz"
];

function next_example()
{
    if (example < 0) {
        example = Math.floor(defaults.length * Math.random());
    }
    example++;
    if (example >= defaults.length) example = 0;
    
    var text = defaults[example].replace(/\//g, "\n");
    var words = document.getElementById("words");
    if (words) words.value = text;
}

var opt = {
    target: "i6",           //  I6- oder I7-Code erzeugen
    idstyle: "underscore",  //  Bezeichner mit:
                            //  underscore: blaues_Buch, Glas_Milch, CD-Huelle
                            //  camel: blauesBuch, GlasMilch, CdHuelle
                            //  pascal: BlauesBuch, GlasMilch, CdHuelle
    prune: false,           //  Vokabeln nach 9 Zeichen 'abschneid'-en?
    marklimit: true,        //  '9er-Gre|nze' markieren?
    longwords: false,       //  Lange Wörter in parse_name berücksichtigen?
    gender: true,           //  Changing Gender zu Vokabeln angeben?
    comments: true          //  Risiken in Kommentaren anmerken.
};

var charset = {
    "ä": "ae",   "ö": "oe",   "ü": "ue",   "Ä": "Ae",   "Ö": "Oe",   "Ü": "Ue",  
    "ß": "ss",   "»": "",     "«": "",     "ë": "e",    "ï": "i",    "ÿ": "y",  
    "Ë": "E",    "Ï": "I",    "á": "a",    "é": "e",    "í": "i",    "ó": "o",  
    "ú": "u",    "ý": "y",    "Á": "A",    "É": "E",    "Í": "I",    "Ó": "O",  
    "Ú": "U",    "Ý": "Y",    "à": "a",    "è": "e",    "ì": "i",    "ò": "o",  
    "ù": "u",    "À": "A",    "È": "E",    "Ì": "I",    "Ò": "O",    "Ù": "U",  
    "â": "a",    "ê": "e",    "î": "i",    "ô": "o",    "û": "u",    "Â": "A",  
    "Ê": "E",    "Î": "I",    "Ô": "O",    "Û": "U",    "å": "a",    "Å": "A",  
    "ø": "oe",   "Ø": "Oe",   "ã": "a",    "ñ": "nh",   "õ": "o",    "Ã": "A",  
    "Ñ": "NH",   "Õ": "O",    "æ": "ae",   "Æ": "AE",   "ç": "c",    "Ç": "C",  
    "þ": "th",   "ð": "th",   "Þ": "Th",   "Ð": "Th",   "£": "L",    "œ": "oe",  
    "Œ": "OE",   "¡": "!",     "¿": "?"
}

var common_endings = {
    chen: "n", lein: "n", ei: "f", er: "m", heit: "f", ion: "f",
    "in": "f", keit: "f", ling: "m", schaft: "f", tum: "n", ung: "f",
    eien: "p", heiten: "p", ionen: "p", innen: "p", keiten: "p", 
    linge: "p", schaften: "p", tümer: "p", ungen: "p"
};

var prepositions = {
    ab: true, an: true, auf: true, aus: true, bei: true, durch: true,
    fuer: true, gegen: true, hin: true, hinter: true, "in": true, mit: true,
    nach: true, neben: true, ueber: true, unter: true, um: true,
    von: true, vor: true, zu: true, zwischen: true,
    der: true, die: true, das: true, dem: true, den: true, des: true, 
    ein: true, eine: true, einer: true, einem: true, eines: true, einen: true, 
    zwei: true, drei: true, vier: true, fuenf: true, sechs: true, 
    und: true
};

var gender = {
    m:  {
        has: "male",
        article: "der",
        possesive: "dein",
        suffix: "er"
    },
    f:  {
        has: "female",
        article: "die",
        possesive: "deine",
        suffix: "e"
    },
    n:  {
        has: "neuter",
        article: "das",
        possesive: "dein",
        suffix: "es"
    },
    p:  {
        has: "pluralname",
        article: "",
        possesive: "deine",
        suffix: "e"
    }
};

var lowstrings = {
    e: "@00",
    n: "@01",
    en: "@02",
    s: "@03",
    es: "@04"
};

var obj;

function asciify(str)
{
    var c = str.split("");
    for (var i = 0; i < c.length; i++) {
        if (c[i] in charset) c[i] = charset[c[i]];
    }
    return c.join("");
}

function is_upper(str)
{
    str = str.replace(/^["'*]+/, "");
    if (!str) return false;
    
    if (str.match(/^[A-Z]/)) return true;
    if (str.charCodeAt(0) < 128) return false;
    
    c = str.charAt(0);
    if (c in charset) {
        c = charset[c].charCodeAt(0);
        if (c > 64 && c < 91) return true;
    }
    return false;
}

function is_lower(str)
{
    str = str.replace(/^["'*]+/, "");
    if (!str) return false;
    
    if (str.match(/^[a-z]/)) return true;
    if (str.charCodeAt(0) < 128) return false;
    
    c = str.charAt(0);
    if (c in charset) {
        c = charset[c].charCodeAt(0);
        if (c > 96 && c < 123) return true;
    }
    return false;
}

function clean(str, ref)
{
    if (ref == "short_name") {
        str = str.replace(/@/g, "@@64");
        str = str.replace(/\^/g, "@@94");
        str = str.replace(/\\/g, "@@92");
        str = str.replace(/~/g, "@@126");
        str = str.replace(/"/g, "~");
        str = str.replace(/=/g, "");
    }
    if (ref == "dword") {
        str = str.replace(/'/g, "^");
        str = str.replace(/[\[\](){}.,;:?!="]/g, "");
    }
    if (ref == "id") {
        str = str.replace(/[^-\w]/g, "");
    }
    if (ref == "i7-id") {
        str = str.replace(/[^-\s\w]/g, "");
    }
    return str;
}

function find_gender(entry, value)
{
    for (var g in ["m", "f", "n", "p"]) {
        if (gender[g][entry] == value) return g;
    }
    return undefined;
}

function determine_gender(wd, article, suffix)
{
    var g;
    
    if (article == "der") return "m";
    if (article == "das") return "n";
    // "die" ist mehrdeutig: f oder p
    
    if (article == "eine") return "f";
    // "ein" ist mehrdeutig: m oder n
    
    if (suffix) {
        
        if (article == "die") {
            if (suffix == "e") return "f";
            return "p";
        }
        if (article == "etwas" && suffix == "e") return "f";
        
        // noch kein Artikel oder "ein" angegeben
        
        if (suffix == "er") return "m";
        if (suffix == "es") return "n";
        // "e" ist mehrdeutig: f oder p
    }
    
    // auf häufig vorkommende Substantivendungen schauen
    // (Deaktiviert, weil man falsche Annahmen nicht korrigieren kann.)
    if (false) {
        for (var end in common_endings) {
            var re = new RegExp(end + "$");
            if (wd.match(re)) return common_endings[end];
        }
    }
    
    // Zwischen "ein Mann" und "ein Haus" kann nicht aufgelöst werden
    if (article == "ein") {
        comment("Als Genus wurde das Neutrum angenommen,");
        comment("zur Klärung 'der' oder 'das' angeben.");
        return "n";
    }
    
    // Letzter Ausweg: "die" bedeutet f, kein Artikel bedeutet p
    if (article == "die") return "f";
    return "p";
}

function dict_word(wd, type, g, prune)
{
    //  Adjektivendungen einem Substantiv folgender Wörter abscheniden:
    //  großes Glas frische Milch: 'gross' 'glas' 'frisch' 'milch'
    if (prune && !(wd in prepositions)) {
        if (is_lower(wd)) {
            wd = wd.replace(/e[rs]?$/, "");
        }
    }

    var dw = clean(asciify(wd), "dword").toLowerCase();
    var orig_dw = dw;
    
    var ix = -1;
    var count = 0;
    var chars = dw.split("");
    var A2 = "0123456789.,!?_#'\"/\\-:()";
    
    for (var i = 0; i < chars.length; i++) {
        var c = chars[i];
        if (c >= 'a' && c <= 'z') {
            count++;
        } else if (A2.indexOf(c) > -1) {
            count += 2;
        } else {
            count += 4;
        }
        if (count > 9) {
            ix = i;
            break;
        }
    }
    
    if (ix > 0) {
        if (opt["prune"]) {
            dw = dw.substr(0, ix);
        } else if (opt["marklimit"]) {
            dw = dw.substr(0, ix) + "|" + dw.substr(ix);
        }
    }
    
    return {
        dword: dw, 
        word: orig_dw, 
        type: type, 
        gender: g,
        long: (ix > -1)
    };
}

function add_name(word, type, g, prune, first)
{
    if (!word) return;

    if (word.match(/[=-]/)) {
        var ix = word.search(/[=-]/);
        
        if (type == "adj") {
            add_name(word.substr(0, ix), type, g, prune, false);
        }
        add_name(word.substr(ix + 1), type, g, prune, false);
    }
    if (first == false || opt["target"] == "i6") {
        obj["name"].push(dict_word(word, type, g, prune));
    }
}

function comment(blurb)
{
    obj["comment"].push(blurb);
}

function make_id(comp)
{
    var us = "";
    var id = "";
    
    for (var i = 0; i < comp.length; i++) {
        var c = clean(asciify(comp[i]), "id");
        
        if (opt["idstyle"] != "underscore") {
            c = c.toLowerCase()
            if (opt["idstyle"] == "pascal" || i) {
                c = c.substr(0, 1).toUpperCase()
                    + c.substr(1).toLowerCase();
            }
        } else {
            id += us;
            us = "_";
        }
        
        if (c.match(/-/)) {
            if (opt["idstyle"] == "underscore") {
                c = c.replace(/-/g, "_");
            } else {
                var cc = c.split(/-/);
                for (var j = 1; j < cc.length; j++) {
                    cc[j] = cc[j].substr(0, 1).toUpperCase()
                        + cc[j].substr(1).toLowerCase();
                }
                c = cc.join("");
            }
        }
        id += c;
    }    
    return id;
}

function parse_line(line, first)
{
    line = line.replace(/,/g, " , ");
    line = line.replace(/^\s+/, "");
    line = line.replace(/\s+$/, "");
    
    if (!line) return false;
    
    var words = line.split(/\s+/);
    var article;
    var suffix;
    var short_name = [];
    var idcomp = [];
    var after_subst = false;
    var g;
    
    if (!words.length) return false;
    
    // 1 // Prüfen, ob ein Artikel angegeben wurde
    
    if (words[0].match(/^(DER|DIE|DAS)$/)) {
        obj["article"] = "definite";
    }
    
    if (words[0].match(/^[(](der|die|das)[)]$/i)) {
        words[0] = words[0].substr(1, 3);
        obj["has"].push("proper");
    }
    
    if (words[0].match(/^(der|die|das)$/i)) {
        article = words[0].toLowerCase();
        words.shift();
    }
        
    if (words[0] == "(etwas)") {
        obj["article"] = "no_article";
        words.shift();
        if (!article) article = "etwas";
    }
    
    if (words[0].match(/^[md]?eine?$/i)) {
        if (words[0].match(/^[md]/)) {
            obj["article"] = "yours";
            add_name("mein", "adj", null, false, false);
            add_name("dein", "adj", null, false, false);
            article = words[0].substr(1);
            if (article.match(/e$/)) article = "die";
            // Mehrdeutigkeit zwischen f und p, die es bei "eine" nicht gibt
        } else {
            article = words[0];
        }
        words.shift();
    }
    
    // 2 // Alle Wörter nacheinander abarbeiten
    
    for (var i = 0; i < words.length; i++) {
        var wd = words[i];
        
        if (is_lower(wd)) {
            // Adjektiv oder Adverb
        
            if (after_subst) {
                // Alles wörtlich übernehmen
                short_name.push(wd);
                idcomp.push(wd);
            } else {
                var re = /(e[mnrs]?)$/;
                if (wd.search(re) > -1) {
                    // Adjektiv
                    suffix = wd.match(re).shift();
                    wd = wd.replace(re, "");
                    short_name.push(clean(wd, "short_name") + "@00");
                    idcomp.push(wd + "~e");
                } else {
                    // Adverb
                    short_name.push(clean(wd, "short_name"));
                    idcomp.push(wd);
                }
            }
            add_name(wd, "adj", null, after_subst, first);
        
        } else if (is_upper(wd)) {
            // Substantiv
            
            if (!g) {
                // Noch kein Genus bekannt: raten
                g = determine_gender(wd, article, suffix);
            }
            
            var low = "";
            var lowkey = "";
            var re = /[(]-?e?[ns]?[)]$/;
            if (wd.match(re)) {
                // Nachgestelle Endung: Löffel(n), Haus(es), usw.
                lowkey = wd.match(re).shift();
                lowkey = lowkey.replace(/\W/g, "");
                low = (lowkey in lowstrings) ? lowstrings[lowkey] : "";
                wd = wd.replace(re, "");
            }
            
            short_name.push(clean(wd, "short_name") + low);
            idcomp.push(wd + lowkey);
            add_name(wd, "subst", g, false, first);
            after_subst = true;
        
        } else {
            // Etwas anderes, z.B. Satzzeichen, Zahlen
        
            if (wd.match(/^[,.;:?!]$/)) {
                // Satzzeichen: nur für den short_name
                short_name.push(wd);
                continue;
            }
            
            if (wd.match(/^\d+(er)?$/)) {
                // 1948er Mouton-Rothschild: als Adverb betrachten
                short_name.push(clean(wd, "short_name"));
                if (idcomp.length) idcomp.push(wd);
                add_name(wd, "adj", null, false, first);
                continue;
            }
            
            // Rest: auch als Adverb betrachten
            short_name.push(clean(wd, "short_name"));
            if (idcomp) idcomp.push(clean(wd, "id"));
            add_name(wd, "adj", null, false, first);
        }
    }
    
    if (first) {
        if (!g) {
            // Noch kein Genus bekannt: raten
            comment("Der Objektname hat kein Substantiv!");
            g = determine_gender(wd, article, suffix);
        }
        
        for (var i = 0; i < idcomp.length; i++) {
            idcomp[i] = idcomp[i].replace(/~e$/, gender[g]["suffix"]);
        }
        obj["id"] = make_id(idcomp);
        obj["has"].push(gender[g]["has"]);
        obj["refgender"] = g;
        
        var sn = "";
        for (var i = 0; i < short_name.length; i++) {
            var wd = short_name[i];
            
            if (wd.match(/^[,.;:?!]/)) {
                sn += wd;
                continue;
            }
            if (i) sn += " ";
            sn += wd;
        }
        obj["short_name"] = sn;
    }
    return true;
}

function i6code()
{
    var cd = "";
    var maxpos = 56;
    
    if (obj.comment.length) {
        for (var i = 0; i < obj.comment.length; i++) {
            cd += "! " + obj.comment[i] + "\n";
        }
        cd += "\n";
    }
    
    // Bezeichner auf 32 Zeichen stutzen, sonst meckert Inform
    if (obj["id"].length > 32) {
        if (opt["idstyle"] == "underscore") {
            obj["id"] = obj["id"].replace(/([A-Z][a-z]+)_.*$/, "$1");
            while (obj["id"].length > 32) {
                obj["id"] = obj["id"].replace(/^[^_]+_/, "");
            }
        } else {
            while (obj["id"].length > 32) {
                obj["id"] = obj["id"].replace(/[A-Z][a-z]*$/, "");
            }
        }
    }

    cd += " Object -> " + obj["id"];
    if (obj["short_name"].length 
        + obj["id"].length + 13 > maxpos) {
        cd += "\n       ";
    }
    cd += " \"" + obj["short_name"] + "\"\n";
    cd += "   with name";
    
    // 'name' ordentlich formatiert ausgeben
    var pos = 12;
    var longwords = 0;
    var prep = 0;
    
    for (var i = 0; i < obj["name"].length; i++) {
        var dw = obj["name"][i];
        if (opt["longwords"] && dw["long"]) {
            longwords++;
            continue;
        }
        if (dw["dword"] in prepositions) {
            prep++;
            continue;
        }
        
        var entry = " '" + dw.dword 
            + ((dw.dword.length == 1) ? "//" : "")
            + "'";
        
        if (opt["gender"] && dw.gender 
            && dw.gender != obj["refgender"]) {
            entry += " '" + dw.gender + ".'";
        }
        if (pos + entry.length > maxpos) {
            cd += "\n           ";
            pos = 11;
        }
        cd += entry;
        pos += entry.length;
    }
    cd += ",\n";
    
    // 'parse_name' für Wörter mit Präspositionen
    if (prep) {
        cd += "        prep";
        for (var i = 0; i < obj["name"].length; i++) {
            var dw = obj["name"][i];
            if (!(dw["dword"] in prepositions)) continue;
            
            var entry = " '" + dw.dword + "'";
            cd += entry;
        }
        cd += ",\n        parse_name [ n m wd;\n            while(";
        if (longwords) {
            for (var i = 0; i < obj["name"].length; i++) {
                var dw = obj["name"][i];
                if (dw["long"] == false) continue;
                cd += "WordMatch(\"" + dw.word + "\")\n                || ";
            }
            longwords = 0;
        }
        cd += "WordInProperty(wd = NextWord(),\n";
        cd += "                self, name)\n";
        cd += "                || WordInProperty(wd, self, prep)) {\n";
        cd += "                m++;\n";
        cd += "                if (~~WordInProperty(wd,\n"; 
        cd += "                    self, prep)) n = m;\n";
        cd += "            }\n";
        cd += "            return n;\n";
        cd += "        ],\n";
    }
    
    // 'parse_name' für lange Wörter
    if (longwords) {
        cd += "        parse_name [ n;\n            while(";
        for (var i = 0; i < obj["name"].length; i++) {
            var dw = obj["name"][i];
            if (dw["long"] == false) continue;
            cd += "WordMatch(\"" + dw.word + "\")\n                || ";
        }
        cd += "WordInProperty(NextWord(),\n";
        cd += "                self, name)) n++;\n";
        cd += "            return n;\n";
        cd += "        ],\n";
    }
    
    if ("article" in obj) {
        cd += "        article " + obj.article + ",\n";
    }
    
    cd += "    has";
    
    for (var i = 0; i < obj["has"].length; i++) {
        cd += " " + obj["has"][i];
    }
    cd += ";\n";
    
    return cd;
}

function i7code()
{
    //  Übersetzt aus dem I6-Code, also vermutlich nicht ganz lupenrein
    var proper = false;
    
    if (obj["has"][0] == "proper") {
        // "proper" extrahieren. Nun gibt es nur noch das Genus-Attribut
        proper = true;
        obj["has"].shift();
    }
    
    cd = "";
    if (!proper) cd += "The ";
    
    var sn = obj["short_name"];
    sn = sn.replace(/@@(\d+)/g, "[unicode $1]");
    sn = sn.replace(/@00/g, "[^]");
    sn = sn.replace(/@01/g, "[-n]");
    sn = sn.replace(/@02/g, "[-en]");
    sn = sn.replace(/@03/g, "[-s]");
    sn = sn.replace(/@04/g, "[-es]");
    sn = sn.replace(/'/g, "[']");
    sn = sn.replace(/~/g, "'");
    
    var id = clean(asciify(sn), "i7-id");
    id = id.replace(/"/g, "");
    id = id.replace(/[\^]/g, "");
    id = id.replace(/\[[^\]]*\]/g, "");
    id = id.replace(/-(e?[ns])$/, "");
    cd += id;
    
    var g = obj["has"].shift();
    if (g == "pluralname") {
        cd += " are a thing. ";
    } else {
        cd += " is a " + g + " thing. ";
    }
    if (id != sn) {
        cd += "The printed name of it is \"" + sn + "\". ";
    }
    
    if ("article" in obj) {
        obj.article = obj.article.replace(/_/g, " ");
        cd += "The article of the " + id + " is " + obj.article + ". ";
    }
 
    if (obj["name"].length) {
        cd += "Understand";
        for (var i = 0; i < obj["name"].length; i++) {
            var dw = obj["name"][i];
            
            if (i) cd += ",";
            cd += " \"" + dw.dword + "\"";
        }
        cd += " as ";
        if (!proper) cd += "the ";
        cd += id + ". ";
    }
    
    if (obj.comment.length) {
        cd += "[" + obj.comment.join(" ") + "]";
    }
    cd += "\n";
    
    return cd;
}

function code()
{

    return (opt["target"] == "i6") ? i6code() : i7code();
}

function informise(text) {
    var lines = text.split(/\s*[;\n]+\s*/)
    obj = {
        has: [],
        name: [],
        firstname: {},
        comment: []
    };
       
    for (var i = 0; i < lines.length; i++) {
        parse_line(lines[i], ("id" in obj) == false)
    }
    return code();
}

function get_options()
{
    var ctrl = document.getElementsByTagName("input");
    
    for (var i = 0; i < ctrl.length; i++) {
        var c = ctrl[i];
        if (c.type == "checkbox") {
            opt[c.name] = c.checked;
        }
        if (c.type == "radio") {
            if (c.checked) opt[c.name] = c.value;
        }
    }
}

function go() 
{
    // Optionen setzen
    get_options();

    var words = document.getElementById("words");
    if (!words) return;
    
    var text = informise(words.value);
    
    var code = document.getElementById("code");
    if (!code) return;
    
    code.value = text;
    code.focus();
}

window.onload = next_example;


