private void CompileJSRecursive(HaJSElement root, HaJSElement parent) { IndentedStringBuilder sb = GetStringBuilderByContext(root.statusContext); if (root is SwitchElement) { SwitchElement se = (SwitchElement)root; for (int i = 0; i < se.Children.Count; i++) { CaseElement ce = (CaseElement)se.Children[i]; sb.AppendLine(ce.Compile(this, se.Type, i == 0)); sb.Enter(); CompileJSRecursive(ce, root); sb.Leave(); } } else if (root.HasChildren && !root.Parallel) { root.Children.ForEach(x => CompileJSRecursive(x, root)); } else if (root is CommandElement) { CommandElement ce = (CommandElement)root; sb.AppendLine(ce.Compile(this)); } else if (root is MessageBaseElement) { MessageBaseElement mbe = (MessageBaseElement)root; if (mbe.ControlFlowBreaker) { WriteStatusChange(sb, mbe.NextStatus); } sb.AppendLine(mbe.Compile(this)); if (mbe is OkMessageElement) { sb.AppendLine(GetFeature("special_End").Compile(this)); } sb.AppendLine("return;"); string postCompileData = mbe.PostCompile(this, parent); if (root is OptionsMessageElement) { // Special case handled here because OptionMessages are complicated OptionsMessageElement ome = (OptionsMessageElement)root; sb = GetStringBuilderByContext(new HashSet <int>() { ome.NextStatus }); for (int i = 0; i < ome.Children.Count; i++) { OptionElement oe = (OptionElement)ome.Children[i]; sb.AppendLine((i == 0 ? "if" : "else if") + " (selection == " + i.ToString() + ")"); sb.Enter(); CompileJSRecursive(oe, root); sb.Leave(); } } else if (postCompileData != null) { GetStringBuilderByContext(new HashSet <int>() { mbe.NextStatus }).Append(postCompileData); } } }
private void BuildElementRecursive(XmlElement element, ref List <HaJSElement> targetList) { HaJSElement result; List <HaJSElement> elements; switch (element.Name) { case "switch": SwitchElement se = new SwitchElement((HaJSSwitchFeature)GetFeature("switch_" + element.GetAttribute("type"))); elements = se.Children; foreach (XmlElement caseNode in element.ChildNodes) { BuildElementRecursive(caseNode, ref elements); } result = se; break; case "case": CaseElement ce; if (element.HasAttribute("cond")) { ce = new CaseElement(false, true, element.GetAttribute("cond")); } else { ce = new CaseElement(false, false, element.GetAttribute("val")); } elements = ce.Children; foreach (XmlElement subnode in element.ChildNodes) { BuildElementRecursive(subnode, ref elements); } result = ce; break; case "default": CaseElement def = new CaseElement(true, false, null); elements = def.Children; foreach (XmlElement subnode in element.ChildNodes) { BuildElementRecursive(subnode, ref elements); } result = def; break; case "message": string msgText = GetTextFromElement(element); switch (element.GetAttribute("style")) { case "n": result = new NextMessageElement(this, msgText); break; case "pn": result = new PrevNextMessageElement(this, msgText); break; case "yn": string no = TryResolveResource(element.GetAttribute("no")); result = new YesNoMessageElement(this, msgText, no); break; case "ok": result = new OkMessageElement(this, msgText); break; default: throw new ArgumentException("Unknown message type \"" + element.GetAttribute("style") + "\" in the element \"" + element.OuterXml + "\""); } if (element.HasAttribute("x")) { ((MessageBaseElement)result).Style = int.Parse(element.GetAttribute("x")); } break; case "options": OptionsMessageElement ome = new OptionsMessageElement(this, GetTextFromElement(element)); elements = ome.Children; foreach (XmlElement subnode in element.ChildNodes) { BuildElementRecursive(subnode, ref elements); } result = ome; break; case "option": OptionElement oe = new OptionElement(GetTextFromElement(element)); elements = oe.Children; foreach (XmlElement subnode in element.ChildNodes) { BuildElementRecursive(subnode, ref elements); } result = oe; break; case "ifdef": case "ifndef": string condition = element.GetAttribute("name"); if ((element.Name == "ifdef" && features.ContainsKey(condition)) || (element.Name == "ifndef" && !features.ContainsKey(condition))) { foreach (XmlElement subnode in element.ChildNodes) { BuildElementRecursive(subnode, ref targetList); } } return; case "assert": string type = element.GetAttribute("type"); string fail = TryResolveResource(element.GetAttribute("onFail")); string cond = element.GetAttribute("cond"); SwitchElement fakeSwitch = new SwitchElement((HaJSSwitchFeature)GetFeature("switch_" + type)); CaseElement fakeCase = new CaseElement(false, true, cond); CaseElement fakeDef = new CaseElement(true, false, null); fakeSwitch.Children.Add(fakeCase); fakeSwitch.Children.Add(fakeDef); OkMessageElement fakeOk = new OkMessageElement(this, fail); fakeDef.Children.Add(fakeOk); targetList.Add(fakeSwitch); targetList = fakeCase.Children; return; default: if (features.ContainsKey(element.Name)) { result = new CommandElement(GetFeature(element.Name), element.HasAttribute("x") ? element.GetAttribute("x") : null, element.HasAttribute("y") ? element.GetAttribute("y") : null, element.HasAttribute("z") ? element.GetAttribute("z") : null); break; } else { throw new InvalidOperationException("Unknown tag type \"" + element.Name + "\" in the element \"" + GetFirstTag(element.OuterXml) + "\""); } } targetList.Add(result); }