/// <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> /// 将所有非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> /// 其余情况的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetUnknown(Token res) { // 生成错误的token res.Type = TokenType.unknown; res.OriginalCodeStr = Convert.ToString(this.sourceCode[this.nextCharPointer]); res.Tag = "错误:不能匹配为token的字符:" + res.OriginalCodeStr; // 跳游程 this.Jump(1); return true; }
/// <summary> /// 处理最长匹配 /// </summary> /// <param name="res">结果实例</param> /// <param name="maxLen">最长匹配长度</param> /// <param name="reservedList">候选关键字</param> /// <returns>是否成功命中</returns> private bool ReservedRouter(Token res, int maxLen, params string[] reservedList) { if (this.nextCharPointer + maxLen <= this.sourceCode.Length) { // 寻找匹配项 bool okFlag = false; string str = this.sourceCode.Substring(this.nextCharPointer, maxLen).ToLower(); foreach (string matchStr in reservedList) { string pureMatch = matchStr.Substring(1); if (pureMatch == str && this.GetCharType(this.sourceCode[this.nextCharPointer + maxLen]) != CharacterType.Letter) { // 参数 if (matchStr[0] == '*') { res.Type = (TokenType)Enum.Parse(typeof(TokenType), String.Format("Token_p_{0}", pureMatch)); } // 动作 else { res.Type = (TokenType)Enum.Parse(typeof(TokenType), String.Format("Token_o_{0}", pureMatch)); } okFlag = true; break; } } // 如果命中了符号就返回 if (okFlag) { res.OriginalCodeStr = str; this.Jump(maxLen); return true; } } return false; }
/// <summary> /// 单字符的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetSingleCharaCalculator(Token res) { int glen = this.sourceCode.Length; if (this.nextCharPointer + 1 <= glen) { string str = this.sourceCode.Substring(this.nextCharPointer, 1); res.OriginalCodeStr = str; switch (str) { case "+": res.Type = TokenType.Token_Plus; break; case "-": res.Type = TokenType.Token_Minus; break; case "*": res.Type = TokenType.Token_Multiply; break; case "/": res.Type = TokenType.Token_Divide; break; case "!": res.Type = TokenType.Token_Not; break; case "(": res.Type = TokenType.Token_LeftParentheses; break; case ")": res.Type = TokenType.Token_RightParentheses; break; case "@": res.Type = TokenType.Token_At; break; case "[": res.Type = TokenType.Token_LeftBracket; break; case "]": res.Type = TokenType.Token_RightBracket; break; case "#": res.Type = TokenType.Token_Sharp; break; default: break; } // 递增字符指针 this.Jump(1); return true; } return false; }
/// <summary> /// 空白符号的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetSpace(Token res) { // 获取字符,看是否要换行 char c = this.sourceCode[this.nextCharPointer]; if (c == LineTerminator) { this.currentLine++; this.currentColumn = 0; } // 为空格跳游程 if (c == ' ') { this.Jump(1); } else { this.nextCharPointer++; } // 空token,永久为false return false; }
/// <summary> /// 关键字的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetReservedCalculator(Token res) { bool okFlag = false; okFlag = this.ReservedRouter(res, 13, "`deletepicture"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 12, "`deletecstand", "`deletebutton"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 11, "`msglayeropt", "`endfunction"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 10, "`titlepoint"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 9, "`stopvocal"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 8, "`waituser", "`msglayer", "`shutdown", "`function", "*filename"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 7, "`picture", "`waitani", "`stopbgm", "`stopbgs", "*opacity"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 6, "`button", "`branch", "`switch", "`freeze", "`cstand", "`return", "`endfor", "*target", "*normal", "*xscale", "*yscale"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 5, "`label", "`trans", "`endif", "`vocal", "`break", "`title", "*state"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 4, "`move", "`jump", "`wait", "`else", "`menu", "`call", "`draw", "`save", "`load", "*name", "*face", "*time", "*link", "*dash", "*cond", "*type", "*over", "*sign"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 3, "`bgm", "`bgs", "`for", "`var", "*vid", "*loc", "*vol", "*acc"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 2, "`se", "`bg", "`if", "*id", "*ro", "*on"); if (okFlag) { return true; } okFlag = this.ReservedRouter(res, 1, "`a", "*x", "*y", "*z"); if (okFlag) { return true; } // 在标识符中没有命中,转到文本内容自动机路径 return this.GetSceneCluster(res); }
/// <summary> /// <para>DFA自动机</para> /// <para>处理当前代码指针所在的单词,并移动指针</para> /// <para>如果遇到未知的字符,将抛出错误</para> /// </summary> /// <param name="nextToken">当前代码指针所指单词实例</param> /// <returns>是否已经完成了一个句子的分析</returns> private bool DFA(out Token nextToken) { // 定义结果实例并初始化 Token res = new Token(); res.Line = this.currentLine; res.Column = this.currentColumn; res.IndexOfCode = this.nextCharPointer; int alen = this.sourceCode.Length; // 获取下一个字符来判断自动机路径 bool successFlag = false; // 如果finFlag还没有成立,直接进入剧本自动机路径 if (finFlag == false) { successFlag = this.GetSceneCluster(res); } else { CharacterType cara = this.GetCharType(this.sourceCode[this.nextCharPointer]); switch (cara) { // 注释 case CharacterType.Pound: this.GetNotation(); break; // 单字符token case CharacterType.Plus: case CharacterType.Minus: case CharacterType.Multiply: case CharacterType.Divide: case CharacterType.Not: case CharacterType.At: case CharacterType.LeftParentheses: case CharacterType.RightParentheses: successFlag = this.GetSingleCharaCalculator(res); break; // 可能双字符token case CharacterType.Equality: case CharacterType.LessThan: case CharacterType.GreaterThan: case CharacterType.And: case CharacterType.Or: successFlag = this.GetDoubleCharaCalculator(res); break; // 关键字 case CharacterType.Letter: successFlag = this.GetReservedCalculator(res); break; // 标识符 case CharacterType.Dollar: successFlag = this.GetIdentifierCalculator(res); break; // 字符串 case CharacterType.Quotation: case CharacterType.DoubleQuotation: successFlag = this.GetCluster(res); break; // 剧本对白 case CharacterType.LeftBracket: successFlag = this.GetSceneCluster(res); break; // 剧本对白结束: case CharacterType.RightBracket: successFlag = this.EndSceneCluster(res); break; // 常数 case CharacterType.Number: successFlag = this.GetConstant(res); break; // 中文(finFlag不成立) case CharacterType.Chinese: successFlag = this.GetSceneCluster(res); break; // 空白 case CharacterType.Space: successFlag = this.GetSpace(res); break; // 谜 default: successFlag = this.GetUnknown(res); throw new InterpreterException() { Message = "有未识别的字符输入:" + res.OriginalCodeStr, HitLine = res.Line, HitColumn = res.Column, HitPhase = InterpreterException.InterpreterPhase.Lexer, SceneFileName = this.dealingFile }; } } // 如果成功获得了token,就返回给Lexer if (successFlag) { res.Length = this.nextCharPointer - res.IndexOfCode; nextToken = res; return blockFlag == false; } // 否则返回空 nextToken = null; return false; }
/// <summary> /// 可能双字符的自动机路径(最长匹配) /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetDoubleCharaCalculator(Token res) { int glen = this.sourceCode.Length; // 双字符的情况 if (this.nextCharPointer + 2 <= glen) { bool okFlag = false; string str = this.sourceCode.Substring(this.nextCharPointer, 2); switch (str) { case "==": res.Type = TokenType.Token_Equality_Equality; okFlag = true; break; case ">=": res.Type = TokenType.Token_GreaterThan_Equality; okFlag = true; break; case "<=": res.Type = TokenType.Token_LessThan_Equality; okFlag = true; break; case "<>": res.Type = TokenType.Token_LessThan_GreaterThan; okFlag = true; break; case "&&": res.Type = TokenType.Token_And_And; okFlag = true; break; case "||": res.Type = TokenType.Token_Or_Or; okFlag = true; break; default: break; } // 如果命中了符号就返回 if (okFlag) { res.OriginalCodeStr = str; this.Jump(2); return true; } } bool idFlag = false; // 双字符匹配失败,进入单字符自动机路径 if (this.nextCharPointer + 1 <= glen) { bool okFlag = false; string str = this.sourceCode.Substring(this.nextCharPointer, 1); switch (str) { case ">": res.Type = TokenType.Token_GreaterThan; okFlag = true; break; case "<": res.Type = TokenType.Token_LessThan; okFlag = true; break; case "=": res.Type = TokenType.Token_Equality; okFlag = true; break; // 遇到&符号就跳转到变量处理路径上 case "&": idFlag = this.GetIdentifierCalculator(res); break; default: break; } // 如果命中了符号就返回 if (okFlag) { res.OriginalCodeStr = str; this.Jump(1); return true; } } return (idFlag || false); }
/// <summary> /// 标识符的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetIdentifierCalculator(Token res) { // 跳过变量引用符号$或& res.IsGlobal = this.GetCharType(this.sourceCode[this.nextCharPointer]) == CharacterType.And; this.Jump(1); // 构造标识符 StringBuilder sb = new StringBuilder(); while (this.nextCharPointer < this.sourceCode.Length) { CharacterType cara = this.GetCharType(this.sourceCode[this.nextCharPointer]); if (cara == CharacterType.Letter || cara == CharacterType.Number || cara == CharacterType.UnderLine || cara == CharacterType.LeftBrace || cara == CharacterType.RightBrace) { sb.Append(this.sourceCode[this.nextCharPointer]); this.Jump(1); } else { break; } } // 修改token的标签 res.IsVar = true; res.Type = TokenType.identifier; res.OriginalCodeStr = sb.ToString(); return true; }
/// <summary> /// 常数数字的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetConstant(Token res) { StringBuilder sb = new StringBuilder(); bool successFlag = false; // 扫描数字序列 while (this.nextCharPointer < this.sourceCode.Length) { char c; c = this.sourceCode[this.nextCharPointer]; if (this.GetCharType(c) == CharacterType.Number) { sb.Append(c); this.Jump(1); successFlag = true; } else { break; } } // 成功得到数字token if (successFlag) { res.Type = TokenType.number; res.OriginalCodeStr = sb.ToString(); res.Tag = Convert.ToInt32(sb.ToString()); return true; } return false; }
/// <summary> /// 字符串的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetCluster(Token res) { // 取得左引号的类型并跳过她 CharacterType latticeType = this.GetCharType(this.sourceCode[this.nextCharPointer]); this.Jump(1); // 构造字符串 bool lattice = false; StringBuilder sb = new StringBuilder(); while (this.nextCharPointer < this.sourceCode.Length) { CharacterType cara = this.GetCharType(this.sourceCode[this.nextCharPointer]); // 在双引号之前的输入都接受,并且这个双引号不能是转义的 if (this.GetCharType(this.sourceCode[this.nextCharPointer]) == latticeType) { // 跳游程并标志封闭性成立 this.Jump(1); lattice = true; break; } else { // 处理转义字符并压入字符串构造器,游程在escaping里跳动 sb.Append(this.Escaping(this.sourceCode[this.nextCharPointer])); } } // 如果成功封闭 //res.aType = TokenType.cluster; res.Type = TokenType.identifier; res.Tag = (string)sb.ToString(); res.OriginalCodeStr = sb.ToString(); res.ErrorBit = lattice == false; return true; }
/// <summary> /// 剧本对白段落终止符的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool EndSceneCluster(Token res) { // 跳过游程 this.Jump(1); // 修改token信息 res.Type = TokenType.sceneterminator; res.OriginalCodeStr = "]"; return true; }
/// <summary> /// 复位匹配器:命令推导向推导过程转化时内部使用 /// </summary> private void DashReset(SyntaxType startNodeType) { // 变数初期化 this.nextTokenPointer = 0; this.parseStack.Clear(); this.commandDerivatorQueue.Clear(); // 放置初始节点 this.parseStack.Push(SyntaxType.tail_startEndLeave); this.parseStack.Push(startNodeType); // 在流的末尾,放置结束标记 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.Last().Column + 1 : -1; this.istream.Add(ccToken); }
/// <summary> /// 剧本对白的自动机路径 /// </summary> /// <param name="res">结果实例</param> /// <returns>是否命中</returns> private bool GetSceneCluster(Token res) { // 跳过左方括弧 if (this.GetCharType(this.sourceCode[this.nextCharPointer]) == CharacterType.LeftBracket) { this.Jump(1); this.finFlag = false; } // 构造字符串 StringBuilder sb = new StringBuilder(); bool entityFlag = false; while (this.nextCharPointer < this.sourceCode.Length) { CharacterType cara = this.GetCharType(this.sourceCode[this.nextCharPointer]); // 在右方括弧之前的输入都接受,并且这个符号不能是转义的 if (this.GetCharType(this.sourceCode[this.nextCharPointer]) == CharacterType.RightBracket) { // 不跳游程,等待DFA进入段落终止符路径,并标志封闭性成立 finFlag = true; break; } // 如果遇到注释就直接截断,进入注释自动机路径,但封闭性不改变 else if (this.GetCharType(this.sourceCode[this.nextCharPointer]) == CharacterType.Pound) { this.GetNotation(); break; } // 如果是换行符也要压入字符串,但它不可以构成一个实体 else if (this.sourceCode[this.nextCharPointer] == '\r' || this.sourceCode[this.nextCharPointer] == '\n') { // 压入,跳游程,不改变实体性质 sb.Append(this.sourceCode[this.nextCharPointer++]); } else { // 处理转义字符并压入字符串构造器,游程在escaping里跳动 sb.Append(this.Escaping(this.sourceCode[this.nextCharPointer])); entityFlag = true; } } // 如果成功封闭 res.Type = TokenType.scenecluster; res.Tag = res.OriginalCodeStr = sb.ToString(); return entityFlag; }
/// <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); } }
/// <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); }