/// <summary> /// 构造器 /// </summary> public SceneFunction(string callname, string parent, SceneAction sa = null) { this.ParentSceneName = parent; this.Callname = callname; this.Param = null; this.Sa = sa; }
/// <summary> /// 为当前动作创建一个副本 /// </summary> /// <param name="pureClone">是否保留关系</param> /// <returns>原动作的深拷贝副本</returns> public SceneAction Clone(bool pureClone) { SceneAction resSa = new SceneAction(); resSa.ArgsDict = new Dictionary<string, string>(); foreach (var kv in this.ArgsDict) { resSa.ArgsDict.Add(kv.Key, kv.Value); } resSa.Tag = this.Tag; resSa.Type = this.Type; resSa.FuncName = this.FuncName; resSa.IsBelongFunc = this.IsBelongFunc; resSa.NodeName = this.NodeName; if (pureClone == false) { resSa.CondPolish = this.CondPolish; resSa.DialogDirtyBit = this.DialogDirtyBit; resSa.Next = this.Next; resSa.NodeName = this.NodeName; resSa.TrueRouting = new List<SceneAction>(); foreach (var tr in this.TrueRouting) { resSa.TrueRouting.Add(tr); } resSa.FalseRouting = new List<SceneAction>(); foreach (var fr in this.FalseRouting) { resSa.FalseRouting.Add(fr); } } return resSa; }
/// <summary> /// 将动作序列绑定到一个新的场景函数 /// </summary> /// <param name="funcSa">动作序列</param> /// <returns>场景函数</returns> private SceneFunction ConstructSceneFunction(SceneAction funcSa) { if (funcSa.IsBelongFunc != true) { throw new InterpreterException() { Message = "一个非函数节点被作为函数声明处理", HitLine = Convert.ToInt32((funcSa.Tag.Split('-'))[0]), HitColumn = Convert.ToInt32((funcSa.Tag.Split('-'))[1]), HitPhase = InterpreterException.InterpreterPhase.Sematicer, SceneFileName = this.scenario }; } // 获得函数签名 string signature = funcSa.ArgsDict["sign"]; string[] signItem = signature.Split(new char[] {'(', ')'}, StringSplitOptions.RemoveEmptyEntries); if (signItem.Length < 1 || !IsSymbol(signItem[0].Trim())) { throw new InterpreterException() { Message = "函数签名不合法", HitLine = Convert.ToInt32((funcSa.Tag.Split('-'))[0]), HitColumn = Convert.ToInt32((funcSa.Tag.Split('-'))[1]), HitPhase = InterpreterException.InterpreterPhase.Sematicer, SceneFileName = this.scenario }; } List<string> funcParas = new List<string>(); // 如果没有参数就跳过参数遍历 if (signItem.Length > 1) { string[] varItem = signItem[1].Split(new char[] {',', ' '}, StringSplitOptions.RemoveEmptyEntries); foreach (string ivar in varItem) { if (ivar.StartsWith("$") && IsSymbol(ivar.Substring(1))) { funcParas.Add(ivar); } else { throw new InterpreterException() { Message = "函数签名的参数列表不合法", HitLine = Convert.ToInt32((funcSa.Tag.Split('-'))[0]), HitColumn = Convert.ToInt32((funcSa.Tag.Split('-'))[1]), HitPhase = InterpreterException.InterpreterPhase.Sematicer, SceneFileName = this.scenario }; } } } return new SceneFunction(signItem[0].Trim(), this.scenario, funcSa); }
/// <summary> /// 递归遍历动作序列,回填控制流程,进行代码优化 /// </summary> /// <param name="saNode">要处理的动作序列头部</param> /// <param name="parent">当前序列头部的双亲</param> /// <param name="funcFlag">函数序列标记</param> /// <returns>函数实例</returns> private SceneFunction BackpatchOptimizer(SceneAction saNode, SceneAction parent, bool funcFlag) { switch (saNode.Type) { case SActionType.NOP: case SActionType.act_function: if (saNode.TrueRouting == null || saNode.TrueRouting.Count == 0) { break; } // 递归访问子节点 for (int i = 0; i < saNode.TrueRouting.Count - 1; i++) { this.BackpatchOptimizer(saNode.TrueRouting[i], saNode, false); } // 清理要移除的节点 while (this.removeQueueDict.ContainsKey(saNode) && this.removeQueueDict[saNode].Count != 0) { saNode.TrueRouting.Remove(this.removeQueueDict[saNode].Dequeue()); } // 最后一个孩子的下一节点修改为它母节点的后继 SceneAction lastNop = saNode.TrueRouting[saNode.TrueRouting.Count - 1]; if (lastNop.Type != SActionType.act_break && lastNop.Type != SActionType.act_endfor) { this.BackpatchOptimizer(lastNop, saNode, false); lastNop.Next = saNode.Next; } else { this.BackpatchOptimizer(lastNop, saNode, false); } break; case SActionType.act_dialog: // 合并dialog项 if (saNode.DialogDirtyBit) { break; } SceneAction basePtr = saNode; SceneAction iterPtr = saNode; string dialogBuilder = iterPtr.Tag; iterPtr = iterPtr.Next; // 有可能是最后一个孩子递归时DT已经被移除了 if (iterPtr == null) { break; } if (this.removeQueueDict.ContainsKey(parent) == false) { this.removeQueueDict[parent] = new Queue<SceneAction>(); } while (iterPtr.Type != SActionType.act_dialogTerminator) { iterPtr.DialogDirtyBit = true; dialogBuilder += iterPtr.Tag; this.removeQueueDict[parent].Enqueue(iterPtr); iterPtr = iterPtr.Next; } this.removeQueueDict[parent].Enqueue(iterPtr); if (iterPtr.Next != null && (iterPtr.Next.Type == SActionType.act_dialog || iterPtr.Next.Type == SActionType.act_a)) { dialogBuilder += "#1"; } else { dialogBuilder += "#0"; } basePtr.Tag = dialogBuilder; basePtr.Next = iterPtr.Next; break; case SActionType.act_dialogTerminator: // 处理对话继续标志位 if (saNode.Next != null && (saNode.Next.Type == SActionType.act_dialog || saNode.Next.Type == SActionType.act_a)) { saNode.Tag += "#1"; } else { saNode.Tag += "#0"; } break; case SActionType.act_for: this.forStack.Push(saNode); if (saNode.TrueRouting == null || saNode.TrueRouting.Count == 0) { break; } // 递归访问子节点 for (int i = 0; i < saNode.TrueRouting.Count - 1; i++) { this.BackpatchOptimizer(saNode.TrueRouting[i], saNode, false); } // 清理要移除的节点 while (this.removeQueueDict.ContainsKey(saNode) && this.removeQueueDict[saNode].Count != 0) { saNode.TrueRouting.Remove(this.removeQueueDict[saNode].Dequeue()); } // 最后一个孩子的下一节点修改为for子句本身 SceneAction lastFor = saNode.TrueRouting[saNode.TrueRouting.Count - 1]; if (lastFor.Type != SActionType.act_break && lastFor.Type != SActionType.act_endfor) { lastFor.Next = saNode.Next; } else { this.BackpatchOptimizer(lastFor, saNode, false); } break; case SActionType.act_endfor: // endfor节点的下一节点是她的for母节点 saNode.Next = parent; // 弹for结构栈 this.forStack.Pop(); break; case SActionType.act_return: // 下一节点是null,这样运行时环境就会弹栈 saNode.Next = null; break; case SActionType.act_break: // break节点的下一节点是她的for母节点的后继 if (this.forStack.Count > 0) { saNode.Next = this.forStack.Peek().Next; } else { throw new InterpreterException("break必须存在for结构的内部"); } break; case SActionType.act_if: // 处理真分支 if (saNode.TrueRouting == null || saNode.TrueRouting.Count == 0) { break; } // 递归访问子节点 for (int i = 0; i < saNode.TrueRouting.Count - 1; i++) { this.BackpatchOptimizer(saNode.TrueRouting[i], saNode, false); } // 清理要移除的节点 while (this.removeQueueDict.ContainsKey(saNode) && this.removeQueueDict[saNode].Count != 0) { saNode.TrueRouting.Remove(this.removeQueueDict[saNode].Dequeue()); } // 最后一个孩子的下一节点修改为if子句节点的后继 SceneAction lastIfTrue = saNode.TrueRouting[saNode.TrueRouting.Count - 1]; // 考虑要更变next属性的节点 if (lastIfTrue.Type != SActionType.act_break && lastIfTrue.Type != SActionType.act_endfor && lastIfTrue.Type != SActionType.act_return) { lastIfTrue.Next = saNode.Next; } else { this.BackpatchOptimizer(lastIfTrue, saNode, false); } // 处理假分支 if (saNode.FalseRouting == null || saNode.FalseRouting.Count == 0) { break; } // 递归访问子节点 for (int i = 0; i < saNode.FalseRouting.Count - 1; i++) { this.BackpatchOptimizer(saNode.FalseRouting[i], saNode, false); } // 清理要移除的节点 while (this.removeQueueDict.ContainsKey(saNode) && this.removeQueueDict[saNode].Count != 0) { saNode.FalseRouting.Remove(this.removeQueueDict[saNode].Dequeue()); } // 最后一个孩子的下一节点修改为if子句节点的后继 SceneAction lastIfFalse = saNode.FalseRouting[saNode.FalseRouting.Count - 1]; // 考虑要更变next属性的节点 if (lastIfFalse.Type != SActionType.act_break && lastIfFalse.Type != SActionType.act_endfor && lastIfFalse.Type != SActionType.act_return) { lastIfFalse.Next = saNode.Next; } else { this.BackpatchOptimizer(lastIfFalse, saNode, false); } break; default: break; } // 如果是函数序列就返回一个函数实例 SceneFunction retSF = null; if (funcFlag) { retSF = this.ConstructSceneFunction(saNode); } // 最后让递归过程去修改子节点的属性 saNode.IsBelongFunc = funcFlag; return retSF; }
/// <summary> /// 递归遍历抽象语法树,构造动作序列 /// </summary> /// <param name="mynode">递归节点</param> /// <param name="curSa">当前场景的动作序列头部</param> /// <param name="funcSaVec">依附在该场景下的函数的动作序列向量</param> private void AST(SyntaxTreeNode mynode, ref SceneAction curSa, List<SceneAction> funcSaVec) { // 设置SA的行列属性 if (curSa != null) { curSa.Tag = mynode.Line.ToString() + "-" + mynode.Column.ToString(); } // 自顶向下递归遍历语法树 switch (mynode.NodeSyntaxType) { case SyntaxType.case_kotori: // 如果是总的根节点 if (curSa == null) { curSa = new SceneAction(); curSa.Tag = mynode.Line.ToString() + "-" + mynode.Column.ToString(); } if (mynode.Children == null) { break; } List<SceneAction> kotoriTrueList = new List<SceneAction>(); curSa.TrueRouting = kotoriTrueList; // 递归遍历 foreach (SyntaxTreeNode child in mynode.Children) { SceneAction sa = new SceneAction(); sa.Tag = mynode.Line.ToString() + "-" + mynode.Column.ToString(); sa.Type = (SActionType)Enum.Parse(typeof(SActionType), "act_" + child.NodeSyntaxType.ToString().Replace("synr_", "")); // 跳过增广文法节点,拷贝参数字典 if (child.NodeSyntaxType.ToString().StartsWith("synr_") && child.ParamDict != null) { foreach (KeyValuePair<string, SyntaxTreeNode> kvp in child.ParamDict) { if (kvp.Value.Children != null) { sa.ArgsDict.Add(kvp.Key, this.Folding(this.ConstructArgPolish(kvp.Value.Children[0]), mynode)); } else { sa.ArgsDict.Add(kvp.Key, ""); } } } // 如果不是函数定义的话递归就这个孩子,加到真分支去 if (child.NodeSyntaxType != SyntaxType.synr_function) { kotoriTrueList.Add(sa); } this.AST(child, ref sa, funcSaVec); } // 处理序列关系 for (int i = 0; i < kotoriTrueList.Count - 1; i++) { kotoriTrueList[i].Next = kotoriTrueList[i + 1]; } break; case SyntaxType.synr_if: // 处理条件指针 curSa.CondPolish = this.Folding(this.ConstructArgPolish(mynode.ParamDict["cond"]), mynode); // 处理真分支 curSa.TrueRouting = new List<SceneAction>(); if (mynode.Children[0] == null) { break; } SceneAction saIfTrue = new SceneAction(); saIfTrue.Tag = mynode.Line.ToString() + "-" + mynode.Column.ToString(); this.AST(mynode.Children[0], ref saIfTrue, funcSaVec); for (int i = 0; i < saIfTrue.TrueRouting.Count; i++) { curSa.TrueRouting.Add(saIfTrue.TrueRouting[i]); } // 处理假分支 curSa.FalseRouting = new List<SceneAction>(); if (mynode.Children[1] == null || (mynode.Children[1].NodeSyntaxType == SyntaxType.synr_endif)) { break; } SceneAction saIfFalse = new SceneAction(); saIfFalse.Tag = mynode.Line.ToString() + "-" + mynode.Column.ToString(); this.AST(mynode.Children[1], ref saIfFalse, funcSaVec); for (int i = 0; i < saIfFalse.TrueRouting.Count; i++) { // 这里之所以是trueRouting是因为kotori节点的缘故 curSa.FalseRouting.Add(saIfFalse.TrueRouting[i]); } break; case SyntaxType.synr_for: // 处理条件指针 if (mynode.ParamDict.ContainsKey("cond")) { curSa.CondPolish = this.Folding(this.ConstructArgPolish(mynode.ParamDict["cond"]), mynode); } // 处理真分支 curSa.TrueRouting = new List<SceneAction>(); if (mynode.Children[0] == null) { break; } SceneAction saForTrue = new SceneAction(); saForTrue.Tag = mynode.Line.ToString() + "-" + mynode.Column.ToString(); this.AST(mynode.Children[0], ref saForTrue, funcSaVec); for (int i = 0; i < saForTrue.TrueRouting.Count; i++) { curSa.TrueRouting.Add(saForTrue.TrueRouting[i]); } break; case SyntaxType.synr_function: // 处理真分支 if (mynode.Children[0] == null) { break; } SceneAction saFuncTrue = new SceneAction(); saFuncTrue.Tag = mynode.Line.ToString() + "-" + mynode.Column.ToString(); curSa.TrueRouting = new List<SceneAction>(); this.AST(mynode.Children[0], ref saFuncTrue, funcSaVec); for (int i = 0; i < saFuncTrue.TrueRouting.Count; i++) { curSa.TrueRouting.Add(saFuncTrue.TrueRouting[i]); } curSa.IsBelongFunc = true; // 加到函数向量里 funcSaVec.Add(curSa); break; case SyntaxType.synr_label: string labelKey = mynode.ParamDict["name"].Children[0].NodeValue; curSa.Tag = labelKey; this.blockDict[labelKey] = curSa; break; case SyntaxType.synr_jump: break; case SyntaxType.synr_dialog: curSa.Tag = mynode.NodeValue; break; default: break; } // 给节点命名 curSa.NodeName = String.Format("{0}_{1}@{2}", this.scenario, mynode.Line, curSa.Type.ToString()); }
/// <summary> /// 将动作序列和从属于它的动作序列全部IL化 /// </summary> /// <param name="saRoot">递归开始节点</param> /// <returns>IL字符串</returns> private string ILGenerator(SceneAction saRoot) { StringBuilder resSb = new StringBuilder(""); Stack<SceneAction> processStack = new Stack<SceneAction>(); processStack.Push(saRoot); while (processStack.Count != 0) { SceneAction topSa = processStack.Pop(); // 栈,先处理falseRouting if (topSa.FalseRouting != null) { for (int i = topSa.FalseRouting.Count - 1; i >= 0; i--) { processStack.Push(topSa.FalseRouting[i]); } } // 处理trueRouting if (topSa.TrueRouting != null) { for (int i = topSa.TrueRouting.Count - 1; i >= 0; i--) { processStack.Push(topSa.TrueRouting[i]); } } resSb.AppendLine(topSa.ToIL()); } return resSb.ToString(); }
/// <summary> /// 构造器 /// </summary> /// <param name="scenario">场景名称</param> /// <param name="mainSa">主动作序列</param> /// <param name="funcVec">函数向量</param> public PackageScene(string scenario, SceneAction mainSa, List<SceneFunction> funcVec) { this.Scenario = scenario; this.Ctor = mainSa; this.FuncContainer = funcVec; }