//*
        // * Parses a production pattern element. All nodes parsed may
        // * or may not be added to the parse tree node specified,
        // * depending on the analyzer callbacks.
        // *
        // * @param node the production parse tree node
        // * @param elem the production pattern element to parse
        // *
        // * @throws ParseException if the input couldn't be parsed
        // * correctly
        //

        private void ParseElement(Production node, ProductionPatternElement elem)
        {
            Node child = default(Node);

            for (int i = 0; i <= elem.MaxCount - 1; i++)
            {
                if (i < elem.MinCount || IsNext(elem))
                {
                    if (elem.IsToken())
                    {
                        child = NextToken(elem.Id);
                        EnterNode(child);
                        AddNode(node, ExitNode(child));
                    }
                    else
                    {
                        child = ParsePattern(GetPattern(elem.Id));
                        AddNode(node, child);
                    }
                }
                else
                {
                    break;                     // TODO: might not be correct. Was : Exit For
                }
            }
        }
Exemple #2
0
        //*
        // * Checks a production pattern element for completeness. If
        // * the element references a production pattern not added to
        // * this parser, a parser creation exception will be thrown.
        // *
        // * @param name the name of the pattern being checked
        // * @param elem the production pattern element to check
        // *
        // * @throws ParserCreationException if the element referenced a
        // * pattern not added to this parser
        //

        private void CheckElement(string name, ProductionPatternElement elem)
        {
            if (elem.IsProduction() && GetPattern(elem.Id) == null)
            {
                throw new ParserCreationException(ParserCreationException.ErrorType.INVALID_PRODUCTION, name, "an undefined production pattern id (" + elem.Id + ") is referenced");
            }
        }
        //*
        // * Adds a production pattern element to this alternative. The
        // * multiplicity values in the element will be overridden with
        // * the specified values. The element is appended to the end of
        // * the element list.
        // *
        // * @param elem the production pattern element
        // * @param min the minimum number of occurancies
        // * @param max the maximum number of occurancies, or
        // * -1 for infinite
        //

        public void AddElement(ProductionPatternElement elem, int min, int max)
        {
            if (elem.IsToken())
            {
                AddToken(elem.Id, min, max);
            }
            else
            {
                AddProduction(elem.Id, min, max);
            }
        }
        //*
        // * Returns the minimum number of elements needed to satisfy
        // * this alternative. The value returned is the sum of all the
        // * elements minimum count.
        // *
        // * @return the minimum number of elements
        //

        public int GetMinElementCount()
        {
            ProductionPatternElement elem = default(ProductionPatternElement);
            int min = 0;

            for (int i = 0; i <= elements.Count - 1; i++)
            {
                elem = (ProductionPatternElement)elements[i];
                min += elem.MinCount;
            }
            return(min);
        }
        //*
        // * Calculates the look-aheads needed for the specified pattern
        // * alternative. This method attempts to resolve any conflicts in
        // * optional elements by recalculating look-aheads for referenced
        // * productions.
        // *
        // * @param alt the production pattern alternative
        // * @param pos the pattern element position
        // *
        // * @throws ParserCreationException if the look-ahead set couldn't
        // * be determined due to inherent ambiguities
        //

        private void CalculateLookAhead(ProductionPatternAlternative alt, int pos)
        {
            ProductionPattern        pattern   = default(ProductionPattern);
            ProductionPatternElement elem      = default(ProductionPatternElement);
            LookAheadSet             first     = default(LookAheadSet);
            LookAheadSet             follow    = default(LookAheadSet);
            LookAheadSet             conflicts = default(LookAheadSet);
            LookAheadSet             previous  = new LookAheadSet(0);
            string location = null;
            int    length   = 1;

            // Check trivial cases
            if (pos >= alt.Count)
            {
                return;
            }

            // Check for non-optional element
            pattern = alt.Pattern;
            elem    = alt[pos];
            if (elem.MinCount == elem.MaxCount)
            {
                CalculateLookAhead(alt, pos + 1);
                return;
            }

            // Calculate simple look-aheads
            first  = FindLookAhead(elem, 1, new CallStack(), null);
            follow = FindLookAhead(alt, 1, pos + 1, new CallStack(), null);

            // Resolve conflicts
            location  = "at position " + (pos + 1);
            conflicts = FindConflicts(pattern.Name, location, first, follow);
            while (conflicts.Size() > 0)
            {
                length += 1;
                conflicts.AddAll(previous);
                first          = FindLookAhead(elem, length, new CallStack(), conflicts);
                follow         = FindLookAhead(alt, length, pos + 1, new CallStack(), conflicts);
                first          = first.CreateCombination(follow);
                elem.LookAhead = first;
                if (first.Intersects(conflicts))
                {
                    first = first.CreateIntersection(conflicts);
                    ThrowAmbiguityException(pattern.Name, location, first);
                }
                previous  = conflicts;
                conflicts = FindConflicts(pattern.Name, location, first, follow);
            }

            // Check remaining elements
            CalculateLookAhead(alt, pos + 1);
        }
