/// <summary> /// 获取缩进 /// </summary> /// <param name="myNode">当前节点</param> /// <returns>树的缩进字符串</returns> private string DrawTree(SyntaxTreeNode myNode) { // 若空就不需要继续了 if (myNode == null) { return ""; } // 取父母节点,若空就不需要画线了 SyntaxTreeNode parent = myNode.Parent; if (parent == null) { return ""; } // 否则查询祖父母节点来看父母节点的排位 List<bool> lstline = new List<bool>(); while (parent != null) { SyntaxTreeNode pp = parent.Parent; int indexOfParent = 0; if (pp != null) { if (pp.NodeSyntaxType.ToString().StartsWith("synr_") && pp.ParamDict != null) { foreach (KeyValuePair<string, SyntaxTreeNode> kvp in pp.ParamDict) { if (kvp.Value == parent) { break; } else { indexOfParent++; } } int nocCount = 0; if (pp.Children != null) { nocCount += pp.Children.Count; } lstline.Add(indexOfParent < pp.ParamDict.Count + nocCount - 1); } else if (pp.Children != null) { for (; indexOfParent < pp.Children.Count; indexOfParent++) { if (parent == pp.Children[indexOfParent]) { break; } } lstline.Add(indexOfParent < pp.Children.Count - 1); } } parent = pp; } // 画纵向线 string builder = ""; for (int i = lstline.Count - 1; i >= 0; i--) { builder += lstline[i] ? "│ " : " "; } // 获得自己在兄弟姐妹中的排行 parent = myNode.Parent; int indexOfParent2 = 0; if (parent.NodeSyntaxType.ToString().StartsWith("synr_") && parent.ParamDict != null) { //foreach (KeyValuePair<string, SyntaxTreeNode> kvp in parent.paramDict) //{ // if (kvp.Value == parent) // { // break; // } // else // { // indexOfParent2++; // } //} //// 如果是最后一个就不要出头了 //if (indexOfParent2 < parent.paramDict.Count - 1) //{ // builder += "├─"; //} //else //{ // builder += "└─"; //} builder += "└─"; } else if (parent.Children != null) { for (; indexOfParent2 < parent.Children.Count; indexOfParent2++) { if (myNode == parent.Children[indexOfParent2]) { break; } } // 如果是最后一个就不要出头了 if (indexOfParent2 < parent.Children.Count - 1) { builder += "├─"; } else { builder += "└─"; } } return builder; }
/// <summary> /// 递归遍历显示 /// </summary> /// <param name="builder">字符串构造器</param> /// <param name="myNode">当前节点</param> /// <param name="identation">缩进量</param> private void GetTree(StringBuilder builder, SyntaxTreeNode myNode, ref int identation, bool dflag) { // 如果空就没必要继续了 if (myNode == null) { return; } // 画树 builder.Append(DrawTree(myNode)); if (dflag) { builder.Append("[d]"); } builder.Append(myNode.NodeName.ToString()); if (myNode.NodeSyntaxType >= SyntaxType.Unknown && myNode.NodeSyntaxType != SyntaxType.epsilonLeave && myNode.NodeSyntaxType != SyntaxType.tail_startEndLeave) { builder.Append(" (" + myNode.NodeValue + ")"); } else if (myNode.NodeSyntaxType == SyntaxType.synr_dialog) { string sub = myNode.NodeValue.Replace("\r", "").Replace("\n", ""); builder.Append(" (" + (sub.Length < 12 ? sub : sub.Substring(0, 11) + " ...") + ")"); } builder.Append(Environment.NewLine); // 缩进并打印结果 identation++; if (myNode.NodeSyntaxType.ToString().StartsWith("synr_") && myNode.ParamDict != null) { foreach (KeyValuePair<string, SyntaxTreeNode> kvp in myNode.ParamDict) { GetTree(builder, kvp.Value, ref identation, true); } } if (myNode.Children != null) { for (int i = 0; i < myNode.Children.Count; i++) { GetTree(builder, myNode.Children[i], ref identation, false); } } // 回归缩进 identation--; }
/// <summary> /// 常数折叠 /// </summary> /// <param name="polish">逆波兰式</param> /// <param name="mynode">该逆波兰式在语法树上的节点</param> /// <returns>优化后的逆波兰式</returns> private string Folding(string polish, SyntaxTreeNode mynode) { if (polish == null) { return null; } Stack<string> polishStack = new Stack<string>(); string[] polishItem = polish.Split(new char[]{' '}, StringSplitOptions.RemoveEmptyEntries); foreach (string item in polishItem) { PolishItemType ptype = this.GetPolishItemType(item); // 如果是操作数就入栈 if (ptype < PolishItemType.CAL_PLUS) { polishStack.Push(item); } // 操作符就出栈计算再入栈结果 else { // 只有!操作符是单目操作 if (ptype == PolishItemType.CAL_NOT && polishStack.Count >= 1) { if (this.GetPolishItemType(polishStack.Peek()) == PolishItemType.CONSTANT) { string booleanItem = polishStack.Pop(); polishStack.Push(Math.Abs(Convert.ToDouble(booleanItem)) < 1e-15 ? "1" : "0"); } // 非常数项就不能做常数折叠,把操作符入栈 else { polishStack.Push(item); } } else if (ptype >= PolishItemType.CAL_PLUS && polishStack.Count >= 2) { string operand2 = polishStack.Pop(); string operand1 = polishStack.Pop(); // 如果两个操作数有不是常数项的,那就不可以做常数折叠 if (this.GetPolishItemType(operand1) != PolishItemType.CONSTANT || this.GetPolishItemType(operand2) != PolishItemType.CONSTANT) { polishStack.Push(operand1); polishStack.Push(operand2); polishStack.Push(item); continue; } // 计算 double op1 = Convert.ToDouble(operand1); double op2 = Convert.ToDouble(operand2); double res = 0.0f; switch (ptype) { case PolishItemType.CAL_PLUS: res = op1 + op2; break; case PolishItemType.CAL_MINUS: res = op1 - op2; break; case PolishItemType.CAL_MULTI: res = op1 * op2; break; case PolishItemType.CAL_DIV: if (Math.Abs(op2) < 1e-15) { throw new InterpreterException() { Message = String.Format("除零错误:({0}/{1})", op1.ToString(), op2.ToString()), HitLine = mynode.Line, HitColumn = mynode.Column, HitPhase = InterpreterException.InterpreterPhase.Optimizer, SceneFileName = this.scenario }; } res = op1 / op2; break; case PolishItemType.CAL_ANDAND: res = (Math.Abs(op1) > 1e-15) && (Math.Abs(op2) > 1e-15) ? 1 : 0; break; case PolishItemType.CAL_OROR: res = (Math.Abs(op1) > 1e-15) || (Math.Abs(op2) > 1e-15) ? 1 : 0; break; case PolishItemType.CAL_EQUAL: res = op1 == op2 ? 1 : 0; break; case PolishItemType.CAL_NOTEQUAL: res = op1 != op2 ? 1 : 0; break; case PolishItemType.CAL_BIG: res = op1 > op2 ? 1 : 0; break; case PolishItemType.CAL_SMALL: res = op1 < op2 ? 1 : 0; break; case PolishItemType.CAL_BIGEQUAL: res = op1 >= op2 ? 1 : 0; break; case PolishItemType.CAL_SMALLEQUAL: res = op1 <= op2 ? 1 : 0; break; default: break; } // 把计算结果压栈 polishStack.Push(Convert.ToString(res)); } else { string polishStackTrace = ""; while (polishStack.Count != 0) { polishStackTrace = polishStack.Pop() + " "; } throw new InterpreterException() { Message = "polish栈运算错误,栈(顶->底):" + polishStackTrace, HitLine = -1, HitColumn = -1, HitPhase = InterpreterException.InterpreterPhase.Optimizer, SceneFileName = this.scenario }; } } } // 将栈转化为逆波兰式 string resStr = " "; while (polishStack.Count != 0) { string pitem = polishStack.Pop(); resStr = " " + pitem + resStr; } return resStr.TrimStart().TrimEnd(); }
/// <summary> /// 构造函数 /// </summary> /// <param name="type">节点类型</param> /// <param name="parent">节点的双亲</param> public SyntaxTreeNode(SyntaxType type = SyntaxType.Unknown, SyntaxTreeNode parent = null) { this.NodeName = type.ToString(); this.NodeSyntaxType = type; this.Parent = parent; }
/// <summary> /// 为命令推导项追加参数字典 /// </summary> /// <param name="statementNode">命令在树上的节点</param> /// <param name="sType">命令的语法类型</param> /// <param name="argv">参数列表</param> private void ConstructArgumentDict(SyntaxTreeNode statementNode, SyntaxType sType, params string[] argv) { statementNode.NodeSyntaxType = sType; foreach (string arg in argv) { statementNode.ParamDict[arg] = new SyntaxTreeNode( (SyntaxType)Enum.Parse(typeof(SyntaxType), String.Format("para_{0}", arg)), statementNode); } }
/// <summary> /// 获取缩进 /// </summary> /// <param name="myNode">当前节点</param> /// <returns>树的缩进字符串</returns> private string DrawTree(SyntaxTreeNode myNode) { // 若空就不需要继续了,否则取父母节点,若空就不需要画线了 SyntaxTreeNode parent = myNode?.Parent; if (parent == null) { return(String.Empty); } // 否则查询祖父母节点来看父母节点的排位 var lstline = new List <bool>(); while (parent != null) { SyntaxTreeNode pp = parent.Parent; int indexOfParent = 0; if (pp != null) { if (pp.NodeSyntaxType.ToString().StartsWith("synr_") && pp.ParamDict != null) { indexOfParent += pp.ParamDict.TakeWhile(kvp => kvp.Value != parent).Count(); int nocCount = 0; if (pp.Children != null) { nocCount += pp.Children.Count; } lstline.Add(indexOfParent < pp.ParamDict.Count + nocCount - 1); } else if (pp.Children != null) { for (; indexOfParent < pp.Children.Count; indexOfParent++) { if (parent == pp.Children[indexOfParent]) { break; } } lstline.Add(indexOfParent < pp.Children.Count - 1); } } parent = pp; } // 画纵向线 string builder = String.Empty; for (int i = lstline.Count - 1; i >= 0; i--) { builder += lstline[i] ? "│ " : " "; } // 获得自己在兄弟姐妹中的排行 parent = myNode.Parent; int indexOfParent2 = 0; if (parent.NodeSyntaxType.ToString().StartsWith("synr_") && parent.ParamDict != null) { builder += "└─"; } else if (parent.Children != null) { for (; indexOfParent2 < parent.Children.Count; indexOfParent2++) { if (myNode == parent.Children[indexOfParent2]) { break; } } // 如果是最后一个就不要出头了 if (indexOfParent2 < parent.Children.Count - 1) { builder += "├─"; } else { builder += "└─"; } } return(builder); }
/// <summary> /// 初始化语义分析器 /// </summary> /// <param name="scenario">场景名称</param> private void Reset(string scenario) { this.scenario = scenario; this.parseTree = new SyntaxTreeNode(SyntaxType.case_kotori); this.parseTree.NodeName = "myKotori_Root"; this.parser.BlockStack.Push(this.parseTree); }
/// <summary> /// 递归下降构造语法树并取下一节点 /// </summary> /// <param name="res">母亲节点</param> /// <returns>下一个拿去展开的产生式</returns> private SyntaxTreeNode RecursiveDescent(SyntaxTreeNode res) { // 已经没有需要递归下降的节点 if (res == null) { return null; } // 否则取她的母亲节点来取得自己的姐妹 SyntaxTreeNode parent = res.Parent; // 如果没有母亲,就说明已经回退到了树的最上层 if (parent == null || parent.Children == null) { return null; } int i = 0; // 遍历寻找自己在姐妹中的排位 for (; i < parent.Children.Count && parent.Children[i] != res; i++); // 跳过自己,找最大的妹妹 if (i + 1 < parent.Children.Count) { return parent.Children[i + 1]; } // 如果自己没有妹妹,那就递归去找母亲的妹妹 SyntaxTreeNode obac = this.RecursiveDescent(parent); if (obac != null) { return obac; } return null; }
/// <summary> /// 调用产生式处理函数 /// </summary> /// <param name="subroot">匹配树根节点</param> /// <param name="syntaxer">语法类型</param> /// <param name="detail">节点信息</param> /// <returns>产生式的处理函数</returns> public SyntaxTreeNode Call(SyntaxTreeNode subroot, SyntaxType syntaxer, Token detail) { return this.candidateProcessor(subroot, this.candidateType, syntaxer, detail); }
/// <summary> /// 调用产生式处理函数 /// </summary> /// <param name="subroot">匹配树根节点</param> /// <param name="syntaxer">语法类型</param> /// <param name="detail">节点信息</param> /// <returns>产生式的处理函数</returns> public SyntaxTreeNode Call(SyntaxTreeNode subroot, SyntaxType syntaxer, Token detail) { return(this.candidateProcessor(subroot, this.candidateType, syntaxer, detail)); }
/// <summary> /// 常数折叠 /// </summary> /// <param name="polish">逆波兰式</param> /// <param name="mynode">该逆波兰式在语法树上的节点</param> /// <returns>优化后的逆波兰式</returns> private string Folding(string polish, SyntaxTreeNode mynode) { if (polish == null) { return(null); } var polishStack = new Stack <string>(); var polishItem = polish.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string item in polishItem) { OptimizerPolishItemType ptype = this.GetPolishItemType(item); // 如果是操作数就入栈 if (ptype < OptimizerPolishItemType.CAL_PLUS) { polishStack.Push(item); } // 操作符就出栈计算再入栈结果 else { // 只有!操作符是单目操作 if (ptype == OptimizerPolishItemType.CAL_NOT && polishStack.Count >= 1) { if (this.GetPolishItemType(polishStack.Peek()) == OptimizerPolishItemType.CONSTANT) { string booleanItem = polishStack.Pop(); polishStack.Push(Math.Abs(Convert.ToDouble(booleanItem)) < 1e-15 ? "1" : "0"); } // 非常数项就不能做常数折叠,把操作符入栈 else { polishStack.Push(item); } } else if (ptype >= OptimizerPolishItemType.CAL_PLUS && polishStack.Count >= 2) { string operand2 = polishStack.Pop(); string operand1 = polishStack.Pop(); // 如果两个操作数有不是常数项的,那就不可以做常数折叠 if (this.GetPolishItemType(operand1) != OptimizerPolishItemType.CONSTANT || this.GetPolishItemType(operand2) != OptimizerPolishItemType.CONSTANT) { polishStack.Push(operand1); polishStack.Push(operand2); polishStack.Push(item); continue; } // 计算 double op1 = Convert.ToDouble(operand1); double op2 = Convert.ToDouble(operand2); double res = 0.0f; switch (ptype) { case OptimizerPolishItemType.CAL_PLUS: res = op1 + op2; break; case OptimizerPolishItemType.CAL_MINUS: res = op1 - op2; break; case OptimizerPolishItemType.CAL_MULTI: res = op1 * op2; break; case OptimizerPolishItemType.CAL_DIV: if (Math.Abs(op2) < 1e-15) { throw new InterpreterException() { Message = String.Format("除零错误:({0}/{1})", op1.ToString(), op2.ToString()), HitLine = mynode.Line, HitColumn = mynode.Column, HitPhase = InterpreterPhase.Optimizer, SceneFileName = this.scenario }; } res = op1 / op2; break; case OptimizerPolishItemType.CAL_ANDAND: res = (Math.Abs(op1) > 1e-15) && (Math.Abs(op2) > 1e-15) ? 1 : 0; break; case OptimizerPolishItemType.CAL_OROR: res = (Math.Abs(op1) > 1e-15) || (Math.Abs(op2) > 1e-15) ? 1 : 0; break; case OptimizerPolishItemType.CAL_EQUAL: res = Math.Abs(op1 - op2) < 1e-15 ? 1 : 0; break; case OptimizerPolishItemType.CAL_NOTEQUAL: res = Math.Abs(op1 - op2) > 1e-15 ? 1 : 0; break; case OptimizerPolishItemType.CAL_BIG: res = op1 > op2 ? 1 : 0; break; case OptimizerPolishItemType.CAL_SMALL: res = op1 < op2 ? 1 : 0; break; case OptimizerPolishItemType.CAL_BIGEQUAL: res = op1 >= op2 ? 1 : 0; break; case OptimizerPolishItemType.CAL_SMALLEQUAL: res = op1 <= op2 ? 1 : 0; break; default: break; } // 把计算结果压栈 polishStack.Push(Convert.ToString(res)); } else { string polishStackTrace = String.Empty; while (polishStack.Count != 0) { polishStackTrace = polishStack.Pop() + " "; } throw new InterpreterException() { Message = "polish栈运算错误,栈(顶->底):" + polishStackTrace, HitLine = -1, HitColumn = -1, HitPhase = InterpreterPhase.Optimizer, SceneFileName = this.scenario }; } } } // 将栈转化为逆波兰式 string resStr = " "; while (polishStack.Count != 0) { string pitem = polishStack.Pop(); resStr = " " + pitem + resStr; } return(resStr.TrimStart().TrimEnd()); }
/// <summary> /// 递归遍历LL1文法,构造逆波兰式 /// </summary> /// <param name="mynode">递归语法树根节点</param> /// <returns>该节点的逆波兰式</returns> private string ConstructArgPolish(SyntaxTreeNode mynode) { switch (mynode.NodeSyntaxType) { // 需要处理逆波兰式的节点 case SyntaxType.case_wexpr: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wexpr__wmulti__wexpr_pi_45) { this.ConstructArgPolish(mynode.Children[0]); // 因式 this.ConstructArgPolish(mynode.Children[1]); // 加项 mynode.Polish += mynode.Children[0].Polish + mynode.Children[1].Polish; } else { mynode.Polish = String.Empty; } break; case SyntaxType.case_wexpr_pi: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wexpr_pi__wplus__wexpr_pi_72) { this.ConstructArgPolish(mynode.Children[0]); // 加项 this.ConstructArgPolish(mynode.Children[1]); // 加项闭包 mynode.Polish += mynode.Children[0].Polish + mynode.Children[1].Polish; } break; case SyntaxType.case_wplus: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wplus__plus_wmulti_46) { this.ConstructArgPolish(mynode.Children[1]); // 加法 mynode.Polish = mynode.Children[1].Polish + " + "; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wplus__minus_wmulti_47) { this.ConstructArgPolish(mynode.Children[1]); // 减法 mynode.Polish = mynode.Children[1].Polish + " - "; } else { mynode.Polish = String.Empty; } break; case SyntaxType.case_wmulti: this.ConstructArgPolish(mynode.Children[0]); // 乘项 this.ConstructArgPolish(mynode.Children[1]); // 乘项闭包 mynode.Polish = " " + mynode.Children[0].Polish + mynode.Children[1].Polish; break; case SyntaxType.case_wmultiOpt: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wmultiOpt__multi_wunit__wmultiOpt_50) { this.ConstructArgPolish(mynode.Children[1]); // 乘项 this.ConstructArgPolish(mynode.Children[2]); // 乘项闭包 // 乘法 mynode.Polish = " " + mynode.Children[1].Polish + " * " + mynode.Children[2].Polish; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wmultiOpt__div_wunit__wmultiOpt_51) { this.ConstructArgPolish(mynode.Children[1]); // 乘项 this.ConstructArgPolish(mynode.Children[2]); // 乘项闭包 // 除法 mynode.Polish = " " + mynode.Children[1].Polish + " / " + mynode.Children[2].Polish; } else { mynode.Polish = String.Empty; } break; case SyntaxType.case_wunit: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__number_53) { mynode.Polish = mynode.Children[0].NodeValue; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__minus_wunit_55) { this.ConstructArgPolish(mynode.Children[1]); mynode.Polish = "-" + mynode.Children[1].Polish; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__plus_wunit_56) { this.ConstructArgPolish(mynode.Children[1]); mynode.Polish = mynode.Children[1].Polish; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__brucket_disjunct_57) { this.ConstructArgPolish(mynode.Children[1]); mynode.Polish = mynode.Children[1].Polish; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__iden_54) { switch (mynode.Children[0].NodeVarType) { case VarScopeType.GLOBAL: mynode.Polish = "&" + mynode.Children[0].NodeValue; break; case VarScopeType.LOCAL: mynode.Polish = "$" + mynode.Children[0].NodeValue; break; case VarScopeType.PERSIST: mynode.Polish = "%" + mynode.Children[0].NodeValue; break; default: mynode.Polish = mynode.Children[0].NodeValue; break; } } break; case SyntaxType.case_disjunct: this.ConstructArgPolish(mynode.Children[0]); // 合取项 this.ConstructArgPolish(mynode.Children[1]); // 析取闭包 mynode.Polish = mynode.Children[0].Polish + mynode.Children[1].Polish; break; case SyntaxType.case_disjunct_pi: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___disjunct_pi__conjunct__disjunct_pi_36) { this.ConstructArgPolish(mynode.Children[1]); // 合取项 this.ConstructArgPolish(mynode.Children[2]); // 析取闭包 mynode.Polish = mynode.Children[1].Polish + mynode.Children[2].Polish; if (mynode.Children[2].Polish != String.Empty) { mynode.Polish += " || "; } } else { mynode.Polish = String.Empty; } break; case SyntaxType.case_conjunct: this.ConstructArgPolish(mynode.Children[0]); // 布尔项 this.ConstructArgPolish(mynode.Children[1]); // 合取闭包 mynode.Polish = mynode.Children[0].Polish + mynode.Children[1].Polish; break; case SyntaxType.case_conjunct_pi: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___conjunct_pi__bool__conjunct_pi_39) { this.ConstructArgPolish(mynode.Children[1]); // 布尔项 this.ConstructArgPolish(mynode.Children[2]); // 合取闭包 mynode.Polish = mynode.Children[1].Polish + mynode.Children[2].Polish; if (mynode.Children[2].Polish != String.Empty) { mynode.Polish += " && "; } } else { mynode.Polish = String.Empty; } break; case SyntaxType.case_bool: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___bool__not_bool_42) { this.ConstructArgPolish(mynode.Children[1]); // 非项 mynode.Polish = mynode.Children[1].Polish + " ! "; } else { this.ConstructArgPolish(mynode.Children[0]); // 表达式 mynode.Polish = mynode.Children[0].Polish; } break; case SyntaxType.case_comp: if (mynode.Children[1].CandidateFunction.GetCFType() == CFunctionType.deri___rop__epsilon_80) { this.ConstructArgPolish(mynode.Children[0]); // 左边 mynode.Polish = mynode.Children[0].Polish; } else { string optype = mynode.Children[1].NodeValue; // 运算符 this.ConstructArgPolish(mynode.Children[0]); // 左边 this.ConstructArgPolish(mynode.Children[2]); // 右边 mynode.Polish = String.Empty; if (optype == "<>") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " <> "; } else if (optype == "==") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " == "; } else if (optype == ">") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " > "; } else if (optype == "<") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " < "; } else if (optype == ">=") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " >= "; } else if (optype == "<=") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " <= "; } } break; case SyntaxType.tail_idenLeave: switch (mynode.NodeVarType) { case VarScopeType.GLOBAL: mynode.Polish = "&" + mynode.NodeValue; break; case VarScopeType.LOCAL: mynode.Polish = "$" + mynode.NodeValue; break; case VarScopeType.PERSIST: mynode.Polish = "%" + mynode.NodeValue; break; default: mynode.Polish = mynode.NodeValue; break; } break; default: break; } if (mynode.NodeSyntaxType.ToString().StartsWith("para_")) { if (mynode.Children != null && mynode.Children.Count > 0) { mynode.Polish = mynode.Children[0].Polish; } } return(mynode.Polish); }
/// <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_", String.Empty)); // 跳过增广文法节点,拷贝参数字典 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, String.Empty); } } } // 如果不是函数定义的话递归就这个孩子,加到真分支去 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> /// 进行语法分析 /// </summary> /// <param name="line">处理的行号</param> /// <returns>匹配完毕的语法树</returns> public SyntaxTreeNode Parse(int line) { // 初期化 this.Reset(line); // 获得原始节点的引用 SyntaxTreeNode parsePtr; SyntaxTreeNode currentPtr; // 如果语句块嵌套栈顶端是可以推出语句块的类型就直接把她作为双亲节点 if (this.BlockStack.Peek().NodeSyntaxType == SyntaxType.case_kotori) { parsePtr = currentPtr = this.BlockStack.Peek(); } // 否则处理这个节点的语句块的从属关系 else { parsePtr = new SyntaxTreeNode(SyntaxType.case_kotori); currentPtr = parsePtr; currentPtr.Parent = this.BlockStack.Peek(); currentPtr.Children = new List<SyntaxTreeNode>(); if (this.BlockStack.Peek().Children == null) { this.BlockStack.Peek().Children = new List<SyntaxTreeNode>(); } this.BlockStack.Peek().Children.Add(currentPtr); } // 自顶向下,语法分析 bool fromKaguya = false; while (this.parseStack.Count != 0 || this.commandDerivatorQueue.Count != 0) { // 语句根节点,就调用命令推导函数去处理,随后立即迭代掉本次循环 if (this.parseStack.Count > 0 && this.parseStack.Peek() == SyntaxType.case_kotori) { SyntaxTreeNode stn = this.Chitanda(); stn.Line = line; // 如果这个节点是if、for、function子句,那就要为她增加一个kotori节点 if (stn.NodeSyntaxType == SyntaxType.synr_if || stn.NodeSyntaxType == SyntaxType.synr_for || stn.NodeSyntaxType == SyntaxType.synr_function) { // 把原来的子句节点加到原来的匹配树上 stn.Parent = currentPtr; if (currentPtr.Children == null) { currentPtr.Children = new List<SyntaxTreeNode>(); } currentPtr.Children.Add(stn); currentPtr = stn; currentPtr.Line = line; // 为子句节点加上一个真分支 currentPtr.Children = new List<SyntaxTreeNode>(); SyntaxTreeNode trueBranch = new SyntaxTreeNode(SyntaxType.case_kotori); trueBranch.Line = line; trueBranch.Children = new List<SyntaxTreeNode>(); trueBranch.NodeName = trueBranch.NodeSyntaxType.ToString() + (stn.NodeSyntaxType == SyntaxType.synr_if ? "_trueBranch" : stn.NodeSyntaxType == SyntaxType.synr_for ? "_forBranch" : "_funDeclaration"); trueBranch.Parent = currentPtr; stn.Children.Add(trueBranch); // 追加到语句块栈 BlockStack.Push(trueBranch); currentPtr = trueBranch; } // 如果这个节点是else子句,那就直接用kotori节点换掉她 else if (stn.NodeSyntaxType == SyntaxType.synr_else) { currentPtr = currentPtr.Parent; SyntaxTreeNode falseBranch = new SyntaxTreeNode(SyntaxType.case_kotori); falseBranch.Line = line; falseBranch.Children = new List<SyntaxTreeNode>(); falseBranch.NodeName = falseBranch.NodeSyntaxType.ToString() + "_falseBranch"; falseBranch.Parent = currentPtr; currentPtr.Children.Add(falseBranch); // 追加到语句块栈 BlockStack.Push(falseBranch); currentPtr = falseBranch; } // 如果这个节点是endif子句,那就直接用她换掉kotori节点 else if (stn.NodeSyntaxType == SyntaxType.synr_endif) { SyntaxTreeNode originTop = parsePtr.Parent; originTop.Children.Add(stn); stn.Parent = originTop; currentPtr = parsePtr = stn; } // 其余情况就把该节点作为当前展开节点的孩子节点 else { stn.Parent = currentPtr; if (currentPtr.Children == null) { currentPtr.Children = new List<SyntaxTreeNode>(); } currentPtr.Children.Add(stn); currentPtr = stn; } fromKaguya = true; continue; } // 如果栈中只有startend,队列中没有元素,那就意味着不需要继续推导了 if (this.parseStack.Count > 0 && this.parseStack.Peek() == SyntaxType.tail_startEndLeave && this.commandDerivatorQueue.Count == 0) { break; } // 如果栈中不空,说明在做LL1文法的推导 if (this.parseStack.Count != 0 && fromKaguya == false) { // 查预测表,获得产生式处理函数 SyntaxType nodeType = this.parseStack.Peek(); Token iToken = this.istream[this.nextTokenPointer]; TokenType tokenType = iToken.Type; CandidateFunction func = this.iMap.GetCFunction(nodeType, tokenType, this.Derivate); // 语法出错时 if (func.GetCFType() == CFunctionType.umi_errorEnd) { throw new InterpreterException() { Message = "语法匹配错误", HitLine = iToken.Line, HitColumn = iToken.Column, HitPhase = InterpreterException.InterpreterPhase.Parser, SceneFileName = this.dealingFile }; } // 如果处于非终结符,就设置她的候选式 if (currentPtr != null) { currentPtr.CandidateFunction = func; } // 调用产生式,下降 if (func != null) { if (currentPtr != null) { currentPtr = currentPtr.CandidateFunction.Call(currentPtr, nodeType, iToken); } else { currentPtr = this.Derivate(currentPtr, func.GetCFType(), nodeType, iToken); } if (currentPtr != null) { currentPtr.Line = line; } } // 没有对应的候选式时 else { if (currentPtr != null) { currentPtr.ErrorBit = true; } break; } } // 最后看命令推导队列 else if (this.commandDerivatorQueue.Count != 0) { SyntaxTreeNode reroot = this.commandDerivatorQueue.Dequeue(); // 析取范式时 if (reroot.NodeSyntaxType == SyntaxType.case_disjunct) { this.parseStack.Push(SyntaxType.case_disjunct); } // 值表达式时 else { this.parseStack.Push(reroot.NodeSyntaxType); } // 把token流改为私有的token流 this.istream = reroot.ParamTokenStream; // 在流的末尾,放置结束标记 Token ccToken = new Token(); ccToken.Length = 1; ccToken.OriginalCodeStr = "#"; ccToken.ErrorBit = false; ccToken.Type = TokenType.startend; ccToken.Line = this.dealingLine; ccToken.Column = this.istream.Count > 0 ? this.istream[Math.Min(this.nextTokenPointer, this.istream.Count - 1)].Column : -1; this.istream.Add(ccToken); // 复位游程 this.nextTokenPointer = 0; // 修改当前指针 currentPtr = reroot; } fromKaguya = false; } return parsePtr; }
/// <summary> /// 进行语义分析 /// </summary> /// <param name="root">语法树根节点</param> /// <returns>一个键值对,剧本的动作序列和函数向量</returns> private KeyValuePair<SceneAction, List<SceneFunction>> Semanticer(SyntaxTreeNode root) { SceneAction resSa = null; List<SceneAction> funcSaVec = new List<SceneAction>(); List<SceneFunction> funcVec = new List<SceneFunction>(); this.forStack = new Stack<SceneAction>(); this.removeQueueDict = new Dictionary<SceneAction, Queue<SceneAction>>(); this.blockDict = new Dictionary<string, SceneAction>(); this.AST(this.parseTree, ref resSa, funcSaVec); this.BackpatchOptimizer(resSa, resSa, false); funcSaVec.ForEach((x) => funcVec.Add(this.BackpatchOptimizer(x, x, true))); resSa.Tag = this.scenario; return new KeyValuePair<SceneAction, List<SceneFunction>>(resSa, funcVec); }
/// <summary> /// 为参数的字典节点追加LL1文法推导项 /// </summary> /// <param name="arg">参数在字典中的名字</param> /// <param name="derivator">LL1文法推导起始类型</param> private void ProcessArgumentDerivator(SyntaxTreeNode statementNode, ref int prescanPointer, string arg, SyntaxType derivator) { statementNode.ParamDict[arg].Children = new List<SyntaxTreeNode>(); SyntaxTreeNode derivationNode = new SyntaxTreeNode(derivator, statementNode.ParamDict[arg]); derivationNode.ParamTokenStream = new List<Token>(); prescanPointer += 2; while (prescanPointer < this.istream.Count && !this.istream[prescanPointer].Type.ToString().StartsWith("Token_p") && this.istream[prescanPointer].Type != TokenType.startend) { derivationNode.ParamTokenStream.Add(this.istream[prescanPointer++]); } statementNode.ParamDict[arg].Children.Add(derivationNode); // 加入命令推导队列 this.commandDerivatorQueue.Enqueue(derivationNode); }
/// <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> /// 将所有非LL1推导项构造到语法树上 /// </summary> /// <returns>预处理完毕的单语句语法树根节点</returns> private SyntaxTreeNode Chitanda() { // 匹配栈出栈 this.parseStack.Pop(); int prescanPointer = this.nextTokenPointer; // 扫描token流,命中的第一个关键字token决定了节点类型 if (this.istream[prescanPointer].Type == TokenType.Token_At) { // 跳过At符号,读下一个token prescanPointer++; Token mainToken = this.istream[prescanPointer]; // 从下一token的类型决定构造的语法树根节点类型,构造参数字典 SyntaxTreeNode statementNode = new SyntaxTreeNode(); statementNode.ParamDict = new Dictionary<string, SyntaxTreeNode>(); switch (mainToken.Type) { case TokenType.Token_o_a: this.ConstructArgumentDict(statementNode, SyntaxType.synr_a, "name", "vid", "face", "loc"); break; case TokenType.Token_o_bg: this.ConstructArgumentDict(statementNode, SyntaxType.synr_bg, "id", "filename", "x", "y", "opacity", "xscale", "yscale", "ro"); break; case TokenType.Token_o_picture: this.ConstructArgumentDict(statementNode, SyntaxType.synr_picture, "id", "filename", "x", "y", "opacity", "xscale", "yscale", "ro"); break; case TokenType.Token_o_move: this.ConstructArgumentDict(statementNode, SyntaxType.synr_move, "name", "id", "time", "target", "dash", "acc"); break; case TokenType.Token_o_deletepicture: this.ConstructArgumentDict(statementNode, SyntaxType.synr_deletecstand, "id"); break; case TokenType.Token_o_cstand: this.ConstructArgumentDict(statementNode, SyntaxType.synr_cstand, "id", "name", "face", "x", "y"); break; case TokenType.Token_o_deletecstand: this.ConstructArgumentDict(statementNode, SyntaxType.synr_deletecstand, "id"); break; case TokenType.Token_o_se: this.ConstructArgumentDict(statementNode, SyntaxType.synr_se, "filename", "vol"); break; case TokenType.Token_o_bgm: this.ConstructArgumentDict(statementNode, SyntaxType.synr_bgm, "filename", "vol"); break; case TokenType.Token_o_bgs: this.ConstructArgumentDict(statementNode, SyntaxType.synr_bgs, "filename", "vol"); break; case TokenType.Token_o_button: this.ConstructArgumentDict(statementNode, SyntaxType.synr_button, "id", "x", "y", "target", "normal", "over", "on", "type", "sign"); break; case TokenType.Token_o_deletebutton: this.ConstructArgumentDict(statementNode, SyntaxType.synr_deletebutton, "id"); break; case TokenType.Token_o_vocal: this.ConstructArgumentDict(statementNode, SyntaxType.synr_vocal, "name", "vid", "vol"); break; case TokenType.Token_o_label: this.ConstructArgumentDict(statementNode, SyntaxType.synr_label, "name"); break; case TokenType.Token_o_jump: this.ConstructArgumentDict(statementNode, SyntaxType.synr_jump, "filename", "target", "cond"); break; case TokenType.Token_o_call: this.ConstructArgumentDict(statementNode, SyntaxType.synr_call, "name", "sign"); break; case TokenType.Token_o_draw: this.ConstructArgumentDict(statementNode, SyntaxType.synr_draw, "id", "dash"); break; case TokenType.Token_o_switch: this.ConstructArgumentDict(statementNode, SyntaxType.synr_switch, "id", "state"); break; case TokenType.Token_o_var: this.ConstructArgumentDict(statementNode, SyntaxType.synr_var, "name", "dash"); break; case TokenType.Token_o_wait: this.ConstructArgumentDict(statementNode, SyntaxType.synr_wait, "time"); break; case TokenType.Token_o_branch: this.ConstructArgumentDict(statementNode, SyntaxType.synr_branch, "link"); break; case TokenType.Token_o_msglayer: this.ConstructArgumentDict(statementNode, SyntaxType.synr_msglayer, "id"); break; case TokenType.Token_o_msglayeropt: this.ConstructArgumentDict(statementNode, SyntaxType.synr_msglayeropt, "id", "target", "dash"); break; case TokenType.Token_o_trans: this.ConstructArgumentDict(statementNode, SyntaxType.synr_trans, "name"); break; case TokenType.Token_o_save: this.ConstructArgumentDict(statementNode, SyntaxType.synr_save, "filename"); break; case TokenType.Token_o_load: this.ConstructArgumentDict(statementNode, SyntaxType.synr_load, "filename"); break; case TokenType.Token_o_stopbgm: statementNode.NodeSyntaxType = SyntaxType.synr_stopbgm; break; case TokenType.Token_o_stopbgs: statementNode.NodeSyntaxType = SyntaxType.synr_stopbgs; break; case TokenType.Token_o_titlepoint: statementNode.NodeSyntaxType = SyntaxType.synr_titlepoint; break; case TokenType.Token_o_stopvocal: statementNode.NodeSyntaxType = SyntaxType.synr_stopvocal; break; case TokenType.Token_o_title: statementNode.NodeSyntaxType = SyntaxType.synr_title; break; case TokenType.Token_o_menu: statementNode.NodeSyntaxType = SyntaxType.synr_menu; break; case TokenType.Token_o_waitani: statementNode.NodeSyntaxType = SyntaxType.synr_waitani; break; case TokenType.Token_o_break: statementNode.NodeSyntaxType = SyntaxType.synr_break; break; case TokenType.Token_o_waituser: statementNode.NodeSyntaxType = SyntaxType.synr_waituser; break; case TokenType.Token_o_freeze: statementNode.NodeSyntaxType = SyntaxType.synr_freeze; break; case TokenType.Token_o_shutdown: statementNode.NodeSyntaxType = SyntaxType.synr_shutdown; break; case TokenType.Token_o_return: statementNode.NodeSyntaxType = SyntaxType.synr_return; break; case TokenType.Token_o_for: statementNode.NodeSyntaxType = SyntaxType.synr_for; statementNode.ParamDict["cond"] = new SyntaxTreeNode(SyntaxType.para_cond, statementNode); // 这里不追加语句块,因为它将在Parse中处理 break; case TokenType.Token_o_endfor: statementNode.NodeSyntaxType = SyntaxType.synr_endfor; // 消除语句块栈 if (BlockStack.Peek().NodeSyntaxType == SyntaxType.case_kotori && BlockStack.Peek().NodeName.EndsWith("_forBranch")) { BlockStack.Pop(); } else { throw new InterpreterException() { Message = "for语句块匹配不成立,是否多余/残缺了endfor?", HitLine = this.dealingLine, HitColumn = mainToken.Column, HitPhase = InterpreterException.InterpreterPhase.Parser, SceneFileName = this.dealingFile }; } break; case TokenType.Token_o_if: statementNode.NodeSyntaxType = SyntaxType.synr_if; statementNode.ParamDict["cond"] = new SyntaxTreeNode(SyntaxType.para_cond, statementNode); // 这里不追加语句块,因为它将在Parse中处理 break; case TokenType.Token_o_else: statementNode.NodeSyntaxType = SyntaxType.synr_else; // 这里不追加语句块,因为它将在Parse中处理 break; case TokenType.Token_o_endif: statementNode.NodeSyntaxType = SyntaxType.synr_endif; // 消除语句块栈 if (BlockStack.Peek().NodeSyntaxType == SyntaxType.case_kotori && BlockStack.Peek().NodeName.EndsWith("_falseBranch")) { BlockStack.Pop(); } if (BlockStack.Peek().NodeSyntaxType == SyntaxType.case_kotori && BlockStack.Peek().NodeName.EndsWith("_trueBranch")) { BlockStack.Pop(); } else { throw new InterpreterException() { Message = "if语句块匹配不成立,是否多余/残缺了endif?", HitLine = this.dealingLine, HitColumn = mainToken.Column, HitPhase = InterpreterException.InterpreterPhase.Parser, SceneFileName = this.dealingFile }; } break; case TokenType.Token_o_function: statementNode.NodeSyntaxType = SyntaxType.synr_function; statementNode.ParamDict["sign"] = new SyntaxTreeNode(SyntaxType.para_sign, statementNode); // 这里不追加语句块,因为它将在Parse中处理 break; case TokenType.Token_o_endfunction: statementNode.NodeSyntaxType = SyntaxType.synr_endfunction; // 消除语句块栈 if (BlockStack.Peek().NodeSyntaxType == SyntaxType.case_kotori && BlockStack.Peek().NodeName.EndsWith("_funDeclaration")) { BlockStack.Pop(); } else { throw new InterpreterException() { Message = "函数定义匹配不成立,是否多余/残缺了endfunction?", HitLine = this.dealingLine, HitColumn = mainToken.Column, HitPhase = InterpreterException.InterpreterPhase.Parser, SceneFileName = this.dealingFile }; } break; case TokenType.scenecluster: throw new InterpreterException() { Message = "未识别的语句:" + mainToken.OriginalCodeStr, HitLine = this.dealingLine, HitColumn = mainToken.Column, HitPhase = InterpreterException.InterpreterPhase.Parser, SceneFileName = this.dealingFile }; case TokenType.sceneterminator: statementNode.NodeSyntaxType = SyntaxType.synr_dialogTerminator; break; default: break; } // 跳过主Token prescanPointer++; // 接下来预备扫描整个token序列,构造参数字典子树 bool latticeFlag = false; while (prescanPointer < this.istream.Count) { // 解析参数列表 switch (this.istream[prescanPointer].Type) { case TokenType.Token_p_name: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "name", SyntaxType.tail_idenLeave); break; case TokenType.Token_p_vid: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "vid", SyntaxType.case_wunit); break; case TokenType.Token_p_face: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "face", SyntaxType.tail_idenLeave); break; case TokenType.Token_p_id: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "id", SyntaxType.case_wunit); break; case TokenType.Token_p_target: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "target", SyntaxType.case_wunit); break; case TokenType.Token_p_type: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "type", SyntaxType.case_wunit); break; case TokenType.Token_p_x: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "x", SyntaxType.case_wunit); break; case TokenType.Token_p_y: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "y", SyntaxType.case_wunit); break; case TokenType.Token_p_z: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "z", SyntaxType.case_wunit); break; case TokenType.Token_p_normal: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "normal", SyntaxType.case_wunit); break; case TokenType.Token_p_over: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "over", SyntaxType.case_wunit); break; case TokenType.Token_p_on: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "on", SyntaxType.case_wunit); break; case TokenType.Token_p_acc: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "acc", SyntaxType.case_wunit); break; case TokenType.Token_p_opacity: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "opacity", SyntaxType.case_wunit); break; case TokenType.Token_p_xscale: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "xscale", SyntaxType.case_wunit); break; case TokenType.Token_p_yscale: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "yscale", SyntaxType.case_wunit); break; case TokenType.Token_p_time: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "time", SyntaxType.case_wunit); break; case TokenType.Token_p_filename: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "filename", SyntaxType.tail_idenLeave); break; case TokenType.Token_p_cond: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "cond", SyntaxType.case_disjunct); break; case TokenType.Token_p_dash: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "dash", SyntaxType.case_disjunct); break; case TokenType.Token_p_state: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "state", SyntaxType.tail_idenLeave); break; case TokenType.Token_p_vol: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "vol", SyntaxType.case_wunit); break; case TokenType.Token_p_loc: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "loc", SyntaxType.case_wunit); break; case TokenType.Token_p_ro: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "ro", SyntaxType.case_wunit); break; case TokenType.Token_p_link: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "link", SyntaxType.tail_idenLeave); break; case TokenType.Token_p_sign: this.ProcessArgumentDerivator(statementNode, ref prescanPointer, "sign", SyntaxType.tail_idenLeave); break; case TokenType.startend: break; default: throw new InterpreterException() { Message = "未识别的语句参数:" + this.istream[prescanPointer].OriginalCodeStr, HitLine = this.dealingLine, HitColumn = this.istream[prescanPointer].Column, HitPhase = InterpreterException.InterpreterPhase.Parser, SceneFileName = this.dealingFile }; } // 如果遇到startend就结束 if (this.istream[prescanPointer].Type == TokenType.startend) { latticeFlag = true; break; } } // 如果语句成功封闭,则返回根节点 if (latticeFlag) { return statementNode; } // 如果语句没有封闭就抛错误给上层 else { return null; } } // 如果是剧情文本的情况下 else if (this.istream[prescanPointer].Type == TokenType.scenecluster) { // 把所有的剧情文本聚合成篇章 SyntaxTreeNode statementNode = new SyntaxTreeNode(); Token sc = new Token(); sc.Type = TokenType.scenecluster; sc.Column = this.istream[prescanPointer].Column; sc.Line = this.istream[prescanPointer].Line; while (prescanPointer < this.istream.Count - 1 // 减1是要消掉startend的影响 && this.istream[prescanPointer].Type != TokenType.sceneterminator) { // 如果匹配错误,就直接向上层抛错误 if (!this.istream[prescanPointer].Type.ToString().StartsWith("scene")) { return null; } sc.Tag = (sc.OriginalCodeStr += this.istream[prescanPointer++].OriginalCodeStr); } // 把这个唯一token加到语法树上 statementNode.NodeSyntaxType = SyntaxType.synr_dialog; statementNode.NodeValue = (string)sc.Tag; statementNode.ParamTokenStream = new List<Token>(); statementNode.ParamTokenStream.Add(sc); return statementNode; } else if (this.istream[prescanPointer].Type == TokenType.sceneterminator) { SyntaxTreeNode statementNode = new SyntaxTreeNode(); statementNode.NodeSyntaxType = SyntaxType.synr_dialogTerminator; return statementNode; } // 除此以外,直接抛错误给上层 return null; }
/// <summary> /// 递归遍历LL1文法,构造逆波兰式 /// </summary> /// <param name="mynode">递归语法树根节点</param> /// <returns>该节点的逆波兰式</returns> private string ConstructArgPolish(SyntaxTreeNode mynode) { switch (mynode.NodeSyntaxType) { // 需要处理逆波兰式的节点 case SyntaxType.case_wexpr: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wexpr__wmulti__wexpr_pi_45) { this.ConstructArgPolish(mynode.Children[0]); // 因式 this.ConstructArgPolish(mynode.Children[1]); // 加项 mynode.Polish += mynode.Children[0].Polish + mynode.Children[1].Polish; } else { mynode.Polish = ""; } break; case SyntaxType.case_wexpr_pi: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wexpr_pi__wplus__wexpr_pi_72) { this.ConstructArgPolish(mynode.Children[0]); // 加项 this.ConstructArgPolish(mynode.Children[1]); // 加项闭包 mynode.Polish += mynode.Children[0].Polish + mynode.Children[1].Polish; } break; case SyntaxType.case_wplus: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wplus__plus_wmulti_46) { this.ConstructArgPolish(mynode.Children[1]); // 加法 mynode.Polish = mynode.Children[1].Polish + " + "; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wplus__minus_wmulti_47) { this.ConstructArgPolish(mynode.Children[1]); // 减法 mynode.Polish = mynode.Children[1].Polish + " - "; } else { mynode.Polish = ""; } break; case SyntaxType.case_wmulti: this.ConstructArgPolish(mynode.Children[0]); // 乘项 this.ConstructArgPolish(mynode.Children[1]); // 乘项闭包 mynode.Polish = " " + mynode.Children[0].Polish + mynode.Children[1].Polish; break; case SyntaxType.case_wmultiOpt: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wmultiOpt__multi_wunit__wmultiOpt_50) { this.ConstructArgPolish(mynode.Children[1]); // 乘项 this.ConstructArgPolish(mynode.Children[2]); // 乘项闭包 // 乘法 mynode.Polish = " " + mynode.Children[1].Polish + " * " + mynode.Children[2].Polish; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wmultiOpt__div_wunit__wmultiOpt_51) { this.ConstructArgPolish(mynode.Children[1]); // 乘项 this.ConstructArgPolish(mynode.Children[2]); // 乘项闭包 // 除法 mynode.Polish = " " + mynode.Children[1].Polish + " / " + mynode.Children[2].Polish; } else { mynode.Polish = ""; } break; case SyntaxType.case_wunit: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__number_53) { mynode.Polish = mynode.Children[0].NodeValue; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__minus_wunit_55) { this.ConstructArgPolish(mynode.Children[1]); mynode.Polish = "-" + mynode.Children[1].Polish; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__plus_wunit_56) { this.ConstructArgPolish(mynode.Children[1]); mynode.Polish = mynode.Children[1].Polish; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__brucket_disjunct_57) { this.ConstructArgPolish(mynode.Children[1]); mynode.Polish = mynode.Children[1].Polish; } else if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___wunit__iden_54) { if (mynode.Children[0].NodeVarType == VarScopeType.GLOBAL) { mynode.Polish = "&" + mynode.Children[0].NodeValue; } else if (mynode.Children[0].NodeVarType == VarScopeType.LOCAL) { mynode.Polish = "$" + mynode.Children[0].NodeValue; } else { mynode.Polish = mynode.Children[0].NodeValue; } } break; case SyntaxType.case_disjunct: this.ConstructArgPolish(mynode.Children[0]); // 合取项 this.ConstructArgPolish(mynode.Children[1]); // 析取闭包 mynode.Polish = mynode.Children[0].Polish + mynode.Children[1].Polish; break; case SyntaxType.case_disjunct_pi: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___disjunct_pi__conjunct__disjunct_pi_36) { this.ConstructArgPolish(mynode.Children[1]); // 合取项 this.ConstructArgPolish(mynode.Children[2]); // 析取闭包 mynode.Polish = mynode.Children[1].Polish + mynode.Children[2].Polish; if (mynode.Children[2].Polish != "") { mynode.Polish += " || "; } } else { mynode.Polish = ""; } break; case SyntaxType.case_conjunct: this.ConstructArgPolish(mynode.Children[0]); // 布尔项 this.ConstructArgPolish(mynode.Children[1]); // 合取闭包 mynode.Polish = mynode.Children[0].Polish + mynode.Children[1].Polish; break; case SyntaxType.case_conjunct_pi: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___conjunct_pi__bool__conjunct_pi_39) { this.ConstructArgPolish(mynode.Children[1]); // 布尔项 this.ConstructArgPolish(mynode.Children[2]); // 合取闭包 mynode.Polish = mynode.Children[1].Polish + mynode.Children[2].Polish; if (mynode.Children[2].Polish != "") { mynode.Polish += " && "; } } else { mynode.Polish = ""; } break; case SyntaxType.case_bool: if (mynode.CandidateFunction.GetCFType() == CFunctionType.deri___bool__not_bool_42) { this.ConstructArgPolish(mynode.Children[1]); // 非项 mynode.Polish = mynode.Children[1].Polish + " ! "; } else { this.ConstructArgPolish(mynode.Children[0]); // 表达式 mynode.Polish = mynode.Children[0].Polish; } break; case SyntaxType.case_comp: if (mynode.Children[1].CandidateFunction.GetCFType() == CFunctionType.deri___rop__epsilon_80) { this.ConstructArgPolish(mynode.Children[0]); // 左边 mynode.Polish = mynode.Children[0].Polish; } else { string optype = mynode.Children[1].NodeValue; // 运算符 this.ConstructArgPolish(mynode.Children[0]); // 左边 this.ConstructArgPolish(mynode.Children[2]); // 右边 mynode.Polish = ""; if (optype == "<>") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " <> "; } else if (optype == "==") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " == "; } else if (optype == ">") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " > "; } else if (optype == "<") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " < "; } else if (optype == ">=") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " >= "; } else if (optype == "<=") { mynode.Polish = mynode.Children[0].Polish + mynode.Children[2].Polish + " <= "; } } break; case SyntaxType.tail_idenLeave: if (mynode.NodeVarType == VarScopeType.GLOBAL) { mynode.Polish = "&" + mynode.NodeValue; } else if (mynode.NodeVarType == VarScopeType.LOCAL) { mynode.Polish = "$" + mynode.NodeValue; } else { mynode.Polish = mynode.NodeValue; } break; default: break; } if (mynode.NodeSyntaxType.ToString().StartsWith("para_")) { if (mynode.Children != null && mynode.Children.Count > 0) { mynode.Polish = mynode.Children[0].Polish; } } return mynode.Polish; }
/// <summary> /// 通用产生式处理函数 /// </summary> /// <param name="myNode">产生式节点</param> /// <param name="myType">候选式类型</param> /// <param name="mySyntax">节点语法类型</param> /// <param name="myToken">命中单词</param> /// <returns>下一个展开节点的指针</returns> private SyntaxTreeNode Derivate(SyntaxTreeNode myNode, CFunctionType myType, SyntaxType mySyntax, Token myToken) { // 更新节点信息 if (myNode != null) { myNode.NodeType = myType; myNode.NodeValue = myToken.OriginalCodeStr; myNode.NodeSyntaxType = mySyntax; myNode.NodeName = mySyntax.ToString(); myNode.Line = myToken.Line; myNode.Column = myToken.Column; if (myToken.IsVar) { myNode.NodeVarType = myToken.IsGlobal ? VarScopeType.GLOBAL : VarScopeType.LOCAL; } } // 取候选向量 List<SyntaxType> iSvec = this.derivatorTypeDict[Convert.ToInt32(myType)]; // 左边出栈 this.parseStack.Pop(); // 如果她是一个非终结符 if (myType < CFunctionType.DERI_UMI_BOUNDARY) { // 自右向左压匹配栈 for (int i = iSvec.Count - 1; i >= 0; i--) { this.parseStack.Push(iSvec[i]); } // 自左向右构造子节点 bool flag = false; SyntaxTreeNode successor = null; myNode.Children = new List<SyntaxTreeNode>(); for (int i = 0; i < iSvec.Count; i++) { SyntaxTreeNode newNode = new SyntaxTreeNode(); newNode.Parent = myNode; myNode.Children.Add(newNode); if (flag == false) { successor = newNode; flag = true; } } // 返回第一个产生式 return successor; } // 如果她是一个终结符 else { // 递增token指针 if (myType != CFunctionType.umi_epsilon) { this.nextTokenPointer++; } // 返回她的后继 return this.RecursiveDescent(myNode); } }