Esempio n. 1
0
        internal DbIns(Reach smb)
        {
            init();
            //TBD
            Db    db        = new Db(new ctx().DbDrivers);
            DbIns ret       = null;
            Zone  bktFilter = new Zone(new Pile <string>(), new Pile <string>("", true, "(", ")", "||:0"));
            Zone  strFilter = new Zone(new Pile <string>(), new Pile <string>("", true, "\"", "\"", "||:1"));

            /*
             * string insstr = "Grid(\"prdrln\").sC(\"sbj, obj, vb, rul, steps, excerpt, trust\").INS(XXXX)";
             * insstr = insstr.Replace("XXXX", "Grid(\"prdrln p1, prdvrb pv1, prdrln p2, prdvrb pv2, kndrln sc, itmrln si, prdvrb pv, prdrul pr, itmrln oi, kndrln oc\", cd(\"p1.obj\").EQ(\"p2.sbj\")).sC(\"si.id, oi.id, pv.id, pr.id, 0, '', 0.5\").sR(XXXX).SLD");
             * insstr = insstr.Replace("XXXX", "cd(\"0\").EQ(Grid(\"prdrln prdrln\").sC(\"count(*)\").sR(cd(\"sbj\").EQ(\"si.id\"), cd(\"obj\").EQ(\"oi.id\"), cd(\"vb\").EQ(\"pr.vb\")).SLC ), XXXX");
             * insstr = bktFilter.on(insstr).text;
             * insstr = insstr.Replace("XXXX", "cd(\"0\").EQ(Grid(\"prdrln prdrln\").sC(\"count(*)\").sR(cd(\"sbj\").EQ(\"si.id\"), cd(\"obj\").EQ(\"oi.id\"), cd(\"vb\").EQ(\"pr.vb\")).SLC ), XXXX");
             */

            Reach gridDef = smb - bktFilter.on(smb);
            Reach ins     = gridDef.at(".INS(");

            if (ins.len == 0)
            {
                throw new Exception("DbIns Constructor: invalid symbolic Definition");
            }
            DbGrid res = db.Grid(smb.before(ins));

            smb = smb.after(ins).before(-1, ")");
            if (smb.startsWith("Grid("))
            {
                ret = res.INS(new DbSlc(smb));
            }
            else
            {
                Pile <string> val = new Pile <string>();
                while (smb.len > 0)
                {
                    if (smb.startsWith("ds("))
                    {
                        val.Push(db.ds(smb.after(1, "\"").before(1, "\""))); smb = smb.after(1, "),").Trim();
                    }
                    else
                    {
                        val.Push(smb.before(1, ",").Trim()); smb = smb.after(1, ",").Trim();
                    }
                }
                ret = res.INS(val.array());
            }
            into   = ret.into;
            fields = ret.fields.Clone(); //new Pile<string>(ret.fieldNames);
            values = ret.values;
            slc    = ret.slc;
        }
Esempio n. 2
0
        } //the super-super class Pile already provides Clone but its result cannot be casted to (DbField) in c#

        public static DbField fromDef(Reach def, Db source, string table)
        {
            DbField ret = new DbField();

            ret.def   = def.before(1, ":").Trim() + " : " + def.after(1, ":").Trim();
            def       = def.after(1, ":").Trim();
            ret.optor = "   ";
            while (def.len > 0)
            {
                Reach fName     = def.before(1, " ").Trim();
                bool  isNumeric = false;
                for (int i = 1; i <= source.Tables[table].Fields.Len; i++)
                {
                    if (source.Tables[table].Fields[i].sql().equals(fName))
                    {
                        isNumeric = ",LONG,INT,INTEGER,DECIMAL,INT4,INT8,BIGINT,REAL,FLOAT8,DOUBLE PRECISION,FLOAT,BIT,".IndexOf("," + source.Tables[table].Fields[i].DataType.ToUpper() + ",") > -1;
                    }
                }
                if (isNumeric)
                {
                    ret.Push(new DbField(fName).cvs());
                }
                else
                {
                    ret.Push(new DbField(fName).ltm().rtm());
                }
                def = def.after(1, " ").Trim();
            }
            return(ret);
        }
