Example #1
0
            // 返回值: (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);
                }
                }
            }