Beispiel #1
0
        static Error parse_specs(Parser_Hook h, string fmt)
        {
            Misc.assert(h != null);
            Misc.assert(fmt != null);

            string[] split = fmt.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            if (split.Length == 0)
            {
                return(Error.GENERIC);
            }

            h.dir = split[0];

            int i = 1;

            while (i < split.Length)
            {
                /* Lack of a type is legal; that means we're at the end of the
                 * line. */
                string stype = split[i++];

                /* Lack of a name, on the other hand... */
                if (i >= split.Length)
                {
                    clean_specs(h);
                    return(Error.GENERIC);
                }
                string name = split[i++];

                /* Grab a type, check to see if we have a mandatory type
                 * following an optional type. */
                PARSE_T type = parse_type(stype);
                if (type == PARSE_T.NONE)
                {
                    clean_specs(h);
                    return(Error.GENERIC);
                }
                if ((type & PARSE_T.OPT) == 0 && h.specs.Count > 0 && (h.specs.Last().type & PARSE_T.OPT) != 0)
                {
                    clean_specs(h);
                    return(Error.GENERIC);
                }
                if (h.specs.Count > 0 && ((h.specs.Last().type & ~PARSE_T.OPT) == PARSE_T.STR))
                {
                    clean_specs(h);
                    return(Error.GENERIC);
                }

                /* Save this spec. */
                Hook_Spec hs = new Hook_Spec();
                hs.type = type;
                hs.name = name;
                h.specs.Add(hs);
            }

            return(Error.NONE);
        }
Beispiel #2
0
        /** Registers a parser hook.
         *
         * Hooks have the following format:
         *   <fmt>  ::= <name> [<type> <name>]* [?<type> <name>]*
         *   <type> ::= int | str | sym | rand | char
         * The first <name> is called the directive for this hook. Any other hooks with
         * the same directive are superseded by this hook. It is an error for a
         * mandatory field to follow an optional field. It is an error for any field to
         * follow a field of type `str`, since `str` fields are not delimited and will
         * consume the entire rest of the line.
         */
        public Error Register(string fmt, ParseFunc pf)
        {
            //Misc.assert(p); //if p (self) was null, we wouldn't be here
            Misc.assert(fmt != null);
            Misc.assert(pf != null);

            Parser_Hook h = new Parser_Hook();

            h.func = pf;

            /*h.next = p.hooks;
             * h.func = func;*/
            Error r = parse_specs(h, fmt);

            if (r != Error.NONE)
            {
                return(r);
            }

            hooks.Add(h);
            //p.hooks = h;
            //mem_free(cfmt);
            return(Error.NONE);
        }
Beispiel #3
0
        /* This is a bit long and should probably be refactored a bit. */
        public Error Parse(string line)
        {
            /*struct parser_hook *h;
             * struct parser_spec *s;
             * struct parser_value *v;
             * char *sp = null;*/

            //assert(p); //lol, C is so silly
            Misc.assert(line != null);

            freeold();

            lineno++;
            colno = 1;

            values.Clear();

            // Ignore empty lines and comments.
            line = line.Trim();
            if (line.Length == 0 || line[0] == '#')
            {
                return(Error.NONE);
            }

            string[] tok = line.Split(new char[] { ':' });
            //If we have an empty, remove it and add ":" to the next entry
            //This also has the side effect of concatinating two empties into a single :, which is what we want.
            //since two empties means it was a ":::" which mean a ":" char.
            List <string> temp_tok = new List <string>(tok);

            for (int i = 0; i < temp_tok.Count() - 1; i++)
            {
                if (temp_tok[i].Length == 0)
                {
                    temp_tok[i + 1] = ":" + temp_tok[i + 1];
                    temp_tok.RemoveAt(i);
                }
            }
            tok = temp_tok.ToArray();

            int tat = 0;

            if (tok.Length == 0)
            {
                error = Error.MISSING_FIELD;
                return(error);
            }

            Parser_Hook h = findhook(tok[tat++]);

            if (h == null)
            {
                error = Error.UNDEFINED_DIRECTIVE;
                return(error);
            }

            //Imma just try this from scratch
            //We wish to match each token in order
            foreach (Hook_Spec s in h.specs)
            {
                if (tat >= tok.Length)
                {
                    if ((s.type & PARSE_T.OPT) != 0)
                    {
                        break;                         //We're cool, it was optional anyways
                    }
                    else
                    {
                        return(Error.GENERIC);
                    }
                }
                string       val = tok[tat++];
                Parser_Value v   = new Parser_Value();

                PARSE_T type = s.type & ~PARSE_T.OPT;

                if (type == PARSE_T.INT)
                {
                    int t = 0;
                    if (val.StartsWith("0x"))
                    {
                        t = Convert.ToInt32(val.Substring(2), 16);
                    }
                    else if (!Int32.TryParse(val, out t))
                    {
                        return(Error.INVALID_VALUE);
                    }
                    v.value = t;
                }
                else if (type == PARSE_T.UINT)
                {
                    uint t;
                    if (!UInt32.TryParse(val, out t))
                    {
                        return(Error.INVALID_VALUE);
                    }
                    v.value = t;
                }
                else if (type == PARSE_T.CHAR)
                {
                    char t;
                    if (!Char.TryParse(val, out t))
                    {
                        return(Error.INVALID_VALUE);
                    }
                    v.value = t;
                }
                else if (type == PARSE_T.RAND)
                {
                    random_value t = new random_value();

                    Regex           r       = new Regex("[0-9]+");
                    MatchCollection matches = r.Matches(val, 0);

                    //This first boolean quickly became hacky. Todo: build better regex!
                    bool has_dice_number   = val.Contains("d") && val[0] != 'd' && val[1] != 'd';                   //begining with a d is cheating
                    bool has_Base_modifies = val.Contains("M");

                    int mat = 0;

                    t.dice = 1;
                    if (has_dice_number)
                    {
                        t.dice = int.Parse(matches[mat++].Value);
                    }

                    t.sides = int.Parse(matches[mat++].Value);

                    t.Base = 0;
                    if (has_Base_modifies)
                    {
                        t.Base = int.Parse(matches[mat++].Value);
                    }

                    v.value = t;
                }
                else if (type == PARSE_T.SYM)
                {
                    v.value = val;                     //Straight up
                }
                else if (type == PARSE_T.STR)
                {
                    string temp = val;
                    while (tat < tok.Length)
                    {
                        temp += tok[tat++];
                        if (tat < tok.Length)
                        {
                            temp += ":";
                        }
                    }
                    v.value = temp;
                }
                else
                {
                    throw new NotImplementedException();
                    //We probably got a type I have not written yet
                }

                v.spec = s;
                values.Add(v);
            }

            return(h.func(this));
        }
