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); }
/** 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); }
/* 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)); }
private static void clean_specs(Parser_Hook h) { h.dir = ""; h.specs = new List <Hook_Spec>(); h.func = null; }
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; }
private static void clean_specs(Parser_Hook h) { h.dir = ""; h.specs = new List<Hook_Spec>(); h.func = null; }
/** 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; }