示例#1
0
        private CharsetGrammar()
        {
            var provider       = new UnicodeCharSetProvider();
            var mapper         = new UnicodeUtf16Mapper(false, false);
            var rx             = RegexLexer.CreateRx(mapper);
            var rxWhitespace   = new RxAccept <char>(RxOfSymbol <char> .Extract(rx, RegexLexer.SymWhitespace), SymWhitespace, 0);
            var rxCharset      = new RxAccept <char>(RxOfSymbol <char> .Extract(rx, RegexLexer.SymCharset), SymCharset, 0);
            var rxRegexCharset = new RxAccept <char>(RxOfSymbol <char> .Extract(rx, RegexLexer.SymRegexCharset), SymRegexCharset, 0);
            var rxUnion        = new RxAccept <char>(RegexMatchSet.FromChars('|', '+').ToInvariant(mapper, provider, true), SymUnion, 0);
            var rxSubtract     = new RxAccept <char>(RegexMatchSet.FromChars('-').ToInvariant(mapper, provider, true), SymSubtract, 0);
            var rxIntersect    = new RxAccept <char>(RegexMatchSet.FromChars('&').ToInvariant(mapper, provider, true), SymIntersect, 0);
            var rxDifference   = new RxAccept <char>(RegexMatchSet.FromChars('^').ToInvariant(mapper, provider, true), SymDifference, 0);
            var rxNegate       = new RxAccept <char>(RegexMatchSet.FromChars('~').ToInvariant(mapper, provider, true), SymNegate, 0);
            var rxParensOpen   = new RxAccept <char>(RegexMatchSet.FromChars('(').ToInvariant(mapper, provider, true), SymParensOpen, 0);
            var rxParensClose  = new RxAccept <char>(RegexMatchSet.FromChars(')').ToInvariant(mapper, provider, true), SymParensClose, 0);
            var alpha          = new AlphabetBuilder <char>(
                new RxAlternation <char>(rxWhitespace,
                                         new RxAlternation <char>(rxCharset,
                                                                  new RxAlternation <char>(rxRegexCharset,
                                                                                           new RxAlternation <char>(rxUnion,
                                                                                                                    new RxAlternation <char>(rxSubtract,
                                                                                                                                             new RxAlternation <char>(rxIntersect,
                                                                                                                                                                      new RxAlternation <char>(rxDifference,
                                                                                                                                                                                               new RxAlternation <char>(rxNegate,
                                                                                                                                                                                                                        new RxAlternation <char>(rxParensOpen, rxParensClose))))))))),
                Utf16Chars.EOF,
                Utf16Chars.ValidBmp);
            var nfa = NfaBuilder <LetterId> .Build(alpha.Expression);

            var dfa = DfaBuilder <LetterId> .Build(nfa, LetterId.Eof);

            if (dfa.StartState.Id != default(Id <DfaState <LetterId> >))
            {
                throw new InvalidOperationException($"Internal error: Unexpected DFA start state {dfa.StartState.Id}");
            }
            this.stateMachine = DfaStateMachineEmitter.CreateExpression(dfa, AlphabetMapperEmitter <char> .CreateExpression(alpha)).Compile();
            this.table        = new LalrTableGenerator(new GrammarBuilder(-2, -1, SymExpression)
            {
                { SymUnionExpression, SymExpression, SymUnion, SymNegateExpression },
                { SymExpression, SymUnionExpression },
                { SymSubtractExpression, SymExpression, SymSubtract, SymNegateExpression },
                { SymExpression, SymSubtractExpression },
                { SymIntersectExpression, SymExpression, SymIntersect, SymNegateExpression },
                { SymExpression, SymIntersectExpression },
                { SymDifferenceExpression, SymExpression, SymDifference, SymNegateExpression },
                { SymExpression, SymDifferenceExpression },
                { SymExpression, SymNegateExpression },
                { SymNegateExpression, SymNegate, SymValueExpression },
                { SymNegateExpression, SymValueExpression },
                { SymValueExpression, SymParensOpen, SymExpression, SymParensClose },
                { SymValueExpression, SymCharset },
                { SymValueExpression, SymRegexCharset }
            })
                                .ComputeTable();
        }
