private AutomataDefinition(Neighbourhood neighbourhood, bool wrap, StateDefinition[] states) { NumStates = states.Length; Neighbourhood = neighbourhood; Wrap = wrap; States = states; }
public static AutomataDefinition Create(string formula, out string error) { error = string.Empty; if(string.IsNullOrWhiteSpace(formula)) { error = "Formula cannot be empty."; return null; } List<StateDefinition> states = new List<StateDefinition>(); List<StateRule> rules = new List<StateRule>(); string[] lines = formula.Split('|','\n','\r'); Neighbourhood neighbourhood = Neighbourhood.Moore; bool wrap = false; foreach(var line in lines) { string parse = line.Replace(" ", string.Empty); parse = parse.Replace("\t", string.Empty); parse = parse.ToLowerInvariant(); if(parse == "n") { neighbourhood = Neighbourhood.VonNeumann; continue; } if (parse == "m") { neighbourhood = Neighbourhood.Moore; continue; } if (parse == "w") { wrap = true; continue; } if (parse == "b") { wrap = false; continue; } string[] pair = parse.Split(':'); if(pair.Length != 2) { error = "Syntax error: '" + line + "'."; return null; } byte state = 0; if(!byte.TryParse(pair[0], out state) || state > 15) { error = "Syntax error: '" + line + "'. Expected number between 0 and 15."; return null; } string[] newStates = pair[1].Split(','); rules.Clear(); foreach(var rule in newStates) { byte stateId = 0; byte count = StateRule.AnyCount; if(rule.Contains('(')) { string[] exp = rule.Split('(', ')'); if (!byte.TryParse(exp[0], out stateId) || stateId > 15) { error = "Syntax error: '" + line + "'. Expected number between 0 and 15."; return null; } if (!byte.TryParse(exp[1], out count) || count > 8) { error = "Syntax error: '" + line + "'. Expected number between 0 and 8."; return null; } } else { if(!byte.TryParse(rule, out stateId) || stateId > 15) { error = "Syntax error: '" + line + "'. Expected number between 0 and 15."; return null; } } if(rules.Find((v)=>(v.State == stateId && v.Count == count)) != null) { error = "Error: '" + line + "'. Already defined state-count pair."; return null; } if (count == StateRule.AnyCount && rules.Find((v) => (v.Count == count)) != null) { error = "Error: '" + line + "'. Already defined default state."; return null; } rules.Add(new StateRule(stateId, count)); } if(states.Find(v=>v.State == state)!=null) { error = string.Format("Error: '{0}'. Already defined state {1}.", line, state); return null; } StateDefinition stateDefinition = new StateDefinition(state, rules.ToArray()); states.Add(stateDefinition); } states.Sort((v1, v2) => { return Math.Sign(v1.State - v2.State); }); for (int idx = 0; idx < states.Count; ++idx ) { if(states[idx].State != idx) { error = string.Format("Missing state definition: {0}.", idx); return null; } } //M|0:0|1:2|2:3|3:1(1=1,2),3 return new AutomataDefinition(neighbourhood, wrap, states.ToArray()); }