// 返回值: (NonTerminal, int) - Item1: 分析得到的语法树,如果是 null,代表分析失败;Item2: 下一个要扫描的 token protected override FuncInstructionBase StepMove(int pc, object lastReturned) { switch (pc) { case 0: { if (_startIdx >= _tokens.Count) { return(Return(((NonTerminalTree)null, _tokens.Count))); } // 一开始一定是非终结符 _ruleList = _bnfDefination.GetRulesForNonTerminal(_currentNonTerminal); _ruleIdx = 0; return(Continue()); } case 1: { if (_ruleIdx >= _ruleList.Count) { // 没有找到合适的rule return(Return(((NonTerminalTree)null, _startIdx))); } _childs = new ISyntacticAnalysisTree[_ruleList[_ruleIdx].Length]; _currentTokenIdx = _startIdx; _ruleItemIdx = 0; return(Continue()); } case 2: { if (_ruleItemIdx >= _ruleList[_ruleIdx].Length) { // child 全部填满,可以返回了 return(GoTo(100)); } // 是否到达末尾 if (_currentTokenIdx == _tokens.Count) { if (_ruleList[_ruleIdx][_ruleItemIdx] == TerminalConsts.EndOfFile) { // 在规则中应该是末尾 return(GoTo(100)); } else { // TODO: 这里有可能产生式是 ɛ,这样的话即使当前位置是末尾也可以满足要求 ++_ruleIdx; return(GoTo(1)); } } if (_ruleList[_ruleIdx][_ruleItemIdx] == TerminalConsts.EndOfFile) { // 在规则中应当到达末尾,但是目前没有到达末尾 ++_ruleIdx; return(GoTo(1)); } else if (_bnfDefination.IsTerminal(_ruleList[_ruleIdx][_ruleItemIdx])) { // 根据规则,当前应该是终结符 var currentToken = _tokens[_currentTokenIdx]; if (currentToken.TokenType == _ruleList[_ruleIdx][_ruleItemIdx]) { _childs[_ruleItemIdx] = new TerminalTree(currentToken); ++_currentTokenIdx; ++_ruleItemIdx; return(GoTo(2)); } else { ++_ruleIdx; return(GoTo(1)); } } else { return(Continue()); } } case 3: { // 当前的 ruleItem 是非终结符 return(CallStackFunc(new ParserFunc(_currentTokenIdx, _ruleList[_ruleIdx][_ruleItemIdx], _tokens, _bnfDefination, _backtracings))); } case 4: { var(tree, nextIdx) = ((NonTerminalTree, int))lastReturned; if (tree == null) { ++_ruleIdx; return(GoTo(1)); } else { _childs[_ruleItemIdx] = tree; _currentTokenIdx = nextIdx; ++_ruleItemIdx; return(GoTo(2)); } } case 100: { return(CallWithCurrentContinuation(cont => { _backtracings.Push(cont); return false; })); } case 101: { var shouldSkip = (bool)lastReturned; if (shouldSkip) { ++_ruleIdx; return(GoTo(1)); } else { return(Return(( new NonTerminalTree(_currentNonTerminal, _childs, _ruleList[_ruleIdx]), _currentTokenIdx ))); } } default: { return(null); } } }