Beispiel #4
0
 private static void clean_specs(Parser_Hook h)
 {
     h.dir   = "";
     h.specs = new List <Hook_Spec>();
     h.func  = null;
 }
Beispiel #5
0
        static Error parse_specs(Parser_Hook h, string fmt)
        {
            Misc.assert(h != null);
            Misc.assert(fmt != null);

            string[] split = fmt.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries);
            if (split.Length == 0)
                return Error.GENERIC;

            h.dir = split[0];

            int i = 1;
            while(i < split.Length)
            {
                /* Lack of a type is legal; that means we're at the end of the
                 * line. */
                string stype = split[i++];

                /* Lack of a name, on the other hand... */
                if(i >= split.Length) {
                    clean_specs(h);
                    return Error.GENERIC;
                }
                string name = split[i++];

                /* Grab a type, check to see if we have a mandatory type
                 * following an optional type. */
                PARSE_T type = parse_type(stype);
                if (type == PARSE_T.NONE)
                {
                    clean_specs(h);
                    return Error.GENERIC;
                }
                if ((type & PARSE_T.OPT) == 0 && h.specs.Count > 0 && (h.specs.Last().type & PARSE_T.OPT) != 0)
                {
                    clean_specs(h);
                    return Error.GENERIC;
                }
                if (h.specs.Count > 0 && ((h.specs.Last().type & ~PARSE_T.OPT) == PARSE_T.STR))
                {
                    clean_specs(h);
                    return Error.GENERIC;
                }

                /* Save this spec. */
                Hook_Spec hs = new Hook_Spec();
                hs.type = type;
                hs.name = name;
                h.specs.Add(hs);
            }

            return Error.NONE;
        }
Beispiel #6
0
 private static void clean_specs(Parser_Hook h)
 {
     h.dir = "";
     h.specs = new List<Hook_Spec>();
     h.func = null;
 }
Beispiel #7
0
        /** Registers a parser hook.
         *
         * Hooks have the following format:
         *   <fmt>  ::= <name> [<type> <name>]* [?<type> <name>]*
         *   <type> ::= int | str | sym | rand | char
         * The first <name> is called the directive for this hook. Any other hooks with
         * the same directive are superseded by this hook. It is an error for a
         * mandatory field to follow an optional field. It is an error for any field to
         * follow a field of type `str`, since `str` fields are not delimited and will
         * consume the entire rest of the line.
         */
        public Error Register(string fmt, ParseFunc pf)
        {
            //Misc.assert(p); //if p (self) was null, we wouldn't be here
            Misc.assert(fmt != null);
            Misc.assert(pf != null);

            Parser_Hook h = new Parser_Hook();
            h.func = pf;

            /*h.next = p.hooks;
            h.func = func;*/
            Error r = parse_specs(h, fmt);
            if (r != Error.NONE)
            {
                return r;
            }

            hooks.Add(h);
            //p.hooks = h;
            //mem_free(cfmt);
            return Error.NONE;
        }