Exemple #1
0
        public TokenParserResult ReadToken(TextRange RangeInLine)
        {
            var s     = Text.GetTextInLine(RangeInLine);
            int Index = 0;

            Func <Boolean>     EndOfLine       = () => Index >= s.Length;
            Func <int, String> Peek            = n => s.Substring(Index, Math.Min(n, s.Length - Index));
            Action             Proceed         = () => Index += 1;
            Action <int>       ProceedMultiple = n => Index += n;

            Func <Optional <TextRange> > MakeRemainingChars = () => new TextRange {
                Start = Text.Calc(RangeInLine.Start, Index), End = RangeInLine.End
            };
            var NullRemainingChars = Optional <TextRange> .Empty;
            var NullToken          = Optional <SyntaxRule> .Empty;
            Func <int, int, TextRange> MakeTokenRange = (TokenStart, TokenEnd) => new TextRange {
                Start = Text.Calc(RangeInLine.Start, TokenStart), End = Text.Calc(RangeInLine.Start, TokenEnd)
            };
            Func <int, FileTextRange> MakeNextErrorTokenRange = n => new FileTextRange {
                Text = Text, Range = MakeTokenRange(Index, n)
            };

            var State = 0;

            var StartIndex = 0;
            Func <String, InvalidTokenException> MakeCurrentErrorTokenException = Message => new InvalidTokenException(Message, new FileTextRange {
                Text = Text, Range = MakeTokenRange(StartIndex, Index)
            }, Text.GetTextInLine(MakeTokenRange(StartIndex, Index)));
            Func <String, InvalidTokenException> MakeNextCharErrorTokenException = Message => new InvalidTokenException(Message, MakeNextErrorTokenRange(1), Peek(1));
            Action          MarkStart = () => StartIndex = Index;
            var             Output    = new List <Char>();
            Action <String> Write     = cs => Output.AddRange(cs);

            Func <Optional <SyntaxRule> > MakeSymbol = () =>
            {
                var Range  = MakeTokenRange(StartIndex, Index);
                var Symbol = new String(Output.ToArray());
                if (rBooleanLiteral.Match(Symbol).Success)
                {
                    var t  = TokenLiteral.CreateBooleanValue(!Symbol.Equals("false", StringComparison.Ordinal));
                    var st = SyntaxRule.CreateLiteral(t);
                    Positions.Add(t, Range);
                    Positions.Add(st, Range);
                    return(st);
                }
                else if (rIntLiteral.Match(Symbol).Success)
                {
                    var t  = TokenLiteral.CreateIntValue(NumericStrings.InvariantParseInt32(Symbol));
                    var st = SyntaxRule.CreateLiteral(t);
                    Positions.Add(t, Range);
                    Positions.Add(st, Range);
                    return(st);
                }
                else if (rRealLiteral.Match(Symbol).Success)
                {
                    var t  = TokenLiteral.CreateRealValue(NumericStrings.InvariantParseFloat64(Symbol));
                    var st = SyntaxRule.CreateLiteral(t);
                    Positions.Add(t, Range);
                    Positions.Add(st, Range);
                    return(st);
                }
                else if (rIdentifier.Match(Symbol).Success)
                {
                    var t = new TokenIdentifier {
                        Name = Symbol
                    };
                    var st = SyntaxRule.CreateIdentifier(t);
                    Positions.Add(t, Range);
                    Positions.Add(st, Range);
                    return(st);
                }
                else
                {
                    throw MakeCurrentErrorTokenException("InvalidToken");
                }
            };

            Func <Optional <SyntaxRule> > MakeBinaryOperator = () =>
            {
                var Range = MakeTokenRange(StartIndex, Index);
                var t     = new TokenBinaryOperator {
                    Name = new String(Output.ToArray())
                };
                var st = SyntaxRule.CreateBinaryOperator(t);
                Positions.Add(t, Range);
                Positions.Add(st, Range);
                return(st);
            };

            Func <Optional <SyntaxRule> > MakeUnaryOperator = () =>
            {
                var Range = MakeTokenRange(StartIndex, Index);
                var t     = new TokenUnaryOperator {
                    Name = new String(Output.ToArray())
                };
                var st = SyntaxRule.CreateUnaryOperator(t);
                Positions.Add(t, Range);
                Positions.Add(st, Range);
                return(st);
            };

            Func <Optional <SyntaxRule> > MakeLeftParen = () =>
            {
                var Range = MakeTokenRange(StartIndex, Index);
                var t     = new TokenLeftParen {
                };
                var st    = SyntaxRule.CreateLeftParen(t);
                Positions.Add(t, Range);
                Positions.Add(st, Range);
                return(st);
            };

            Func <Optional <SyntaxRule> > MakeRightParen = () =>
            {
                var Range = MakeTokenRange(StartIndex, Index);
                var t     = new TokenRightParen {
                };
                var st    = SyntaxRule.CreateRightParen(t);
                Positions.Add(t, Range);
                Positions.Add(st, Range);
                return(st);
            };

            Func <Optional <SyntaxRule> > MakeComma = () =>
            {
                var Range = MakeTokenRange(StartIndex, Index);
                var t     = new TokenComma {
                };
                var st    = SyntaxRule.CreateComma(t);
                Positions.Add(t, Range);
                Positions.Add(st, Range);
                return(st);
            };

            while (true)
            {
                if (State == 0)
                {
                    if (EndOfLine())
                    {
                        return(new TokenParserResult {
                            Token = NullToken, RemainingChars = NullRemainingChars
                        });
                    }
                    var c2 = Peek(2);
                    if (c2 == "&&" || c2 == "||" || c2 == "<=" || c2 == ">=" || c2 == "==" || c2 == "!=")
                    {
                        MarkStart();
                        Write(c2);
                        ProceedMultiple(2);
                        return(new TokenParserResult {
                            Token = MakeBinaryOperator(), RemainingChars = MakeRemainingChars()
                        });
                    }
                    var c = Peek(1);
                    if (c == " ")
                    {
                        Proceed();
                        continue;
                    }
                    if (c == "+" || c == "-" || c == "*" || c == "/" || c == "<" || c == ">")
                    {
                        MarkStart();
                        Write(c);
                        Proceed();
                        return(new TokenParserResult {
                            Token = MakeBinaryOperator(), RemainingChars = MakeRemainingChars()
                        });
                    }
                    if (c == "!")
                    {
                        MarkStart();
                        Write(c);
                        Proceed();
                        return(new TokenParserResult {
                            Token = MakeUnaryOperator(), RemainingChars = MakeRemainingChars()
                        });
                    }
                    if (c == "(")
                    {
                        MarkStart();
                        Proceed();
                        return(new TokenParserResult {
                            Token = MakeLeftParen(), RemainingChars = MakeRemainingChars()
                        });
                    }
                    if (c == ")")
                    {
                        MarkStart();
                        Proceed();
                        return(new TokenParserResult {
                            Token = MakeRightParen(), RemainingChars = MakeRemainingChars()
                        });
                    }
                    if (c == ",")
                    {
                        MarkStart();
                        Proceed();
                        return(new TokenParserResult {
                            Token = MakeComma(), RemainingChars = MakeRemainingChars()
                        });
                    }
                    if (rSymbol.Match(c).Success)
                    {
                        MarkStart();
                        Write(c);
                        Proceed();
                        State = 1;
                        continue;
                    }
                    throw MakeNextCharErrorTokenException("InvalidChar");
                }
                else if (State == 1)
                {
                    var c = Peek(1);
                    if (rSymbol.Match(c).Success)
                    {
                        Write(c);
                        Proceed();
                        continue;
                    }
                    return(new TokenParserResult {
                        Token = MakeSymbol(), RemainingChars = MakeRemainingChars()
                    });
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }
        }
Exemple #2
0
        public SyntaxParserResult Parse(TextRange RangeInLine)
        {
            var TokenQueue = new LinkedList <SyntaxRule>();

            var r = RangeInLine;

            while (true)
            {
                var t = tp.ReadToken(r);
                if (t.Token.OnSome)
                {
                    TokenQueue.AddLast(t.Token.Some);
                }
                if (!t.RemainingChars.OnSome)
                {
                    break;
                }
                r = t.RemainingChars.Some;
            }

            var StateStack          = new Stack <int>();
            var RuleStack           = new Stack <SyntaxRule>();
            var BinaryOperatorStack = new Stack <TokenBinaryOperator>();

            var State = 0; //初始状态为0

            StateStack.Push(State);
            Optional <SyntaxRule> Token = Optional <SyntaxRule> .Empty;

            Action <SyntaxRule, TextRange> Mark = (st, Range) =>
            {
                if (st.OnExpr)
                {
                    Positions.Add(st.Expr, Range);
                }
                else if (st.OnParameterList)
                {
                    Positions.Add(st.ParameterList, Range);
                }
                else if (st.OnNonnullParameterList)
                {
                    Positions.Add(st.NonnullParameterList, Range);
                }
                Positions.Add(st, Range);
            };

            Func <Boolean> EndOfFile = () => TokenQueue.Count == 0;
            Action <int>   Shift     = NewState =>
            {
                StateStack.Push(NewState);
                RuleStack.Push(TokenQueue.First.Value);
                TokenQueue.RemoveFirst();
            };
            Action <Func <SyntaxRule> > Reduce0 = f =>
            {
                var       st = f();
                TextRange Range;
                if (EndOfFile())
                {
                    Range = new TextRange {
                        Start = RangeInLine.End, End = RangeInLine.End
                    };
                }
                else
                {
                    var NextTokenRange = Positions[Token.Some];
                    Range = new TextRange {
                        Start = NextTokenRange.Start, End = NextTokenRange.Start
                    };
                }
                Mark(st, Range);
                TokenQueue.AddFirst(st);
            };
            Action <Func <SyntaxRule, SyntaxRule> > Reduce1 = f =>
            {
                var Rule0 = RuleStack.Pop();
                StateStack.Pop();
                var st         = f(Rule0);
                var Rule0Range = Positions[Rule0];
                var Range      = Rule0Range;
                Mark(st, Range);
                TokenQueue.AddFirst(st);
            };
            Action <Func <SyntaxRule, SyntaxRule, SyntaxRule> > Reduce2 = f =>
            {
                var Rule1 = RuleStack.Pop();
                var Rule0 = RuleStack.Pop();
                StateStack.Pop();
                StateStack.Pop();
                var st         = f(Rule0, Rule1);
                var Rule0Range = Positions[Rule0];
                var Rule1Range = Positions[Rule1];
                var Range      = new TextRange {
                    Start = Rule0Range.Start, End = Rule1Range.End
                };
                Mark(st, Range);
                TokenQueue.AddFirst(st);
            };
            Action <Func <SyntaxRule, SyntaxRule, SyntaxRule, SyntaxRule> > Reduce3 = f =>
            {
                var Rule2 = RuleStack.Pop();
                var Rule1 = RuleStack.Pop();
                var Rule0 = RuleStack.Pop();
                StateStack.Pop();
                StateStack.Pop();
                StateStack.Pop();
                var st         = f(Rule0, Rule1, Rule2);
                var Rule0Range = Positions[Rule0];
                var Rule2Range = Positions[Rule2];
                var Range      = new TextRange {
                    Start = Rule0Range.Start, End = Rule2Range.End
                };
                Mark(st, Range);
                TokenQueue.AddFirst(st);
            };
            Action <Func <SyntaxRule, SyntaxRule, SyntaxRule, SyntaxRule, SyntaxRule> > Reduce4 = f =>
            {
                var Rule3 = RuleStack.Pop();
                var Rule2 = RuleStack.Pop();
                var Rule1 = RuleStack.Pop();
                var Rule0 = RuleStack.Pop();
                StateStack.Pop();
                StateStack.Pop();
                StateStack.Pop();
                StateStack.Pop();
                var st         = f(Rule0, Rule1, Rule2, Rule3);
                var Rule0Range = Positions[Rule0];
                var Rule3Range = Positions[Rule3];
                var Range      = new TextRange {
                    Start = Rule0Range.Start, End = Rule3Range.End
                };
                Mark(st, Range);
                TokenQueue.AddFirst(st);
            };
            Action <SyntaxRule> Replace = f =>
            {
                Mark(f, Positions[Token.Some]);
                Token = f;
                TokenQueue.First.Value = f;
            };

            Func <InvalidSyntaxException> MakeInvalidEndOfFile = () =>
            {
                var Range = new FileTextRange {
                    Text = Text, Range = new TextRange {
                        Start = RangeInLine.End, End = RangeInLine.End
                    }
                };
                return(new InvalidSyntaxException("InvalidEndOfFile", Range));
            };
            Func <InvalidSyntaxException> MakeInvalidSyntaxRule = () =>
            {
                var tr    = Positions[Token.Some];
                var Range = new FileTextRange {
                    Text = Text, Range = tr
                };
                var t = Text.GetTextInLine(tr);
                return(new InvalidSyntaxException(String.Format("'{0}' : InvalidSyntaxRuleAtToken", t), Range));
            };

            while (true)
            {
                State = StateStack.Peek();
                Token = EndOfFile() ? Optional <SyntaxRule> .Empty : TokenQueue.First.Value;
                if (State == 0)
                {
                    if (!Token.OnSome)
                    {
                        throw MakeInvalidEndOfFile();
                    }
                    var t = Token.Some;
                    if (t.OnLiteral)
                    {
                        Shift(1);
                    }
                    else if (t.OnIdentifier)
                    {
                        Shift(2);
                    }
                    else if (t.OnBinaryOperator)
                    {
                        if (t.BinaryOperator.Name == "+" || t.BinaryOperator.Name == "-")
                        {
                            Replace(SyntaxRule.CreateUnaryOperator(new TokenUnaryOperator {
                                Name = t.BinaryOperator.Name
                            }));
                        }
                        else
                        {
                            throw MakeInvalidSyntaxRule();
                        }
                    }
                    else if (t.OnUnaryOperator)
                    {
                        Shift(3);
                    }
                    else if (t.OnLeftParen)
                    {
                        Shift(4);
                    }
                    else if (t.OnRightParen)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnComma)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnExpr)
                    {
                        Shift(5);
                    }
                    else if (t.OnParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnNonnullParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }
                else if (State == 1)
                {
                    Reduce1(l => SyntaxRule.CreateExpr(SyntaxExpr.CreateLiteral(new ProductionLiteral {
                        Literal = l.Literal
                    })));
                }
                else if (State == 2)
                {
                    if (Token.OnSome && Token.Some.OnLeftParen)
                    {
                        Shift(6);
                    }
                    else
                    {
                        Reduce1(i => SyntaxRule.CreateExpr(SyntaxExpr.CreateVariable(new ProductionVariable {
                            Identifier = i.Identifier
                        })));
                    }
                }
                else if (State == 3)
                {
                    if (!Token.OnSome)
                    {
                        throw MakeInvalidEndOfFile();
                    }
                    var t = Token.Some;
                    if (t.OnLiteral)
                    {
                        Shift(1);
                    }
                    else if (t.OnIdentifier)
                    {
                        Shift(2);
                    }
                    else if (t.OnBinaryOperator)
                    {
                        if (t.BinaryOperator.Name == "+" || t.BinaryOperator.Name == "-")
                        {
                            Replace(SyntaxRule.CreateUnaryOperator(new TokenUnaryOperator {
                                Name = t.BinaryOperator.Name
                            }));
                        }
                        else
                        {
                            throw MakeInvalidSyntaxRule();
                        }
                    }
                    else if (t.OnUnaryOperator)
                    {
                        Shift(3);
                    }
                    else if (t.OnLeftParen)
                    {
                        Shift(4);
                    }
                    else if (t.OnRightParen)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnComma)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnExpr)
                    {
                        Shift(7);
                    }
                    else if (t.OnParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnNonnullParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }
                else if (State == 4)
                {
                    if (!Token.OnSome)
                    {
                        throw MakeInvalidEndOfFile();
                    }
                    var t = Token.Some;
                    if (t.OnLiteral)
                    {
                        Shift(1);
                    }
                    else if (t.OnIdentifier)
                    {
                        Shift(2);
                    }
                    else if (t.OnBinaryOperator)
                    {
                        if (t.BinaryOperator.Name == "+" || t.BinaryOperator.Name == "-")
                        {
                            Replace(SyntaxRule.CreateUnaryOperator(new TokenUnaryOperator {
                                Name = t.BinaryOperator.Name
                            }));
                        }
                        else
                        {
                            throw MakeInvalidSyntaxRule();
                        }
                    }
                    else if (t.OnUnaryOperator)
                    {
                        Shift(3);
                    }
                    else if (t.OnLeftParen)
                    {
                        Shift(4);
                    }
                    else if (t.OnRightParen)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnComma)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnExpr)
                    {
                        Shift(8);
                    }
                    else if (t.OnParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnNonnullParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }
                else if (State == 5)
                {
                    if (!Token.OnSome)
                    {
                        return(new SyntaxParserResult {
                            Syntax = RuleStack.Single().Expr
                        });
                    }
                    var t = Token.Some;
                    if (t.OnBinaryOperator)
                    {
                        BinaryOperatorStack.Push(t.BinaryOperator);
                        Shift(9);
                    }
                    else
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                }
                else if (State == 6)
                {
                    if (!Token.OnSome)
                    {
                        throw MakeInvalidEndOfFile();
                    }
                    var t = Token.Some;
                    if (t.OnLiteral)
                    {
                        Shift(1);
                    }
                    else if (t.OnIdentifier)
                    {
                        Shift(2);
                    }
                    else if (t.OnBinaryOperator)
                    {
                        if (t.BinaryOperator.Name == "+" || t.BinaryOperator.Name == "-")
                        {
                            Replace(SyntaxRule.CreateUnaryOperator(new TokenUnaryOperator {
                                Name = t.BinaryOperator.Name
                            }));
                        }
                        else
                        {
                            throw MakeInvalidSyntaxRule();
                        }
                    }
                    else if (t.OnUnaryOperator)
                    {
                        Shift(3);
                    }
                    else if (t.OnLeftParen)
                    {
                        Shift(4);
                    }
                    else if (t.OnRightParen)
                    {
                        Reduce0(() => SyntaxRule.CreateParameterList(SyntaxParameterList.CreateNull(new ProductionNullParameterList {
                        })));
                    }
                    else if (t.OnComma)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnExpr)
                    {
                        Shift(10);
                    }
                    else if (t.OnParameterList)
                    {
                        Shift(11);
                    }
                    else if (t.OnNonnullParameterList)
                    {
                        Shift(12);
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }
                else if (State == 7)
                {
                    if (Token.OnSome && Token.Some.OnLeftParen)
                    {
                        Shift(6);
                    }
                    else
                    {
                        Reduce2((u, e) => SyntaxRule.CreateExpr(SyntaxExpr.CreateUnaryOperator(new ProductionUnaryOperator {
                            UnaryOperator = u.UnaryOperator, Expr = e.Expr
                        })));
                    }
                }
                else if (State == 8)
                {
                    if (!Token.OnSome)
                    {
                        throw MakeInvalidEndOfFile();
                    }
                    var t = Token.Some;
                    if (t.OnBinaryOperator)
                    {
                        BinaryOperatorStack.Push(t.BinaryOperator);
                        Shift(9);
                    }
                    else if (t.OnRightParen)
                    {
                        Shift(13);
                    }
                    else
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                }
                else if (State == 9)
                {
                    if (!Token.OnSome)
                    {
                        throw MakeInvalidEndOfFile();
                    }
                    var t = Token.Some;
                    if (t.OnLiteral)
                    {
                        Shift(1);
                    }
                    else if (t.OnIdentifier)
                    {
                        Shift(2);
                    }
                    else if (t.OnBinaryOperator)
                    {
                        if (t.BinaryOperator.Name == "+" || t.BinaryOperator.Name == "-")
                        {
                            Replace(SyntaxRule.CreateUnaryOperator(new TokenUnaryOperator {
                                Name = t.BinaryOperator.Name
                            }));
                        }
                        else
                        {
                            throw MakeInvalidSyntaxRule();
                        }
                    }
                    else if (t.OnUnaryOperator)
                    {
                        Shift(3);
                    }
                    else if (t.OnLeftParen)
                    {
                        Shift(4);
                    }
                    else if (t.OnRightParen)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnComma)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnExpr)
                    {
                        Shift(14);
                    }
                    else if (t.OnParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnNonnullParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }
                else if (State == 10)
                {
                    if (Token.OnSome && Token.Some.OnBinaryOperator)
                    {
                        BinaryOperatorStack.Push(Token.Some.BinaryOperator);
                        Shift(9);
                    }
                    else
                    {
                        Reduce1(e => SyntaxRule.CreateNonnullParameterList(SyntaxNonnullParameterList.CreateSingle(new ProductionSingleParameterList {
                            Expr = e.Expr
                        })));
                    }
                }
                else if (State == 11)
                {
                    if (!Token.OnSome)
                    {
                        throw MakeInvalidEndOfFile();
                    }
                    var t = Token.Some;
                    if (t.OnRightParen)
                    {
                        Shift(15);
                    }
                    else
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                }
                else if (State == 12)
                {
                    if (Token.OnSome && Token.Some.OnComma)
                    {
                        Shift(16);
                    }
                    else
                    {
                        Reduce1(n => SyntaxRule.CreateParameterList(SyntaxParameterList.CreateNonnull(new ProductionNonnullParameterList {
                            NonnullParameterList = n.NonnullParameterList
                        })));
                    }
                }
                else if (State == 13)
                {
                    Reduce3((lp, e, rp) => SyntaxRule.CreateExpr(SyntaxExpr.CreateParen(new ProductionParen {
                        Expr = e.Expr
                    })));
                }
                else if (State == 14)
                {
                    if (Token.OnSome && Token.Some.OnBinaryOperator)
                    {
                        var sbo = BinaryOperatorStack.Peek();
                        var bo  = Token.Some.BinaryOperator;
                        var sp  = GetPriority(sbo);
                        var p   = GetPriority(bo);
                        if (p == 3 && p == sp && bo.Name != sbo.Name)
                        {
                            throw MakeInvalidSyntaxRule();
                        }
                        else if (p >= sp)
                        {
                            Reduce3((le, b, re) => SyntaxRule.CreateExpr(SyntaxExpr.CreateBinaryOperator(new ProductionBinaryOperator {
                                Left = le.Expr, BinaryOperator = b.BinaryOperator, Right = re.Expr
                            })));
                            BinaryOperatorStack.Pop();
                        }
                        else
                        {
                            BinaryOperatorStack.Push(Token.Some.BinaryOperator);
                            Shift(9);
                        }
                    }
                    else
                    {
                        Reduce3((le, b, re) => SyntaxRule.CreateExpr(SyntaxExpr.CreateBinaryOperator(new ProductionBinaryOperator {
                            Left = le.Expr, BinaryOperator = b.BinaryOperator, Right = re.Expr
                        })));
                        BinaryOperatorStack.Pop();
                    }
                }
                else if (State == 15)
                {
                    Reduce4((i, lp, p, rp) => SyntaxRule.CreateExpr(SyntaxExpr.CreateFunction(new ProductionFunction {
                        Identifier = i.Identifier, ParameterList = p.ParameterList
                    })));
                }
                else if (State == 16)
                {
                    if (!Token.OnSome)
                    {
                        throw MakeInvalidEndOfFile();
                    }
                    var t = Token.Some;
                    if (t.OnLiteral)
                    {
                        Shift(1);
                    }
                    else if (t.OnIdentifier)
                    {
                        Shift(2);
                    }
                    else if (t.OnBinaryOperator)
                    {
                        if (t.BinaryOperator.Name == "+" || t.BinaryOperator.Name == "-")
                        {
                            Replace(SyntaxRule.CreateUnaryOperator(new TokenUnaryOperator {
                                Name = t.BinaryOperator.Name
                            }));
                        }
                        else
                        {
                            throw MakeInvalidSyntaxRule();
                        }
                    }
                    else if (t.OnUnaryOperator)
                    {
                        Shift(3);
                    }
                    else if (t.OnLeftParen)
                    {
                        Shift(4);
                    }
                    else if (t.OnRightParen)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnComma)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnExpr)
                    {
                        Shift(17);
                    }
                    else if (t.OnParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else if (t.OnNonnullParameterList)
                    {
                        throw MakeInvalidSyntaxRule();
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }
                else if (State == 17)
                {
                    if (Token.OnSome && Token.Some.OnBinaryOperator)
                    {
                        BinaryOperatorStack.Push(Token.Some.BinaryOperator);
                        Shift(9);
                    }
                    else
                    {
                        Reduce3((n, c, e) => SyntaxRule.CreateNonnullParameterList(SyntaxNonnullParameterList.CreateMultiple(new ProductionMultipleParameterList {
                            NonnullParameterList = n.NonnullParameterList, Expr = e.Expr
                        })));
                    }
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }
            throw new InvalidOperationException();
        }