示例#2
0
        public static Expression <Action <TParser, ParserContextBase <TAstNode, TInput, TPosition>, SymbolId, Capture <TInput>, TPosition> > CreateExpression <TParser, TAstNode, TInput, TPosition>(LalrTable table, IParserFragmentEmitter <TParser, TAstNode, TInput, TPosition> fragmentEmitter, Func <SymbolId, string> resolver = null)
        {
            var paramParser            = Expression.Parameter(typeof(TParser), "parser");
            var paramContext           = Expression.Parameter(typeof(ParserContextBase <TAstNode, TInput, TPosition>), "context");
            var paramTokenSymbolId     = Expression.Parameter(typeof(SymbolId), "tokenSymbolId");
            var paramTokenValue        = Expression.Parameter(typeof(Capture <TInput>), "tokenValue");
            var paramPosition          = Expression.Parameter(typeof(TPosition), "position");
            var varInitialState        = Expression.Variable(typeof(ParserState <TAstNode>), "initialState");
            var exprCurrentState       = Expression.Field(paramContext, Reflect <ParserContext <TAstNode, TInput, TPosition> > .GetField(c => c.currentState));
            var lblBreak               = Expression.Label("Break");
            var lblContinue            = Expression.Label("Continue");
            var ctor_ParserState       = Reflect.GetConstructor(() => new ParserState <TAstNode>(default(TAstNode), default(int), default(ParserState <TAstNode>)));
            var prop_ParserState_State = Reflect <ParserState <TAstNode> > .GetProperty(s => s.State);

            var prop_ParserState_Node = Reflect <ParserState <TAstNode> > .GetProperty(s => s.Node);

            var prop_ParserState_Parent = Reflect <ParserState <TAstNode> > .GetProperty(s => s.Parent);

            var meth_Accept = Reflect <ParserContext <TAstNode, TInput, TPosition> > .GetMethod(c => c.Accept(default(TAstNode)));

            var meth_SyntaxError = Reflect <ParserContext <TAstNode, TInput, TPosition> > .GetMethod(c => c.SyntaxError(default(SymbolId), default(Capture <TInput>), default(TPosition), default(IEnumerable <SymbolId>)));

            Expression DoShift(SymbolId symbolId, ShiftAction action)
            {
                return(Expression.Block(typeof(void),
                                        Expression.Assign(
                                            exprCurrentState,
                                            Expression.New(
                                                ctor_ParserState,
                                                fragmentEmitter.CreateTerminal(symbolId, paramParser, paramTokenValue, paramPosition),
                                                Expression.Constant(action.NewState),
                                                exprCurrentState)),
                                        Expression.Break(lblBreak)));
            }

            Expression DoReduce(ReduceSingleAction action)
            {
                var varCurrentState = Expression.Variable(typeof(ParserState <TAstNode>), "currentState");
                var varsNodes       = action.ProductionRule.RuleSymbolIds.Select(s => Expression.Variable(typeof(TAstNode), s.ToString(resolver))).ToArray();
                var body            = new List <Expression>(varsNodes.Length * 2 + 3);

                body.Add(Expression.Assign(
                             varCurrentState,
                             exprCurrentState));
                for (var i = varsNodes.Length - 1; i >= 0; i--)
                {
                    body.Add(Expression.Assign(
                                 varsNodes[i],
                                 Expression.Property(
                                     varCurrentState,
                                     prop_ParserState_Node)));
                    body.Add(Expression.Assign(
                                 varCurrentState,
                                 Expression.Property(
                                     varCurrentState,
                                     prop_ParserState_Parent)));
                }
                body.Add(Expression.Assign(
                             exprCurrentState,
                             Expression.New(
                                 ctor_ParserState,
                                 fragmentEmitter.CreateNonterminal(action.ProductionRule, paramParser, varsNodes),
                                 Expression.Switch(
                                     Expression.Property(
                                         varCurrentState,
                                         prop_ParserState_State),
                                     Expression.Throw(
                                         Expression.New(ctor_InvalidOperationException), typeof(int)),
                                     table.Action
                                     .Where(a => (a.Value.Type == ActionType.Goto) && (a.Key.Value == action.ProductionRule.ProductionSymbolId))
                                     .Select(a => Expression.SwitchCase(
                                                 Expression.Constant(((GotoAction)a.Value).NewState),
                                                 Expression.Constant(a.Key.State)
                                                 )).ToArray()),
                                 varCurrentState)));
                body.Add(Expression.Continue(lblContinue));
                return(Expression.Block(typeof(void),
                                        varsNodes.Append(varCurrentState),
                                        body));
            }

            Expression DoAccept()
            {
                return(Expression.Block(typeof(void),
                                        Expression.Call(
                                            paramContext,
                                            meth_Accept,
                                            Expression.Property(
                                                exprCurrentState,
                                                prop_ParserState_Node)),
                                        Expression.Assign(
                                            exprCurrentState,
                                            Expression.Property(
                                                exprCurrentState,
                                                prop_ParserState_Parent)),
                                        Expression.Break(lblBreak)));
            }

            Expression DoThrow()
            {
                throw new InvalidOperationException("Internal error: unexpected action type");
            }

            Expression DoSyntaxError()
            {
                var varSimulatedState  = Expression.Variable(typeof(ParserState <TAstNode>), "simulatedState");
                var lblSimulationBreak = Expression.Label(typeof(bool), "simulationBreak");

                Expression DoSimulateReduce(ProductionRule rule)
                {
                    Expression exprNewSimulatedState = Expression.Assign(
                        varSimulatedState,
                        Expression.New(
                            ctor_ParserState,
                            Expression.Default(typeof(TAstNode)),
                            Expression.Switch(
                                Expression.Property(
                                    varSimulatedState,
                                    prop_ParserState_State),
                                Expression.Break(
                                    lblSimulationBreak,
                                    Expression.Constant(false),
                                    typeof(int)),
                                table.Action
                                .Where(a => (a.Key.Value == rule.ProductionSymbolId) && (a.Value.Type == ActionType.Goto))
                                .GroupBy(a => ((GotoAction)a.Value).NewState)
                                .Select(g => Expression.SwitchCase(
                                            Expression.Constant(g.Key),
                                            g.Select(a => Expression.Constant(a.Key.State)))).ToArray()),
                            varSimulatedState));

                    return(rule.RuleSymbolIds.Count == 0
                                                        ? exprNewSimulatedState
                                                        : Expression.Block(
                               Expression.Assign(varSimulatedState,
                                                 rule.RuleSymbolIds.Aggregate <SymbolId, Expression>(varSimulatedState, (expression, id) => Expression.Property(expression, prop_ParserState_Parent))),
                               exprNewSimulatedState));
                }

                var varExpectedTokens = Expression.Variable(typeof(List <SymbolId>), "expectedTokens");
                var terminalSymbolIds = table.Action
                                        .Where(a => (a.Value.Type == ActionType.Accept) || (a.Value.Type == ActionType.Shift))
                                        .Select(a => a.Key.Value)
                                        .Distinct()
                                        .OrderBy(id => id.ToInt32())
                                        .ToArray();
                var body = new List <Expression>(terminalSymbolIds.Length + 2);

                body.Add(Expression.Assign(
                             varExpectedTokens,
                             Expression.New(
                                 ctor_ListOfSymbolId,
                                 Expression.Constant(terminalSymbolIds.Length))));
                foreach (var symbolId in terminalSymbolIds)
                {
                    body.Add(Expression.IfThen(
                                 Expression.Block(typeof(bool), new[] { varSimulatedState },
                                                  Expression.Assign(
                                                      varSimulatedState,
                                                      exprCurrentState),
                                                  Expression.Loop(
                                                      Expression.Switch(typeof(void),
                                                                        Expression.Property(
                                                                            varSimulatedState,
                                                                            prop_ParserState_State),
                                                                        Expression.Break(lblSimulationBreak,
                                                                                         Expression.Constant(false)),
                                                                        null,
                                                                        table.Action
                                                                        .Where(a => (a.Key.Value == symbolId) && (a.Value.Type == ActionType.Reduce))
                                                                        .GroupBy(a => ((ReduceSingleAction)a.Value).ProductionRule)
                                                                        .Select(g => Expression.SwitchCase(
                                                                                    DoSimulateReduce(g.Key),
                                                                                    g.Select(a => Expression.Constant(a.Key.State))))
                                                                        .Append(Expression.SwitchCase(
                                                                                    Expression.Break(lblSimulationBreak,
                                                                                                     Expression.Constant(true)),
                                                                                    table.Action
                                                                                    .Where(a => (a.Key.Value == symbolId) && ((a.Value.Type == ActionType.Accept) || (a.Value.Type == ActionType.Shift)))
                                                                                    .Select(a => Expression.Constant(a.Key.State))
                                                                                    )).ToArray()), lblSimulationBreak)),
                                 Expression.Call(
                                     varExpectedTokens,
                                     meth_ListOfSymbolId_Add,
                                     Expression.New(
                                         ctor_SymbolId_Int32,
                                         Expression.Constant(symbolId.ToInt32())))));
                }
                body.Add(Expression.Convert(
                             varExpectedTokens,
                             typeof(IEnumerable <SymbolId>)));
                var exprExpectedSymbolIds = Expression.Block(typeof(IEnumerable <SymbolId>), new[] { varExpectedTokens }, body);
                var exprCustomSyntaxError = fragmentEmitter.SyntaxError(paramParser, paramTokenSymbolId, paramTokenValue, paramPosition, exprExpectedSymbolIds);

                if (exprCustomSyntaxError?.Type == typeof(bool))
                {
                    exprCustomSyntaxError = Expression.IfThen(
                        exprCustomSyntaxError,
                        Expression.Continue(lblContinue));
                }
                return(Expression.Block(typeof(void),
                                        Expression.Assign(
                                            exprCurrentState,
                                            varInitialState),
                                        exprCustomSyntaxError ?? Expression.Call(
                                            paramContext,
                                            meth_SyntaxError,
                                            paramTokenSymbolId,
                                            paramTokenValue,
                                            paramPosition,
                                            exprExpectedSymbolIds),
                                        Expression.Break(lblBreak)));
            }

            return(Expression.Lambda <Action <TParser, ParserContextBase <TAstNode, TInput, TPosition>, SymbolId, Capture <TInput>, TPosition> >(
                       Expression.Block(typeof(void), new[] { varInitialState },
                                        Expression.Assign(
                                            varInitialState,
                                            exprCurrentState),
                                        Expression.Loop(
                                            Expression.Block(typeof(void),
                                                             Expression.Switch(
                                                                 Expression.Property(
                                                                     exprCurrentState,
                                                                     prop_ParserState_State),
                                                                 table.Action
                                                                 .Where(a => (a.Value.Type == ActionType.Shift) || (a.Value.Type == ActionType.Reduce) || (a.Value.Type == ActionType.Accept))
                                                                 .GroupBy(a => a.Key.State)
                                                                 .Select(g => Expression.SwitchCase(
                                                                             Expression.Switch(
                                                                                 Expression.Call(
                                                                                     paramTokenSymbolId,
                                                                                     meth_SymbolId_ToInt32),
                                                                                 g.Select(a => Expression.SwitchCase(
                                                                                              a.Value.Type == ActionType.Shift
                                                                                                                                                                                        ? DoShift(a.Key.Value, (ShiftAction)a.Value)
                                                                                                                                                                                        : a.Value.Type == ActionType.Reduce
                                                                                                                                                                                                        ? DoReduce((ReduceSingleAction)a.Value)
                                                                                                                                                                                                        : a.Value.Type == ActionType.Accept
                                                                                                                                                                                                                        ? DoAccept()
                                                                                                                                                                                                                        : DoThrow(),
                                                                                              Expression.Constant(a.Key.Value.ToInt32()))).ToArray()),
                                                                             Expression.Constant(g.Key))).ToArray()),
                                                             DoSyntaxError()
                                                             ), lblBreak, lblContinue)),
                       paramParser,
                       paramContext,
                       paramTokenSymbolId,
                       paramTokenValue,
                       paramPosition));
        }
示例#3
0
 protected ParserBase(LalrTable table, ParserContextBase <TAstNode, TInput, TPosition> context)
 {
     this.table   = table;
     this.context = context;
 }