Esempio n. 3
0
        public DbSlc(Reach smb)
        {
            Db db = new Db(new ctx().DbDrivers);

            init();
            DbSlc ret = new DbGrid(smb.before(-1, ".SL")).SLC;

            smb = smb.after(-1, ".SL");
            if (smb.startsWith("D"))
            {
                ret = ret.DST;
            }
            smb = smb.from(3);
            while (smb.len > 0)
            {
                if (smb.startsWith("DST"))
                {
                    ret = ret.DST; smb = smb.from(5); continue;
                }
                if (smb.startsWith("TOP("))
                {
                    ret = ret.TOP(long.Parse(smb.from(5).before(1, ")").text)); smb = smb.after(1, ")").from(2); continue;
                }
                if (smb.startsWith("ORD("))
                {
                    ret = ret.ORD(smb.from(5).before(1, ")").after(1, "\"").before(1, "\"").text); smb = smb.after(1, ")").from(2); continue;
                }
            }
            this.count  = ret.count;
            this.fields = ret.fields.Clone(); //new Pile<string>(ret.fieldNames);
            this.from   = new KeyPile <string, string>(ret.from);
            this.join   = ret.join.Clone();   //new Pile<Cnd>(ret.join);
            this.where  = ret.where.Clone();  //new Pile<Cnd>(ret.where);
            this.order  = ret.order;
        }
Esempio n. 4
0
        private Reach extract(Reach source, bool includeTokens)
        {
            Reach ret = source.upto(0) + source.from(source.len + 1); // FromLeftToRight strategy Reach ret = source.from(source.len + 1)

            for (long i = 1; i <= def.Length; i++)
            {
                long k = 1;
                while ((k <= rpt[i - 1]) || ((rpt[i - 1] == 0) && (source.len > 0)))
                {
                    Reach leadIn = source.at(1, utl.dmyBool("al(occur, token) is planned"), def[i - 1].Name);
                    if ((leadIn.len == 0) && (def[i - 1].Name.Length > 0))
                    {
                        return(ret);
                    }
                    if (includeTokens)
                    {
                        if (ret.len == 0)
                        {
                            ret = leadIn;
                        }
                        else
                        {
                            ret = ret + leadIn;
                        }
                    }
                    Reach res     = source.after(leadIn);
                    Reach leadOut = null;
                    int   occur   = 0; // first we try the first closing bracelet, only in case that this will be a non-matching bracelet then wee will try the second, third, fourth etc. closing closing bracelet
                    do
                    {
                        occur++; for (int j = (def[i - 1]).Len; j > 0; j--)
                        {
                            Reach token = res.at(occur, utl.dmyBool("al(occur, token) is planned"), (def[i - 1])[j]); if (token.len > 0)
                            {
                                leadOut = token;
                            }
                        }
                    } while (nested[i - 1] && (res.upto(leadOut).at(-occur, utl.dmyBool("al(occur, token) is planned"), leadIn.text).len > 0));
                    if (leadOut != null)
                    {
                        res = res.before(leadOut);
                    }
                    if (leadOut == null)
                    {
                        return((ret.len == 0) ? res : ret + res);
                    }
                    if (ret.len == 0)
                    {
                        ret = includeTokens ? source.after(leadIn).upto(leadOut) : source.after(leadIn).before(leadOut);
                    }
                    else
                    {
                        ret = includeTokens ? ret + source.after(leadIn).upto(leadOut) : ret + source.after(leadIn).before(leadOut);
                    }
                    source = source.after(leadOut);
                    k++;
                }
            }
            return(ret);
        }
Esempio n. 5
0
        public Reach fromClause(Db db)
        {
            Reach ret = "";

            foreach (string t in From.Keys)
            {
                ret += db.dbTable(From[t]) + " " + t.Replace(".", "") + ", ";
            }
            if (ret.EndsWith(" \r\n FROM "))
            {
                ret = ret.before(-9);
            }
            else
            {
                ret = ret.before(-2);
            }
            return(ret);
        }
