示例#1
0
        /// <summary>
        /// Productions MUST BE:
        /// - left factored
        /// - without left recursions
        /// </summary>
        /// <param name="productions">Processed productions</param>
        public void FillByProcessedProductions(IEnumerable <Production> productions, Nonterminal axiom)
        {
            // A -> alpha
            foreach (var production in productions)
            {
                var useProductionAction = AutomateAction.FromProduction(production);

                // FIRST(alpha)
                var first = Helper.First(productions, production.RightPart);
                foreach (var terminal in first)
                {
                    this[production.LeftPart, terminal] = useProductionAction;
                }

                if (first.Contains(GeneralizedTerminal.Epsilon))
                {
                    // FOLLOW(A)
                    var follow = Helper.Follow(productions, production.LeftPart, axiom);
                    foreach (var terminal in follow)
                    {
                        this[production.LeftPart, terminal] = useProductionAction;
                    }
                }
            }
        }
示例#2
0
        private StepResults Step(out Error error)
        {
            if (_stack.Count == 0)
            #region When stack is empty
            {
                if (_tokenStream.Current.Type == TokenType.EndOfText)
                #region ACCEPT
                {
                    error = null;
                    return(StepResults.AcceptInput);
                }
                #endregion
                else
                #region REJECT: EOF EXPECTED
                {
                    error = new Error(_tokenStream.Current, ErrorKind.Syntax, "End of input expected");
                    return(StepResults.RejectInput);
                }
                #endregion
            }
            #endregion
            else
            #region When stack is not empty
            {
                Symbol           magazineSymbol = _stack.Peek();
                ConcreteTerminal inputTerminal  = new ConcreteTerminal(_tokenStream.Current);

                if (magazineSymbol is Nonterminal)
                {
                    var            magazineNonterminal = (Nonterminal)magazineSymbol;
                    AutomateAction action = _controlTable[magazineNonterminal, inputTerminal];

                    if (action == null && CanBeEpsilon(magazineNonterminal))
                    {
                        _stack.Pop();
                        error = null;
                        return(StepResults.InProgress);
                    }

                    if (action == null) // common error handling
                    {
                        error = new Error(_tokenStream.Current, ErrorKind.Syntax, GenerateErrorMessage(magazineNonterminal, inputTerminal));
                        return(StepResults.RejectInput);
                    }

                    switch (action.Kind)
                    {
                    case AutomateActionKind.UseProduction:
                        _stack.Pop();     // delete disclosing nonterminal
                        Production production = action.GetProduction();
                        if (!production.RightPart.IsEpsilonChain)
                        {
                            production.RightPart.ReverseForEach(s => _stack.Push(s));     // and push right parts of productions
                        }
                        ConstructSyntaxTree(production);
                        break;

                    case AutomateActionKind.HandleError:     // custom error handling
                        break;

                    default: break;
                    }

                    error = null;
                    return(StepResults.InProgress);
                }
                else // magazineSymbol is Terminal
                {
                    var magazineTerminal = (Terminal)magazineSymbol;

                    if (magazineTerminal.IsAppropriateTerminal(inputTerminal))
                    {
                        _stack.Pop();
                        _tokenStream.MoveNext();

                        SubstituteTreeTerminalByActualValue(magazineTerminal, inputTerminal);

                        error = null;
                        return(StepResults.InProgress);
                    }
                    else
                    {
                        error = new Error(_tokenStream.Current, ErrorKind.Syntax, GenerateErrorMessage(magazineTerminal, inputTerminal));
                        return(StepResults.RejectInput);
                    }
                }
            }
            #endregion
        }