Exemple #6
0
        //*
        // * Checks if this object is equal to another. This method only
        // * returns true for another identical production pattern
        // * element.
        // *
        // * @param obj the object to compare with
        // *
        // * @return true if the object is identical to this one, or
        // * false otherwise
        //

        public override bool Equals(object obj)
        {
            ProductionPatternElement elem = default(ProductionPatternElement);

            if (obj is ProductionPatternElement)
            {
                elem = (ProductionPatternElement)obj;
                return(this.token == elem.token && this.m_id == elem.Id && this.min == elem.min && this.max == elem.max);
            }
            else
            {
                return(false);
            }
        }
        //*
        // * Checks if the next tokens match a production pattern
        // * element. If the element has a look-ahead set it will be
        // * used, otherwise the look-ahead set of the referenced
        // * production or token will be used.
        // *
        // * @param elem the pattern element to check
        // *
        // * @return true if the next tokens match, or
        // * false otherwise
        //

        private bool IsNext(ProductionPatternElement elem)
        {
            LookAheadSet @set = elem.LookAhead;

            if (@set != null)
            {
                return(@set.IsNext(this));
            }
            else if (elem.IsToken())
            {
                return(elem.IsMatch(PeekToken(0)));
            }
            else
            {
                return(IsNext(GetPattern(elem.Id)));
            }
        }
        //*
        // * Checks if this alternative is recursive on the right-hand side.
        // * This method checks all the possible right side elements and
        // * returns true if the pattern itself is among them.
        // *
        // * @return true if the alternative is right side recursive, or
        // * false otherwise
        //

        public bool IsRightRecursive()
        {
            ProductionPatternElement elem = default(ProductionPatternElement);

            for (int i = elements.Count - 1; i >= 0; i += -1)
            {
                elem = (ProductionPatternElement)elements[i];
                if (elem.Id == m_pattern.Id)
                {
                    return(true);
                }
                else if (elem.MinCount > 0)
                {
                    break;                     // TODO: might not be correct. Was : Exit For
                }
            }
            return(false);
        }
        //*
        // * Returns the maximum number of elements needed to satisfy
        // * this alternative. The value returned is the sum of all the
        // * elements maximum count.
        // *
        // * @return the maximum number of elements
        //

        public int GetMaxElementCount()
        {
            ProductionPatternElement elem = default(ProductionPatternElement);
            int max = 0;

            for (int i = 0; i <= elements.Count - 1; i++)
            {
                elem = (ProductionPatternElement)elements[i];
                if (elem.MaxCount >= Int32.MaxValue)
                {
                    return(Int32.MaxValue);
                }
                else
                {
                    max += elem.MaxCount;
                }
            }
            return(max);
        }
        //*
        // * Finds the look-ahead set for a production pattern element. The
        // * maximum look-ahead length must be specified. This method takes
        // * the element repeats into consideration when creating the
        // * look-ahead set, but does NOT include an empty sequence even if
        // * the minimum count is zero (0). It is also possible to specify a
        // * look-ahead set filter, which will make sure that unnecessary
        // * token sequences will be avoided.
        // *
        // * @param elem the production pattern element
        // * @param length the maximum look-ahead length
        // * @param stack the call stack used for loop detection
        // * @param filter the look-ahead set filter
        // *
        // * @return the look-ahead set for the pattern element
        // *
        // * @throws ParserCreationException if an infinite loop was found
        // * in the grammar
        //

        private LookAheadSet FindLookAhead(ProductionPatternElement elem, int length, CallStack stack, LookAheadSet filter)
        {
            LookAheadSet result = default(LookAheadSet);
            LookAheadSet first  = default(LookAheadSet);
            LookAheadSet follow = default(LookAheadSet);
            int          max    = 0;

            // Find initial element look-ahead
            first  = FindLookAhead(elem, length, 0, stack, filter);
            result = new LookAheadSet(length);
            result.AddAll(first);
            if (filter == null || !filter.IsOverlap(result))
            {
                return(result);
            }

            // Handle element repetitions
            if (elem.MaxCount == Int32.MaxValue)
            {
                first = first.CreateRepetitive();
            }
            max = elem.MaxCount;
            if (length < max)
            {
                max = length;
            }
            for (int i = 1; i <= max - 1; i++)
            {
                first = first.CreateOverlaps(filter);
                if (first.Size() <= 0 || first.GetMinLength() >= length)
                {
                    break;                     // TODO: might not be correct. Was : Exit For
                }
                follow = FindLookAhead(elem, length, 0, stack, filter.CreateFilter(first));
                first  = first.CreateCombination(follow);
                result.AddAll(first);
            }

            return(result);
        }