Esempio n. 6
0
 private void txtDtv_TextChanged(object sender, EventArgs e)
 {
     if (programGeneratedEvent > 0)
     {
         return;
     }
     programGeneratedEvent++;
     try
     {
         Reach dtv = txtDtv.Text;
         txtOptor.Text = dtv.before(1, " = ");
         writeToTable(txtOptor.Text, dtv.after(1, " = "));
         trm = new Trm(txtOptor.Text, txtOpnd1.Text, txtOpnd2.Text, txtOpnd3.Text, txtOpnd4.Text); //trm = new Trm(":dbg:" + txtOptor.Text, txtOpnd1.Text, txtOpnd2.Text, txtOpnd3.Text, txtOpnd4.Text);
         trm.Dtv.Set(txtOptor.Text, dtv.after(1, " = ").text);                                     //trm.Dtv.Set(":dbg:" + txtOptor.Text, dtv.after(1, " = ").text);
         try { txtVal4.Text = trm.val(); }
         catch { }
         txtOptr.Text          = trm.optr;
         txtDtv0.Text          = trm.dtv0;
         txtDtv1lR.Text        = trm.dtv1lR;
         txtDtv1mR.Text        = trm.dtv1mR;
         txtDtv1rR.Text        = trm.dtv1rR;
         txtDtv1lS.Text        = trm.dtv1lS;
         txtDtv1mS.Text        = trm.dtv1mS;
         txtDtv1rS.Text        = trm.dtv1rS;
         txtDtv2.Text          = trm.dtv2;
         chkRight2Left.Checked = !trm.left2right;
         chkRevert.Checked     = trm.revert;
         try
         {
             trm = new Trm(txtOptor.Text, txtOpnd1.Text, txtOpnd2.Text, txtOpnd3.Text);
             trm.Dtv.Set(txtOptor.Text, dtv.after(1, " = ").text); //trm.Dtv.Set(":dbg:" + txtOptor.Text, dtv.after(1, " = ").text);
             txtVal3.Text = trm.val();                             //txtVal3.Text = new Trm(":dbg:" + txtOptor.Text, txtOpnd1.Text, txtOpnd2.Text, txtOpnd3.Text).val();
             trm          = new Trm(txtOptor.Text, new object[] { txtOpnd1.Text, txtOpnd2.Text });
             trm.Dtv.Set(txtOptor.Text, dtv.after(1, " = ").text); //trm.Dtv.Set(":dbg:" + txtOptor.Text, dtv.after(1, " = ").text);
             txtVal2.Text = trm.val();                             //txtVal2.Text = new Trm(":dbg:" + txtOptor.Text, new object[] { txtOpnd1.Text, txtOpnd2.Text }).val();
             trm          = new Trm(txtOptor.Text, txtOpnd1.Text);
             trm.Dtv.Set(txtOptor.Text, dtv.after(1, " = ").text); //trm.Dtv.Set(":dbg:" + txtOptor.Text, dtv.after(1, " = ").text);
             txtVal1.Text = trm.val();                             //txtVal1.Text = new Trm(":dbg:" + txtOptor.Text, txtOpnd1.Text).val();
         }
         catch { }
     }
     finally { programGeneratedEvent--; }
 }
Esempio n. 7
0
        public string struc(long indent)
        {
            string ret = new string(' ', Math.Max(0, (int)indent));

            if (this != root)
            {
                ret += def + ctn.before(1, "<");
            }
            string lastType = "";

            foreach (Tag t in _tags)
            {
                if ((t.type.len == 0) && ((t.def + t.ctn.before(1, "<")).len > 0))
                {
                    ret += t.def + t.ctn.before(1, "<");
                }
                else if (t.type.text.ToLower().Equals("/" + lastType))
                {
                    ret += t.def;
                }
                else
                {
                    ret += "\n".Substring(0, Math.Min(1, ret.Length)) + t.struc(indent + 1);
                }
                lastType = t.type.text.ToLower();
            }
            if (closingTag != null)
            {
                if (closingTag != this)
                {
                    ret += closingTag.def;
                }
                else if (!type.Equals("") && !type.Equals("!") && !type.startsWith("/"))
                {
                    if (!def.at(-2).equals("/"))
                    {
                        ret += "</" + type + ">";
                    }
                }
            }
            return(ret);
        }
