コード例 #1
0
ファイル: ParseTableBuilder.cs プロジェクト: ph3rin/sacc
 public Rule(ParseAction action, Symbol symbol, int srcId, int?destId = null)
 {
     Action = action;
     Symbol = symbol;
     SrcId  = srcId;
     DestId = destId;
 }
コード例 #2
0
ファイル: Cfg.cs プロジェクト: ph3rin/sacc
        public (Item?, ParseAction) FindTransitionOfItemOn(Item item, Symbol symbol)
        {
            var(target, action) = FindTransitionOfItemOnUnchecked(item, symbol);

            return(TransitionIsValidForItem(action, item, symbol)
                ? (target, action)
                : (null, ParseAction.MakeDiscard()));
        }
コード例 #3
0
ファイル: Cfg.cs プロジェクト: ph3rin/sacc
        private bool TransitionIsValidForItem(ParseAction action, Item item, Symbol inputSymbol)
        {
            /*
             * Constraints:
             *  - If the action is to discard, then this is fine.
             *  - If precedence(lhs) < precedence(rhs), this must be a shift
             *  - If precedence(lhs) > precedence(rhs) and dot is at the end, this must be a reduce
             *  - If either has undefined precedence or associativity, then this is ok
             *  - If precedence(rhs) == precedence(lhs),
             *      - If either are left-associative and dot is at the end, this must be a reduce
             *      - Otherwise, this must be a shift
             */

            var lhsIdx = Array.FindLastIndex(item.Production.Ingredients, HasPrecedence);
            var lhs    = item.Production.OverridePrecedence ??
                         (lhsIdx != -1 ? item.Production.Ingredients[lhsIdx] : (Symbol?)null);
            var rhs    = inputSymbol;
            var pLeft  = PrecedenceOf(lhs);
            var pRight = PrecedenceOf(rhs);
            var aLeft  = AssociativityOf(lhs);
            var aRight = AssociativityOf(rhs);

            if (pLeft < pRight && action.Type != ParseActionType.Shift)
            {
                return(false);
            }

            if (pLeft > pRight && item.CanReduce && action.Type != ParseActionType.Reduce)
            {
                return(false);
            }

            if (pLeft is null || pRight is null || aLeft == Associativity.Default || aRight == Associativity.Default)
            {
                return(true);
            }

            if (pLeft == pRight)
            {
                Debug.Assert(aLeft == aRight);
                if (aLeft == Associativity.Left || aRight == Associativity.Left)
                {
                    if (item.CanReduce && action.Type != ParseActionType.Reduce)
                    {
                        return(false);
                    }
                }
                else if (action.Type != ParseActionType.Shift)
                {
                    return(false);
                }
            }

            return(true);
        }
コード例 #4
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());
        }
コード例 #5
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());
        }
コード例 #6
0
 public Entry(ParseAction action, int?destStateId = null)
 {
     Action       = action;
     mDestStateId = destStateId;
 }