예제 #1
0
파일: Cfg.cs 프로젝트: ph3rin/sacc
        private (Item?, ParseAction) FindTransitionOfItemOnUnchecked(Item item, Symbol symbol)
        {
            var productionLen = item.Production.Ingredients.Length;

            if (item.DotPos < productionLen && symbol == item.Production.Ingredients[item.DotPos])
            {
                return(item.ShiftedByOne(), ParseAction.MakeShift());
            }

            if (item.DotPos >= productionLen && symbol == item.Follow)
            {
                if (symbol == Symbol.EndOfInput && item.Production.Product == Symbol.ExtendedStartSymbol)
                {
                    return(null, ParseAction.MakeAccept());
                }

                return(null, ParseAction.MakeReduce(item.Production));
            }

            return(null, ParseAction.MakeDiscard());
        }
예제 #2
0
        public ParseAction TransitionedOn(Symbol symbol, out ParserState?targetState)
        {
            var items       = Expand();
            var transitions = new HashSet <Transition>();

            foreach (var item in items)
            {
                var(target, action) = mCfg.FindTransitionOfItemOn(item, symbol);
                if (action.Type == ParseActionType.Discard)
                {
                    continue;
                }
                var transition = new Transition(action, item, target);
                transitions.Add(transition);
            }

            if (transitions.Count == 0)
            {
                targetState = null;
                return(ParseAction.MakeReject());
            }

            if (transitions.Any(t => t.Action.Type == ParseActionType.Accept))
            {
                targetState = null;
                return(ParseAction.MakeAccept());
            }

            if (transitions.Any(t => t.Action.Type == ParseActionType.Reduce && (
                                    mCfg.AssociativityOf(t.Action.Production) == Associativity.Left ||
                                    mCfg.PrecedenceOf(t.Action.Production) > mCfg.PrecedenceOf(symbol))))
            {
                transitions.RemoveWhere(t => t.Action.Type != ParseActionType.Reduce);
                if (transitions.Count > 1)
                {
                    throw new Exception("There is a reduce-reduce conflict.");
                }
                targetState = null;
                return(ParseAction.MakeReduce(transitions.First().Action.Production));
            }

            if (transitions.All(t => t.Action.Type == ParseActionType.Reduce))
            {
                if (transitions.Count > 1)
                {
                    throw new Exception("There is a reduce-reduce conflict.");
                }
                targetState = null;
                return(ParseAction.MakeReduce(transitions.First().Action.Production));
            }

            transitions.RemoveWhere(t => t.Action.Type != ParseActionType.Shift);

            if (transitions.Count == 0)
            {
                targetState = null;
                return(ParseAction.MakeReject());
            }

            targetState = new ParserState(
                mCfg,
                transitions
                .Select(t => t.Dest ?? throw new NullReferenceException())
                .ToHashSet());
            return(ParseAction.MakeShift());
        }