Esempio n. 8
0
        /// <summary> sC ("select Columns") is the fields selector clause. (like in SQL Statements)</summary>
        public DbGrid sC(string allfields)
        {
            DbGrid ret = new DbGrid(this);

            ret.allFields = ret.fields.Clone(); //new Pile<string> (ret.fieldNames);
            Reach fields = new Reach(allfields + ",");

            if (!fields.Trim().equals("*,"))
            {
                ret.fields = new Pile <DbField>();
                Reach tokenMap = fields - bltZone.upon(fields - chrZone.upon(fields)); //AttGeTr: upon is too expensive!
                while (fields.Trim().len > 0)
                {
                    Reach token = tokenMap.at(1, ",");
                    ret.fields.Add(new DbField(fields.before(token).Trim().text)); //AttGeTr: no type information is added for each field !!! / ToBeSolved !!!
                    fields   = fields.after(token);
                    tokenMap = tokenMap.after(token);
                }
            }
            return(ret);
        }
Esempio n. 9
0
        public string Exec(string name, string param)
        {
            string ret = "";
            string debug = ""; Tag debugDef = null; try { debugDef = new Tag(param, true).tags(2, Tag.where ("[type]==debug"))[1]; } catch (Exception ex) { } if (debugDef != null)
            {
                debug = debugDef.attr["name"].Value;
            }

            KeyPile <string, Tag>        paramSet    = new KeyPile <string, Tag>();              //Dictionary<string, Tag> paramSet = new Dictionary<string, Tag>();
            Pile <Tag>                   rsDefSet    = new Pile <Tag>();
            KeyPile <string, Conditions> rsCondSet   = new KeyPile <string, Conditions>();
            KeyPile <string, Tag>        responseSet = new KeyPile <string, Tag>();              //Dictionary<string, Tag> responseSet = new Dictionary<string, Tag>();
            KeyPile <string, Tag>        results     = new KeyPile <string, Tag>();
            KeyPile <string, Pile <NamedValue <string, Tag> > > resSet = new KeyPile <string, Pile <NamedValue <string, Tag> > >();

            string url = prepare(name, param, paramSet, rsDefSet, rsCondSet, responseSet, results, debug);

            Pile <NamedValue <string, Tag> > baseSet = new Pile <NamedValue <string, Tag> >();

            foreach (Tag t in results[1].Tags)
            {
                baseSet.Add(new NamedValue <string, Tag>("base:" + (baseSet.Len + 1), t));
            }
            resSet.Add("base", baseSet);
            results[1].tags(-1, 1, rsCondSet, resSet);
            ret += "<tr>\n<td>" + (++execCounter) + "</td></tr>\n";
            foreach (NamedValue <string, Tag> nt in resSet[-1])
            {
                ret += "<tr>\n";
                if (debug.Length == 0)
                {
                    foreach (Tag rDef in responseSet)
                    {
                        Reach val;
                        Reach valDef = rDef.attr["value"].Value.text.Replace("&lt;", "<").Replace("&gt;", ">").ToLower();
                        Reach delim  = valDef.at(1, ".");
                        if ((delim.len > 0) && (!valDef.before(delim).Equals(resSet.Keys[-1])))
                        {
                            NamedValue <string, Tag> baseTag = nt;
                            while (true)
                            {
                                Reach baseName = (Reach)baseTag.Name; int num = Int32.Parse(baseName.after(1, ":")); baseTag = resSet[baseName.before(1, ":")][num]; if (baseName.before(1, ":").Equals(valDef.before(delim)))
                                {
                                    val = baseTag.Value.val(valDef.after(delim)); break;
                                }
                            }
                        }
                        else if (delim.len > 0)
                        {
                            val = nt.Value.val(valDef.after(delim));
                        }
                        else
                        {
                            val = nt.Value.val(valDef);
                        }
                        ret += " <td>" + val.text.Replace("\n", "").Replace("\r", "") + " </td>\n";
                    }
                    ret += "</tr>\n";
                }
                else
                {
                    ret += nt.Value.struc(-1) + "</tr>\n";
                }
            }
            return("<url>" + url + "</url>" + ret);
        }