Exemple #11
0
        //*
        // * Returns a string representation of a production pattern
        // * element.
        // *
        // * @param elem the production pattern element
        // *
        // * @return a detailed string representation of the element
        //

        private string ToString(ProductionPatternElement elem)
        {
            StringBuilder buffer = new StringBuilder();
            int           min    = elem.MinCount;
            int           max    = elem.MaxCount;

            if (min == 0 && max == 1)
            {
                buffer.Append("[");
            }
            if (elem.IsToken())
            {
                buffer.Append(GetTokenDescription(elem.Id));
            }
            else
            {
                buffer.Append(GetPattern(elem.Id).Name);
            }
            if (min == 0 && max == 1)
            {
                buffer.Append("]");
            }
            else if (min == 0 && max == Int32.MaxValue)
            {
                buffer.Append("*");
            }
            else if (min == 1 && max == Int32.MaxValue)
            {
                buffer.Append("+");
            }
            else if (min != 1 || max != 1)
            {
                buffer.Append("{");
                buffer.Append(min);
                buffer.Append(",");
                buffer.Append(max);
                buffer.Append("}");
            }
            return(buffer.ToString());
        }
        //*
        // * Finds the look-ahead set for a production pattern element. The
        // * maximum look-ahead length must be specified. This method does
        // * NOT take the element repeat into consideration when creating
        // * the look-ahead set. It is also possible to specify a look-ahead
        // * set filter, which will make sure that unnecessary token
        // * sequences will be avoided.
        // *
        // * @param elem the production pattern element
        // * @param length the maximum look-ahead length
        // * @param dummy a parameter to distinguish the method
        // * @param stack the call stack used for loop detection
        // * @param filter the look-ahead set filter
        // *
        // * @return the look-ahead set for the pattern element
        // *
        // * @throws ParserCreationException if an infinite loop was found
        // * in the grammar
        //

        private LookAheadSet FindLookAhead(ProductionPatternElement elem, int length, int dummy, CallStack stack, LookAheadSet filter)
        {
            LookAheadSet      result  = default(LookAheadSet);
            ProductionPattern pattern = default(ProductionPattern);

            if (elem.IsToken())
            {
                result = new LookAheadSet(length);
                result.Add(elem.Id);
            }
            else
            {
                pattern = GetPattern(elem.Id);
                result  = FindLookAhead(pattern, length, stack, filter);
                if (stack.Contains(pattern.Name))
                {
                    result = result.CreateRepetitive();
                }
            }

            return(result);
        }
        //*
        // * Adds a production pattern element to this alternative. The
        // * element is appended to the end of the element list.
        // *
        // * @param elem the production pattern element
        //

        public void AddElement(ProductionPatternElement elem)
        {
            elements.Add(elem);
        }