예제 #1
0
        /// <summary>
        /// Adds the specified SPPF node to the cache
        /// </summary>
        /// <param name="node">The node to add to the cache</param>
        /// <param name="action">The tree action to apply onto the node</param>
        private void AddToCache(SPPFNodeNormal node, TreeAction action)
        {
            SPPFNodeVersion version = node.DefaultVersion;

            while (cacheNext + version.ChildrenCount + 1 >= cacheChildren.Length)
            {
                // the current cache is not big enough, build a bigger one
                Array.Resize(ref cacheChildren, cacheChildren.Length + INIT_HANDLE_SIZE);
            }
            // add the node in the cache
            cacheChildren[cacheNext] = new SPPFNodeRef(node.Identifier, 0);
            // setup the handle to point to the root
            if (handleNext == handleIndices.Length)
            {
                Array.Resize(ref handleIndices, handleIndices.Length + INIT_HANDLE_SIZE);
                Array.Resize(ref handleActions, handleActions.Length + INIT_HANDLE_SIZE);
            }
            handleIndices[handleNext] = cacheNext;
            handleActions[handleNext] = action;
            // copy the children
            if (version.ChildrenCount > 0)
            {
                Array.Copy(version.Children, 0, cacheChildren, cacheNext + 1, version.ChildrenCount);
            }
            handleNext++;
            cacheNext += version.ChildrenCount + 1;
        }
예제 #2
0
        /// <summary>
        /// Executes the reduction as a normal reduction
        /// </summary>
        /// <param name="varIndex">The reduced variable index</param>
        /// <param name="headAction">The tree action applied in the rule's head</param>
        /// <returns>The identifier of the produced SPPF node</returns>
        private int ReduceNormal(int varIndex, TreeAction headAction)
        {
            TableElemRef promotedSymbol    = new TableElemRef();
            SPPFNodeRef  promotedReference = new SPPFNodeRef(SPPF.EPSILON, 0);

            int insertion = 0;

            for (int i = 0; i != handleNext; i++)
            {
                switch (handleActions[i])
                {
                case TreeAction.Promote:
                    if (promotedReference.NodeId != SPPF.EPSILON)
                    {
                        // not the first promotion
                        // create a new version for the promoted node
                        SPPFNodeNormal oldPromotedNode = sppf.GetNode(promotedReference.NodeId) as SPPFNodeNormal;
                        SPPFNodeRef    oldPromotedRef  = oldPromotedNode.NewVersion(promotedSymbol, cacheChildren, insertion);
                        // register the previously promoted reference into the cache
                        cacheChildren[0] = oldPromotedRef;
                        insertion        = 1;
                    }
                    // save the new promoted node
                    promotedReference = cacheChildren[handleIndices[i]];
                    SPPFNodeNormal  promotedNode    = sppf.GetNode(promotedReference.NodeId) as SPPFNodeNormal;
                    SPPFNodeVersion promotedVersion = promotedNode.GetVersion(promotedReference.Version);
                    promotedSymbol = promotedVersion.Label;
                    // repack the children on the left if any
                    Array.Copy(cacheChildren, handleIndices[i] + 1, cacheChildren, insertion, promotedVersion.ChildrenCount);
                    insertion += promotedVersion.ChildrenCount;
                    break;

                default:
                    // Repack the sub-root on the left
                    if (insertion != handleIndices[i])
                    {
                        cacheChildren[insertion] = cacheChildren[handleIndices[i]];
                    }
                    insertion++;
                    break;
                }
            }

            TableElemRef originalLabel = new TableElemRef(TableType.Variable, varIndex);
            TableElemRef currentLabel  = originalLabel;

            if (promotedReference.NodeId != SPPF.EPSILON)
            {
                // a promotion occurred
                currentLabel = promotedSymbol;
            }
            else if (headAction == TreeAction.ReplaceByEpsilon)
            {
                // this variable must be replaced in the final AST
                currentLabel = new TableElemRef(TableType.None, 0);
            }
            return(sppf.NewNode(originalLabel, currentLabel, cacheChildren, insertion));
        }