Esempio n. 10
0
 public ndUrl(string urlString)
 {
     urlString = urlString.Trim();
     if (urlString.IndexOf("://") < 0)
     {
         urlString = "http://" + urlString;
     }
     _url     = new Reach(urlString);
     Protocol = _url.before(1, "://");
     _url     = _url.after(Protocol).from(4);
     Domain   = _url.before(1, "/");
     _url     = _url.after(Domain).from(2);
     Password = Domain.before(-1, "@");
     if (Password.len > 0)
     {
         Domain = Domain.after(Password).from(2);
         User   = Password.before(1, ":");
         if (User.len > 0)
         {
             Password = Password.after(User).from(2);
         }
     }
     else
     {
         User = Password.upto(0);
     }
     Port = Domain.after(1, ":");
     if (Port.len > 0)
     {
         Domain = Domain.before(Port).upto(-2);
     }
     Extension = Domain.after(-2, ".");
     if (_allExtensions.IndexOf(" " + Extension.uText + " ") < 0)
     {
         Extension = Domain.after(-1, ".");
     }
     if (_allExtensions.IndexOf(" " + Extension.uText + " ") < 0)
     {
         Extension = Domain.from(Domain.len + 1);
     }
     if (Extension.len > 0)
     {
         Domain = Domain.before(Extension).upto(-2);
     }
     Server = Domain.before(-1, ".");
     if (Server.len > 0)
     {
         Domain = Domain.after(Server).from(2);
     }
     Path = _url.before(1, "?");
     if (Path.len > 0)
     {
         _url = _url.after(Path).from(2);
     }
     Query = new Assoc(_url, "=", "&", "");
     File  = Path.after(-1, "/");
     if (File.len > 0)
     {
         Path = Path.before(File).upto(-2);
     }
 }
