Пример #1
0
        public Token GetToken()
        {
            State = LexicAnalyserState.Initial;
            Value = HasNext ? Character.ToString() : "";
            Token token = null;

            while (HasNext && token == null)
            {
                switch (State)
                {
                case LexicAnalyserState.Initial:
                    HandleInitial();
                    break;

                case LexicAnalyserState.NonTerminal:
                    token = new NonTerminalToken(Value);
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Space:
                    token = new SpaceToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Terminal:
                    token = new TerminalToken(Value);
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Empty:
                    token = new EmptyToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.NewLine:
                    token = new NewLineToken(Value);
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Identifier:
                    token = new IdentifierToken(Value);
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Number:
                    token = new NumberToken(Value);
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Var:
                    token = new VarToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Write:
                    token = new WriteToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Read:
                    token = new ReadToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.If:
                    token = new IfToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.End:
                    token = new EndToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Then:
                    token = new ThenToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Begin:
                    token = new BeginToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.While:
                    token = new WhileToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Do:
                    token = new DoToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.SemiColon:
                    token = new SemiColonToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.OpenParentheses:
                    token = new OpenParenthesesToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.CloseParentheses:
                    token = new CloseParenthesesToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Plus:
                    token = new PlusToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Sub:
                    token = new SubToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Great:
                    token = new GreatToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Less:
                    token = new LessToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Equal:
                    token = new EqualToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Repeat:
                    token = new RepeatToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Until:
                    token = new UntilToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.Attribution:
                    token = new AttributionToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.NotEqual:
                    token = new NotEqualToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.GreatOrEqual:
                    token = new GreatOrEqualToken();
                    CurrentIndex++;
                    break;

                case LexicAnalyserState.LessOrEqual:
                    token = new LessOrEqualToken();
                    CurrentIndex++;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            return(token);
        }
Пример #2
0
        public INonterminalToken Parse()
        {
            ITerminalToken?token = Lexer.Next(stack.StateId);

            while (token != null)
            {
                var action = Decode(token.Symbol.Id);

                switch (action.Action)
                {
                case ParseAction.Error:
                    HandleError(token);
                    token = null;
                    break;

                case ParseAction.Shift:
                    Shift(action.Number);
                    break;

                case ParseAction.Reduce:
                    Reduce(action.Number);
                    break;

                case ParseAction.Accept:
                    Debug.Assert(Lexer.IsEnd());
                    token = null;
                    break;
                }
            }

            return((INonterminalToken)stack.Pop().Token);

            void HandleError(ITerminalToken token)
            {
                var msg = Errors.GetExpectedMessage(token.Location, Errors.GetSymbols(stack.StateId).ToArray());

                throw new ParserException(msg);
            }

            void Shift(int stateId)
            {
                Debug.Assert(token != null);
                stack.Push(new StackItem(token, stateId));

                token = Lexer.Next(stack.StateId);
            }

            void Reduce(int productionId)
            {
                var production  = Context.Productions[productionId];
                var nonterminal = production.Nonterminal;

                IToken token;

                var popped = stack.Pop(production.Length);

                var rhs = production.DropFilter(popped).ToArray();

                switch (nonterminal.Repeat)
                {
                case RepeatKind.Star:
                    switch (rhs.Length)
                    {
                    case 0:
                        /* empty part */
                    {
                        token = new RepeatToken(RepeatSymbol.Star);
                        break;
                    }

                    case 1:
                        /* core part */
                    {
                        var item = rhs[0];
                        token = new RepeatToken(RepeatSymbol.Star, item);
                        break;
                    }

                    case 2:
                        /* recursive part */
                    {
                        var item   = rhs[1];
                        var repeat = (RepeatToken)rhs[0];
                        repeat.Add(item);
                        token = repeat;
                        break;
                    }

                    default:
                        throw new InternalException();
                    }
                    break;

                case RepeatKind.Plus:
                    switch (rhs.Length)
                    {
                    case 1:
                        /* core part */
                    {
                        var item = rhs[0];
                        token = new RepeatToken(RepeatSymbol.Plus, item);
                        break;
                    }

                    case 2:
                        /* recursive part */
                    {
                        var item   = rhs[1];
                        var repeat = (RepeatToken)rhs[0];
                        repeat.Add(item);
                        token = repeat;
                        break;
                    }

                    default:
                        throw new InternalException();
                    }
                    break;

                case RepeatKind.Optional:
                    switch (rhs.Length)
                    {
                    case 0:
                        /* empty part */
                    {
                        token = new RepeatToken(RepeatSymbol.Option);
                        break;
                    }

                    default:
                        /* core part */
                    {
                        var item = rhs[0];
                        token = new RepeatToken(RepeatSymbol.Option, rhs);
                        break;
                    }
                    }
                    break;

                case RepeatKind.None:
                    if (production.IsPromote)
                    {
                        if (rhs.Length != 1)
                        {
                            throw new InternalException();
                        }
                        token = rhs[0];
                    }
                    else
                    {
                        token = new NonterminalToken(nonterminal, rhs);
                    }
                    break;

                default:
                    throw new InternalException();
                }

                var action = Decode(nonterminal.Id);

                if (action.Action != ParseAction.Shift)
                {
                    throw new ParserException();
                }

                stack.Push(new StackItem(token, action.Number));
            }
        }