Beispiel #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;
        }
Beispiel #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));
        }
Beispiel #3
0
        /// <summary>
        /// Adds a new version to this node
        /// </summary>
        /// <param name="label">The label for this version of the node</param>
        /// <param name="children">A buffer of children for this version of the node</param>
        /// <param name="childrenCount">The number of children</param>
        /// <returns>The reference to this new version</returns>
        public SPPFNodeRef NewVersion(TableElemRef label, SPPFNodeRef[] children, int childrenCount)
        {
            if (versionsCount == versions.Length)
            {
                Array.Resize(ref versions, versions.Length + VERSION_COUNT);
            }
            versions[versionsCount] = new SPPFNodeVersion(label, children, childrenCount);
            SPPFNodeRef result = new SPPFNodeRef(identifier, versionsCount);

            versionsCount++;
            return(result);
        }
Beispiel #4
0
        /// <summary>
        /// Builds the final AST for the specified SPPF node reference
        /// </summary>
        /// <param name="reference">A reference to an SPPF node in a specific version</param>
        /// <returns>The AST node for the SPPF reference</returns>
        public AST.Node BuildFinalAST(SPPFNodeRef reference)
        {
            SPPFNode        sppfNode = sppf.GetNode(reference.NodeId);
            SPPFNodeVersion version  = (sppfNode as SPPFNodeNormal).GetVersion(reference.Version);

            if (version.ChildrenCount == 0)
            {
                return(new AST.Node(version.Label));
            }

            AST.Node[] buffer = new AST.Node[version.ChildrenCount];
            for (int i = 0; i != version.ChildrenCount; i++)
            {
                buffer[i] = BuildFinalAST(version.Children[i]);
            }
            int first = result.Store(buffer, 0, version.ChildrenCount);

            return(new AST.Node(version.Label, version.ChildrenCount, first));
        }