Esempio n. 11
0
        private void splitparts()
        {
            Pile <Reach> res = new Pile <Reach>();

            Reach s = parts[1].Trim();

            while (s.len > 0)
            {
                Reach first = s.At(1, false, ops.array());
                if (first.len == 0)
                {
                    res.Push(s); s = "";
                }
                else
                {
                    if (s.startsWith(first))
                    {
                        if (first.Equals("\""))
                        {
                            res.Push("`dsF`"); res.Push(Zone.quotation.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }
                        if (first.Equals("'"))
                        {
                            res.Push("`dsF`"); res.Push(Zone.charray.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }
                        if (first.Equals("("))
                        {
                            res.Push(Zone.bracelet.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }
                        if (first.Equals("["))
                        {
                            res.Push(Zone.bracket.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }
                        if (first.Equals("{"))
                        {
                            res.Push(Zone.curlybrack.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }

                        if (first.Equals("+"))
                        {
                            res.Push("`cct`"); res.Push(Zone.curlybrack.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }
                        if (first.Equals("||"))
                        {
                            res.Push("`cct`"); res.Push(Zone.curlybrack.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }

                        if (first.Equals("ltrim("))
                        {
                            res.Push("`ltr`"); res.Push(Zone.bracelet.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }
                        if (first.Equals("rtrim("))
                        {
                            res.Push("`rtr`"); res.Push(Zone.bracelet.on(s)); res.Push(s.after(res[-1]).Trim()); s = "";
                        }
                    }
                    else
                    {
                        res.Push("`dF`");
                        res.Push(s.before(first).Trim());
                        res.Push(s.from(first).Trim());
                        s = "";
                    }
                }
            }
            parts = res;
        }
Esempio n. 12
0
        private void splitparts()
        {
            if (operators == null)
            {
                operators = ops.Clone(); foreach (string key in Dtv.Keys)
                {
                    operators.Push(new Reach(Dtv[key]).before(1, "``"));
                }
            }
            int inx = 1;

            while (inx <= Len)
            {
                Reach  rest = null;
                object lOp  = null;
                object rOp  = null;
                object tOp  = null;
                //if (this[inx].GetType() ==  typeof(string)) rest = new Reach((string)this[inx]).Trim();   //AttGeTr SEVERE BUGS HERE!!  the middle chars of "word" will be detected as Operator "or" !
                if (rest == null)
                {
                    inx++;
                }
                else
                {
                    Reach firstOptorSmb = rest.At(1, false, operators.array()).Trim();
                    if (firstOptorSmb.At(1, "(").len == 0)
                    {
                        if (operators.Contains((firstOptorSmb + "(").uText))
                        {
                            if (rest.after(firstOptorSmb).startsWith("("))
                            {
                                firstOptorSmb = firstOptorSmb + rest.after(firstOptorSmb).upto(1);                                                                                                                 // both the infix OR and the prefix OR( may be defined as directive
                            }
                        }
                    }
                    String firstOptor = optorForSymbolicOptor(firstOptorSmb.text);
                    if (rest.startsWith(firstOptorSmb))
                    {
                    }
                    else
                    {
                    }

                    if (firstOptorSmb.len == 0)
                    {
                        Reach fieldVal = new Reach((string)this[inx]).Trim();
                        this[inx] = new Reach((string)this[inx]);
                        rest      = "";
                    } // this term has no operand, it is a literal like 3 or a Symbol like a DbField Name or a composite field definition

                    else
                    {
                        if (rest.startsWith(firstOptorSmb))
                        {
                            if (firstOptorSmb.Equals("("))
                            {
                                this[inx] = new Trm(Zone.bracelet.on(rest).text); optor = ""; rest = rest.after(Zone.bracelet.upon(rest)).Trim();
                            }
                            else
                            {
                                string newOptor = firstOptorSmb.Trim().text.Replace("(", "");
                                bool   prefix   = (firstOptorSmb.at(1, "(").len > 0);
                                if (prefix)
                                {
                                    this[inx] = new Trm(Zone.bracelet.on(rest.after(1, optor).Trim()).text); rest = rest.after(Zone.bracelet.upon(rest.after(1, optor))).Trim();
                                }
                                else
                                {
                                    rest = "";
                                    if (optor.Length > 0)
                                    {
                                        this[1] = new Trm(optor, this[1]);
                                        for (int i = 2; i < inx; i++)
                                        {
                                            ((Trm)this[1]).Push(this[i]);
                                        }
                                        for (int i = 2; i <= Len - (inx - 2); i++)
                                        {
                                            this[i] = this[i + (inx - 2)];
                                        }
                                        for (int i = 1; i <= (inx - 2); i++)
                                        {
                                            Del(Len);
                                        }
                                        inx = 2;
                                    }
                                    this[inx] = new Trm(rest.after(1, optor).Trim().text); rest = "";
                                }
                                if ((((Trm)this[inx]).Len == 1 && ((Trm)this[inx]).optor.Length == 0))
                                {
                                    this[inx] = ((Trm)this[inx]).lOpnd;
                                }
                                optor = optorForSymbolicOptor(firstOptorSmb.Trim().text);
                            }
                        }
                        else
                        {
                            if ((Len == 1) && (optor.Length == 0))
                            {
                                optor = optorForSymbolicOptor(firstOptorSmb.Trim().text); this[inx] = rest.before(firstOptorSmb).Trim(); Push(rest.after(firstOptorSmb).Trim().text);
                            }
                            else
                            {
                                this[inx] = new Trm(optorForSymbolicOptor(firstOptorSmb.Trim().text), new object[] { rest.before(firstOptorSmb).Trim(), rest.after(firstOptorSmb).Trim().text });
                            }
                            rest = "";
                        }
                    }
                    if (rest.len > 0)
                    {
                        Push(rest.text);
                    }
                    rest = "";
                    inx++;
                }
            }
        }
Esempio n. 13
0
 private void init(Reach src, Tag parent, bool xml)
 {
     isRelevant  = true;
     type        = src.upto(0); //AttGeTr: type was null in new Tag("", false)
     ctn         = src.upto(0); //AttGeTr: ctn was null in some TestCase ...
     isXmlTag    = xml;
     _tags       = new Pile <Tag>();
     this.parent = parent;
     def         = src;
     if (parent == null)
     {
         root = this;
         all  = new Pile <Tag>();
         int done = 0;
         while (done < def.len)
         {
             all.Add(new Tag(def.after(done), this, xml));
             if (all[-1].isWhiteSpace())
             {
                 all[-1].isRelevant = false;
             }
             if (all.Len == 1)
             {
                 all[-1].parent = this;
             }
             else
             {
                 if (all[-1].type.startsWith("/"))
                 {
                     for (int i = all.Len - 1; i > 0; i--)
                     {
                         if ((all[-1].type.Equals("/" + all[i].type.text)) && (all[i].closingTag == null))
                         {
                             all[i].closingTag = all[-1]; all[-1].parent = all[i].parent; break;
                         }
                     }
                     if (all[-1].parent == null)
                     {
                         all[-1].parent = all[-2].parent;    // orphaned closing tag
                     }
                 }
                 else
                 {
                     if ((all[-1].type.len == 0) && (!all[-2].type.startsWith("/"))) // new definition: a "plain text tag" may be contained in any tag but may not always be relevant ...
                     {
                         if (!all[-2].mayContain(all[-1].type.text))
                         {
                             all[-1].isRelevant = false;
                         }
                         if (all[-2].closingTag == null)
                         {
                             all[-1].parent = all[-2];
                         }
                         else
                         {
                             all[-1].parent = all[-2].parent;
                         }
                     }
                     else
                     {
                         if ((all[-2].mayContain(all[-1].type.text)))
                         {
                             all[-1].parent = all[-2];
                         }
                         else
                         {
                             all[-1].parent = all[-2].parent; if (all[-2].closingTag == null)
                             {
                                 all[-2].closingTag = all[-2];
                             }
                         }
                     }
                 }
             }
             done = done + all[-1]._htm.len;
         }
         for (int i = 1; i <= all.Len; i++)
         {
             if ((all[i].isRelevant) && (!all[i].type.startsWith("/")))
             {
                 all[i].parent._tags.Add(all[i]);
             }
         }
     }
     else
     {
         root = parent.root;
         if (def.startsWith("<"))
         {
             def  = def.upto(1, ">");
             type = def.after(1).before(-1).before(1, " ");
             if (type.startsWith("!"))
             {
                 if (type.startsWith("!--"))
                 {
                     type = type.upto(3);
                 }
                 else
                 {
                     type = type.upto(1);
                 }
             }
             if (type.endsWith("/"))
             {
                 type = type.before(-1);
             }
             if (type.Equals("!--"))
             {
                 closingTag = this;
                 type       = type.upto(1);
                 def        = root.def.from(def).upto(1, "-->");
                 ctn        = def.after(-1).upto(0);
                 _htm       = def;
                 attrib     = def.after(type).upto(-2).lTrim().rTrim(); if (attrib.endsWith("/"))
                 {
                     closingTag = this; attrib = attrib.before(-1);
                 }
             }
             else
             {
                 if (type.startsWith("!"))
                 {
                     closingTag = this; type = type.upto(1);
                 }
                 if (type.Equals("script"))
                 {
                     ctn    = root.def.from(def).Before(1, "</script");
                     _htm   = ctn.upto(-1); //htm = def + ctn + root.def.after(ctn).upto(1, ">");
                     attrib = def.after(type).upto(-2).lTrim().rTrim(); if (attrib.endsWith("/"))
                     {
                         closingTag = this; attrib = attrib.before(-1);
                     }
                 }
                 else
                 {
                     ctn    = root.def.after(def).upto(0);
                     _htm   = def.upto(-1); //_htm = def.plus(ctn);
                     attrib = def.after(type).upto(-2).lTrim().rTrim(); if (attrib.endsWith("/"))
                     {
                         closingTag = this; attrib = attrib.before(-1);
                     }
                 }
             }
         }
         else
         {
             closingTag = this;
             ctn        = def.before(1, "<");
             type       = def.upto(0);
             def        = def.upto(0);
             attrib     = def.upto(0);
             _htm       = ctn.upto(-1);
         }
     }
 }