Example #1
0
 /// <summary>
 /// Removes all the token sequences from a specified set. Only
 /// sequences already in this set will be removed.
 /// </summary>
 /// <param name="set">The set to remove from</param>
 public void RemoveAll(LookAheadSet set)
 {
     foreach (var elt in set.elements)
     {
         this.Remove(elt);
     }
 }
Example #2
0
        /// <summary>
        /// Returns a look-ahead set with all conflicts between
        /// alternatives in a production pattern.
        /// </summary>
        /// <param name="pattern">The production pattern</param>
        /// <param name="maxLength">The maximum token sequence length</param>
        /// <returns>A look-ahead set with the conflicts found</returns>
        /// <exception cref="ParserCreationException">
        /// If an inherent ambiguity was found among the look-ahead sets
        /// </exception>
        private LookAheadSet FindConflicts(
            ProductionPattern pattern,
            int maxLength)
        {
            LookAheadSet result = new LookAheadSet(maxLength);
            LookAheadSet set1;
            LookAheadSet set2;

            for (int i = 0; i < pattern.Count; i++)
            {
                set1 = pattern[i].LookAhead;
                for (int j = 0; j < i; j++)
                {
                    set2 = pattern[j].LookAhead;
                    result.AddAll(set1.CreateIntersection(set2));
                }
            }

            if (result.IsRepetitive)
            {
                this.ThrowAmbiguityException(pattern.Name, null, result);
            }

            return(result);
        }
Example #3
0
        /// <summary>
        /// Throws a parse exception that matches the specified look-ahead
        /// set. This method will take into account any initial matching
        /// tokens in the look-ahead set.
        /// </summary>
        /// <param name="set">The look-ahead set to match</param>
        /// <exception cref="ParseException">Always thrown by this method</exception>
        private void ThrowParseException(LookAheadSet set)
        {
            Token          token;
            IList <string> list = new List <string>();

            int[] initials;

            // Read tokens until mismatch
            while (set.IsNext(this, 1))
            {
                set = set.CreateNextSet(this.NextToken().Id);
            }

            // Find next token descriptions
            initials = set.InitialTokens;
            for (int i = 0; i < initials.Length; i++)
            {
                list.Add(this.GetTokenDescription(initials[i]));
            }

            // Create exception
            token = this.NextToken();
            throw new ParseException(
                      ParseException.ErrorType.UnexpectedToken,
                      token.ToShortString(),
                      list,
                      token.StartLine,
                      token.StartColumn);
        }
Example #4
0
 /// <summary>
 /// Adds all the token sequences from a specified set. Only
 /// sequences not already in this set will be added.
 /// </summary>
 /// <param name="set">The set to add from</param>
 public void AddAll(LookAheadSet set)
 {
     foreach (var elt in set.elements)
     {
         this.Add(elt);
     }
 }
Example #5
0
        /**
         * Creates a new look-ahead set filter. The filter will contain
         * all sequences from this set, possibly left trimmed by each one
         * of the sequences in the specified set.
         *
         * @param set            the look-ahead set to trim with
         *
         * @return a new look-ahead set filter
         */
        public LookAheadSet CreateFilter(LookAheadSet set)
        {
            LookAheadSet result = new LookAheadSet(maxLength);
            Sequence     first;
            Sequence     second;

            // Handle special cases
            if (Size() <= 0 || set.Size() <= 0)
            {
                return(this);
            }

            // Create combinations
            for (int i = 0; i < elements.Count; i++)
            {
                first = (Sequence)elements[i];
                for (int j = 0; j < set.elements.Count; j++)
                {
                    second = (Sequence)set.elements[j];
                    if (first.StartsWith(second))
                    {
                        result.Add(first.Subsequence(second.Length()));
                    }
                }
            }
            return(result);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ProductionPatternElement"/> class.
        /// If the maximum value if zero (0) or negative, it will be set to <c>int.MaxValue</c>.
        /// </summary>
        /// <param name="isToken">The token flag</param>
        /// <param name="id">The node identity</param>
        /// <param name="min">The minimum number of occurrences</param>
        /// <param name="max">
        /// The maximum number of occurrences, or a negative value for infinite
        /// </param>
        public ProductionPatternElement(
            bool isToken,
            int id,
            int min,
            int max)
        {
            this.token = isToken;
            this.id    = id;
            if (min < 0)
            {
                min = 0;
            }

            this.min = min;

            if (max <= 0)
            {
                max = int.MaxValue;
            }
            else if (max < min)
            {
                max = min;
            }

            this.max       = max;
            this.lookAhead = null;
        }
Example #7
0
        /**
         * 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;
            ProductionPattern pattern;

            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);
        }
Example #8
0
        /**
         * Finds the look-ahead set for a production pattern. The maximum
         * look-ahead length must be specified. It is also possible to
         * specify a look-ahead set filter, which will make sure that
         * unnecessary token sequences will be avoided.
         *
         * @param pattern        the production pattern
         * @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 production pattern
         *
         * @throws ParserCreationException if an infinite loop was found
         *             in the grammar
         */
        private LookAheadSet FindLookAhead(ProductionPattern pattern,
                                           int length,
                                           CallStack stack,
                                           LookAheadSet filter)
        {
            LookAheadSet result;
            LookAheadSet temp;

            // Check for infinite loop
            if (stack.Contains(pattern.Name, length))
            {
                throw new ParserCreationException(
                          ParserCreationException.ErrorType.INFINITE_LOOP,
                          pattern.Name,
                          (String)null);
            }

            // Find pattern look-ahead
            stack.Push(pattern.Name, length);
            result = new LookAheadSet(length);
            for (int i = 0; i < pattern.Count; i++)
            {
                temp = FindLookAhead(pattern[i],
                                     length,
                                     0,
                                     stack,
                                     filter);
                result.AddAll(temp);
            }
            stack.Pop();

            return(result);
        }
Example #9
0
 /**
  * Removes all the token sequences from a specified set. Only
  * sequences already in this set will be removed.
  *
  * @param set            the set to remove from
  */
 public void RemoveAll(LookAheadSet set)
 {
     for (int i = 0; i < set.elements.Count; i++)
     {
         Remove((Sequence)set.elements[i]);
     }
 }
Example #10
0
 /**
  * Adds all the token sequences from a specified set. Only
  * sequences not already in this set will be added.
  *
  * @param set            the set to add from
  */
 public void AddAll(LookAheadSet set)
 {
     for (int i = 0; i < set.elements.Count; i++)
     {
         Add((Sequence)set.elements[i]);
     }
 }
Example #11
0
        /**
         * Throws a parse exception that matches the specified look-ahead
         * set. This method will take into account any initial matching
         * tokens in the look-ahead set.
         *
         * @param set            the look-ahead set to match
         *
         * @throws ParseException always thrown by this method
         */
        private void ThrowParseException(LookAheadSet set)
        {
            Token     token;
            ArrayList list = new ArrayList();

            int[] initials;

            // Read tokens until mismatch
            while (set.IsNext(this, 1))
            {
                set = set.CreateNextSet(NextToken().Id);
            }

            // Find next token descriptions
            initials = set.GetInitialTokens();
            for (int i = 0; i < initials.Length; i++)
            {
                list.Add(GetTokenDescription(initials[i]));
            }

            // Create exception
            token = NextToken();
            throw new ParseException(ParseException.ErrorType.UNEXPECTED_TOKEN,
                                     token.ToShortString(),
                                     list,
                                     token.StartLine,
                                     token.StartColumn);
        }
Example #12
0
        /// <summary>
        /// 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.
        /// </summary>
        /// <param name="elem">The production pattern element</param>
        /// <param name="length">The maximum look ahead length</param>
        /// <param name="dummy">A parameter to distinguish the method</param>
        /// <param name="stack">The call stack used for loop detection</param>
        /// <param name="filter">The look ahead set filter</param>
        /// <returns>The look-ahead set for the pattern element</returns>
        /// <exception cref="ParserCreationException">
        /// If an infinite loop was found in the grammar
        /// </exception>
        private LookAheadSet FindLookAhead(
            ProductionPatternElement elem,
            int length,
#pragma warning disable IDE0060 // Remove unused parameter
            int dummy,
#pragma warning restore IDE0060 // Remove unused parameter
            CallStack stack,
            LookAheadSet filter)
        {
            LookAheadSet      result;
            ProductionPattern pattern;

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

            return(result);
        }
Example #13
0
 /**
  * Creates a new production pattern.
  *
  * @param id             the production pattern id
  * @param name           the production pattern name
  */
 public ProductionPattern(int id, string name) {
     this.id = id;
     this.name = name;
     this.synthetic = false;
     this.alternatives = new ArrayList();
     this.defaultAlt = -1;
     this.lookAhead = null;
 }
Example #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ProductionPattern"/> class.
 /// </summary>
 /// <param name="id">The production pattern id</param>
 /// <param name="name">The production pattern name</param>
 public ProductionPattern(int id, string name)
 {
     this.id           = id;
     this.name         = name;
     this.synthetic    = false;
     this.alternatives = new List <ProductionPatternAlternative>();
     this.defaultAlt   = -1;
     this.lookAhead    = null;
 }
Example #15
0
 /**
  * Creates a new production pattern.
  *
  * @param id             the production pattern id
  * @param name           the production pattern name
  */
 public ProductionPattern(int id, string name)
 {
     id           = id;
     name         = name;
     synthetic    = false;
     alternatives = new ArrayList();
     defaultAlt   = -1;
     lookAhead    = null;
 }
Example #16
0
 /**
  * Checks if some token sequence is present in both this set
  * and a specified one.
  *
  * @param set            the look-ahead set to compare with
  *
  * @return true if the look-ahead sets intersect, or
  *         false otherwise
  */
 public bool Intersects(LookAheadSet set)
 {
     for (int i = 0; i < elements.Count; i++)
     {
         if (set.Contains((Sequence)elements[i]))
         {
             return(true);
         }
     }
     return(false);
 }
Example #17
0
 /**
  * Checks if another look-ahead set has an overlapping token
  * sequence. An overlapping token sequence is a token sequence
  * that is identical to another sequence, but for the length.
  * I.e. one of the two sequences may be longer than the other.
  *
  * @param set            the look-ahead set to check
  *
  * @return true if there is some token sequence that overlaps, or
  *         false otherwise
  */
 public bool IsOverlap(LookAheadSet set)
 {
     for (int i = 0; i < elements.Count; i++)
     {
         if (set.IsOverlap((Sequence)elements[i]))
         {
             return(true);
         }
     }
     return(false);
 }
Example #18
0
        /// <summary>
        /// Checks if another look-ahead set has an overlapping token
        /// sequence. An overlapping token sequence is a token sequence
        /// that is identical to another sequence, but for the length.
        /// I.e. one of the two sequences may be longer than the other.
        /// </summary>
        /// <param name="set">The look-ahead set to check</param>
        /// <returns>
        /// True if there is some token sequence that overlaps, or false otherwise
        /// </returns>
        public bool IsOverlap(LookAheadSet set)
        {
            foreach (var seq in this.elements)
            {
                if (set.IsOverlap(seq))
                {
                    return(true);
                }
            }

            return(false);
        }
Example #19
0
        /// <summary>
        /// Checks if some token sequence is present in both this set
        /// and a specified one.
        /// </summary>
        /// <param name="set">The look-ahead set to compare with</param>
        /// <returns>
        /// True if the look-ahead sets intersect, or false otherwise
        /// </returns>
        public bool Intersects(LookAheadSet set)
        {
            foreach (var elem in this.elements)
            {
                if (set.Contains(elem))
                {
                    return(true);
                }
            }

            return(false);
        }
Example #20
0
        /// <summary>
        /// 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.
        /// </summary>
        /// <param name="elem">The production pattern element</param>
        /// <param name="length">The maximum look-ahead length</param>
        /// <param name="stack">The call stack used for loop detection</param>
        /// <param name="filter">The look-ahead set filter</param>
        /// <returns>The look-ahead set for the pattern element</returns>
        /// <exception cref="ParserCreationException">
        /// If an infinite loop was found in the grammar
        /// </exception>
        private LookAheadSet FindLookAhead(
            ProductionPatternElement elem,
            int length,
            CallStack stack,
            LookAheadSet filter)
        {
            LookAheadSet result;
            LookAheadSet first;
            LookAheadSet follow;
            int          max;

            // Find initial element look-ahead
            first  = this.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 == int.MaxValue)
            {
                first = first.CreateRepetitive();
            }

            max = elem.MaxCount;
            if (length < max)
            {
                max = length;
            }

            for (int i = 1; i < max; i++)
            {
                first = first.CreateOverlaps(filter);
                if (first.Size <= 0 || first.MinLength >= length)
                {
                    break;
                }

                follow = this.FindLookAhead(
                    elem,
                    length,
                    0,
                    stack,
                    filter.CreateFilter(first));
                first = first.CreateCombination(follow);
                result.AddAll(first);
            }

            return(result);
        }
Example #21
0
        /**
         * Checks if the next tokens match a production pattern
         * alternative. The pattern alternative look-ahead set will be
         * used if existing, otherwise this method returns false.
         *
         * @param alt            the pattern alternative to check
         *
         * @return true if the next tokens match, or
         *         false otherwise
         */
        private bool IsNext(ProductionPatternAlternative alt)
        {
            LookAheadSet set = alt.LookAhead;

            if (set == null)
            {
                return(false);
            }
            else
            {
                return(set.IsNext(this));
            }
        }
Example #22
0
        /**
         * Checks if the next tokens match a production pattern. The
         * pattern look-ahead set will be used if existing, otherwise
         * this method returns false.
         *
         * @param pattern        the pattern to check
         *
         * @return true if the next tokens match, or
         *         false otherwise
         */
        private bool IsNext(ProductionPattern pattern)
        {
            LookAheadSet set = pattern.LookAhead;

            if (set == null)
            {
                return(false);
            }
            else
            {
                return(set.IsNext(this));
            }
        }
Example #23
0
        /**
         * Returns a look-ahead set with all conflicts between two
         * look-ahead sets.
         *
         * @param pattern        the pattern name being analyzed
         * @param location       the pattern location
         * @param set1           the first look-ahead set
         * @param set2           the second look-ahead set
         *
         * @return a look-ahead set with the conflicts found
         *
         * @throws ParserCreationException if an inherent ambiguity was
         *             found among the look-ahead sets
         */
        private LookAheadSet FindConflicts(string pattern,
                                           string location,
                                           LookAheadSet set1,
                                           LookAheadSet set2)
        {
            LookAheadSet result;

            result = set1.CreateIntersection(set2);
            if (result.IsRepetitive())
            {
                ThrowAmbiguityException(pattern, location, result);
            }
            return(result);
        }
Example #24
0
        /// <summary>
        /// Creates a new look-ahead set with overlaps from another. All
        /// token sequences in this set that overlaps with the other set
        /// will be added to the new look-ahead set.
        /// </summary>
        /// <param name="set">The look-ahead set to check with</param>
        /// <returns>A new look-ahead set containing the overlaps</returns>
        public LookAheadSet CreateOverlaps(LookAheadSet set)
        {
            LookAheadSet result = new LookAheadSet(this.maxLength);

            foreach (var seq in this.elements)
            {
                if (set.IsOverlap(seq))
                {
                    result.Add(seq);
                }
            }

            return(result);
        }
Example #25
0
        /**
         * Creates a new look-ahead set with overlaps from another. All
         * token sequences in this set that overlaps with the other set
         * will be added to the new look-ahead set.
         *
         * @param set            the look-ahead set to check with
         *
         * @return a new look-ahead set containing the overlaps
         */
        public LookAheadSet CreateOverlaps(LookAheadSet set)
        {
            LookAheadSet result = new LookAheadSet(maxLength);
            Sequence     seq;

            for (int i = 0; i < elements.Count; i++)
            {
                seq = (Sequence)elements[i];
                if (set.IsOverlap(seq))
                {
                    result.Add(seq);
                }
            }
            return(result);
        }
Example #26
0
        /// <summary>
        /// Creates a new look-ahead set that is the result of reading
        /// the specified token. The new look-ahead set will contain
        /// the rest of all the token sequences that started with the
        /// specified token.
        /// </summary>
        /// <param name="token">The token to read</param>
        /// <returns>
        /// A new look-ahead set containing the remaining tokens
        /// </returns>
        public LookAheadSet CreateNextSet(int token)
        {
            LookAheadSet result = new LookAheadSet(this.maxLength - 1);
            object       value;

            foreach (var seq in this.elements)
            {
                value = seq.GetToken(0);
                if (value != null && token == (int)value)
                {
                    result.Add(seq.Subsequence(1));
                }
            }

            return(result);
        }
Example #27
0
        /**
         * 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)));
            }
        }
Example #28
0
        /**
         * Creates a new look-ahead set that is the result of reading
         * the specified token. The new look-ahead set will contain
         * the rest of all the token sequences that started with the
         * specified token.
         *
         * @param token          the token to read
         *
         * @return a new look-ahead set containing the remaining tokens
         */
        public LookAheadSet CreateNextSet(int token)
        {
            LookAheadSet result = new LookAheadSet(maxLength - 1);
            Sequence     seq;
            object       value;

            for (int i = 0; i < elements.Count; i++)
            {
                seq   = (Sequence)elements[i];
                value = seq.GetToken(0);
                if (value != null && token == (int)value)
                {
                    result.Add(seq.Subsequence(1));
                }
            }
            return(result);
        }
Example #29
0
        /// <summary>
        /// Finds the look-ahead set for a production pattern alternative.
        /// The pattern position and maximum look-ahead length must be
        /// specified. It is also possible to specify a look-ahead set
        /// filter, which will make sure that unnecessary token sequences
        /// will be avoided.
        /// </summary>
        /// <param name="alt">The production pattern alternative</param>
        /// <param name="length">The maximum look-ahead length</param>
        /// <param name="pos">The pattern element position</param>
        /// <param name="stack">The call stack used for loop detection</param>
        /// <param name="filter">The look-ahead set filter</param>
        /// <returns>
        /// The look-ahead set for the pattern alternative
        /// </returns>
        /// <exception cref="ParserCreationException">
        /// If an infinite loop was found in the grammar
        /// </exception>
        private LookAheadSet FindLookAhead(
            ProductionPatternAlternative alt,
            int length,
            int pos,
            CallStack stack,
            LookAheadSet filter)
        {
            LookAheadSet first;
            LookAheadSet follow;
            LookAheadSet overlaps;

            // Check trivial cases
            if (length <= 0 || pos >= alt.Count)
            {
                return(new LookAheadSet(0));
            }

            // Find look-ahead for this element
            first = this.FindLookAhead(alt[pos], length, stack, filter);
            if (alt[pos].MinCount == 0)
            {
                first.AddEmpty();
            }

            // Find remaining look-ahead
            if (filter == null)
            {
                length -= first.MinLength;
                if (length > 0)
                {
                    follow = this.FindLookAhead(alt, length, pos + 1, stack, null);
                    first  = first.CreateCombination(follow);
                }
            }
            else if (filter.IsOverlap(first))
            {
                overlaps = first.CreateOverlaps(filter);
                length  -= overlaps.MinLength;
                filter   = filter.CreateFilter(overlaps);
                follow   = this.FindLookAhead(alt, length, pos + 1, stack, filter);
                first.RemoveAll(overlaps);
                first.AddAll(overlaps.CreateCombination(follow));
            }

            return(first);
        }
Example #30
0
        /// <summary>
        /// Throws a parser creation exception for an ambiguity. The
        /// specified look-ahead set contains the token conflicts to be
        /// reported.
        /// </summary>
        /// <param name="pattern">The production pattern name</param>
        /// <param name="location">The production pattern location, or null</param>
        /// <param name="set">The look-ahead set with conflicts</param>
        /// <exception cref="ParserCreationException">
        /// Always thrown by this method
        /// </exception>
        private void ThrowAmbiguityException(
            string pattern,
            string location,
            LookAheadSet set)
        {
            int[] initials;

            // Find next token descriptions
            initials = set.InitialTokens;
            IList <string> list = initials.Select(i => this.GetTokenDescription(i)).ToList();

            // Create exception
            throw new ParserCreationException(
                      ParserCreationException.ErrorType.InherentAmbiguity,
                      pattern,
                      location,
                      list);
        }
Example #31
0
        /// <summary>
        /// Creates a new identical look-ahead set, except for the
        /// repeat flag being set in each token sequence.
        /// </summary>
        /// <returns>A new repetitive look-ahead set</returns>
        public LookAheadSet CreateRepetitive()
        {
            LookAheadSet result = new LookAheadSet(this.maxLength);

            foreach (var seq in this.elements)
            {
                if (seq.IsRepetitive)
                {
                    result.Add(seq);
                }
                else
                {
                    result.Add(new Sequence(true, seq));
                }
            }

            return(result);
        }
        /**
         * Calculates the look-ahead needed for the specified production
         * pattern. This method attempts to resolve any conflicts and
         * stores the results in the pattern look-ahead object.
         *
         * @param pattern        the production pattern
         *
         * @throws ParserCreationException if the look-ahead set couldn't
         *             be determined due to inherent ambiguities
         */
        private void CalculateLookAhead(ProductionPattern pattern) {
            ProductionPatternAlternative  alt;
            LookAheadSet                  result;
            LookAheadSet[]                alternatives;
            LookAheadSet                  conflicts;
            LookAheadSet                  previous = new LookAheadSet(0);
            int                           length = 1;
            int                           i;
            CallStack                     stack = new CallStack();

            // Calculate simple look-ahead
            stack.Push(pattern.Name, 1);
            result = new LookAheadSet(1);
            alternatives = new LookAheadSet[pattern.Count];
            for (i = 0; i < pattern.Count; i++) {
                alt = pattern[i];
                alternatives[i] = FindLookAhead(alt, 1, 0, stack, null);
                alt.LookAhead = alternatives[i];
                result.AddAll(alternatives[i]);
            }
            if (pattern.LookAhead == null) {
                pattern.LookAhead = result;
            }
            conflicts = FindConflicts(pattern, 1);

            // Resolve conflicts
            while (conflicts.Size() > 0) {
                length++;
                stack.Clear();
                stack.Push(pattern.Name, length);
                conflicts.AddAll(previous);
                for (i = 0; i < pattern.Count; i++) {
                    alt = pattern[i];
                    if (alternatives[i].Intersects(conflicts)) {
                        alternatives[i] = FindLookAhead(alt,
                                                        length,
                                                        0,
                                                        stack,
                                                        conflicts);
                        alt.LookAhead = alternatives[i];
                    }
                    if (alternatives[i].Intersects(conflicts)) {
                        if (pattern.DefaultAlternative == null) {
                            pattern.DefaultAlternative = alt;
                        } else if (pattern.DefaultAlternative != alt) {
                            result = alternatives[i].CreateIntersection(conflicts);
                            ThrowAmbiguityException(pattern.Name,
                                                    null,
                                                    result);
                        }
                    }
                }
                previous = conflicts;
                conflicts = FindConflicts(pattern, length);
            }

            // Resolve conflicts inside rules
            for (i = 0; i < pattern.Count; i++) {
                CalculateLookAhead(pattern[i], 0);
            }
        }
        /**
         * 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;
            LookAheadSet  first;
            LookAheadSet  follow;
            int           max;

            // 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; i++) {
                first = first.CreateOverlaps(filter);
                if (first.Size() <= 0 || first.GetMinLength() >= length) {
                    break;
                }
                follow = FindLookAhead(elem,
                                       length,
                                       0,
                                       stack,
                                       filter.CreateFilter(first));
                first = first.CreateCombination(follow);
                result.AddAll(first);
            }

            return result;
        }
        /**
         * Finds the look-ahead set for a production pattern. The maximum
         * look-ahead length must be specified. It is also possible to
         * specify a look-ahead set filter, which will make sure that
         * unnecessary token sequences will be avoided.
         *
         * @param pattern        the production pattern
         * @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 production pattern
         *
         * @throws ParserCreationException if an infinite loop was found
         *             in the grammar
         */
        private LookAheadSet FindLookAhead(ProductionPattern pattern,
                                           int length,
                                           CallStack stack,
                                           LookAheadSet filter) {

            LookAheadSet  result;
            LookAheadSet  temp;

            // Check for infinite loop
            if (stack.Contains(pattern.Name, length)) {
                throw new ParserCreationException(
                    ParserCreationException.ErrorType.INFINITE_LOOP,
                    pattern.Name,
                    (String) null);
            }

            // Find pattern look-ahead
            stack.Push(pattern.Name, length);
            result = new LookAheadSet(length);
            for (int i = 0; i < pattern.Count; i++) {
                temp = FindLookAhead(pattern[i],
                                     length,
                                     0,
                                     stack,
                                     filter);
                result.AddAll(temp);
            }
            stack.Pop();

            return result;
        }
        /**
         * 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;
            ProductionPatternElement  elem;
            LookAheadSet              first;
            LookAheadSet              follow;
            LookAheadSet              conflicts;
            LookAheadSet              previous = new LookAheadSet(0);
            String                    location;
            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++;
                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);
        }
Example #36
0
 /**
  * Adds all the token sequences from a specified set. Only
  * sequences not already in this set will be added.
  *
  * @param set            the set to add from
  */
 public void AddAll(LookAheadSet set) {
     for (int i = 0; i < set.elements.Count; i++) {
         Add((Sequence) set.elements[i]);
     }
 }
Example #37
0
 /**
  * Checks if another look-ahead set has an overlapping token
  * sequence. An overlapping token sequence is a token sequence
  * that is identical to another sequence, but for the length.
  * I.e. one of the two sequences may be longer than the other.
  *
  * @param set            the look-ahead set to check
  *
  * @return true if there is some token sequence that overlaps, or
  *         false otherwise
  */
 public bool IsOverlap(LookAheadSet set) {
     for (int i = 0; i < elements.Count; i++) {
         if (set.IsOverlap((Sequence) elements[i])) {
             return true;
         }
     }
     return false;
 }
Example #38
0
        /**
         * Creates a new look-ahead set that is the result of reading
         * the specified token. The new look-ahead set will contain
         * the rest of all the token sequences that started with the
         * specified token.
         *
         * @param token          the token to read
         *
         * @return a new look-ahead set containing the remaining tokens
         */
        public LookAheadSet CreateNextSet(int token) {
            LookAheadSet  result = new LookAheadSet(maxLength - 1);
            Sequence      seq;
            object        value;

            for (int i = 0; i < elements.Count; i++) {
                seq = (Sequence) elements[i];
                value = seq.GetToken(0);
                if (value != null && token == (int) value) {
                    result.Add(seq.Subsequence(1));
                }
            }
            return result;
        }
        /**
         * Creates a new element. If the maximum value if zero (0) or
         * negative, it will be set to Int32.MaxValue.
         *
         * @param isToken        the token flag
         * @param id             the node identity
         * @param min            the minimum number of occurancies
         * @param max            the maximum number of occurancies, or
         *                       negative for infinite
         */
        public ProductionPatternElement(bool isToken,
                                        int id,
                                        int min,
                                        int max) {

            this.token = isToken;
            this.id = id;
            if (min < 0) {
                min = 0;
            }
            this.min = min;
            if (max <= 0) {
                max = Int32.MaxValue;
            } else if (max < min) {
                max = min;
            }
            this.max = max;
            this.lookAhead = null;
        }
Example #40
0
        /**
         * Creates a duplicate look-ahead set, possibly with a
         * different maximum length.
         *
         * @param maxLength      the maximum token sequence length
         * @param set            the look-ahead set to copy
         */
        public LookAheadSet(int maxLength, LookAheadSet set)
            : this(maxLength) {

            AddAll(set);
        }
Example #41
0
        /**
         * Creates a new look-ahead set filter. The filter will contain
         * all sequences from this set, possibly left trimmed by each one
         * of the sequences in the specified set.
         *
         * @param set            the look-ahead set to trim with
         *
         * @return a new look-ahead set filter
         */
        public LookAheadSet CreateFilter(LookAheadSet set) {
            LookAheadSet  result = new LookAheadSet(maxLength);
            Sequence      first;
            Sequence      second;

            // Handle special cases
            if (this.Size() <= 0 || set.Size() <= 0) {
                return this;
            }

            // Create combinations
            for (int i = 0; i < elements.Count; i++) {
                first = (Sequence) elements[i];
                for (int j = 0; j < set.elements.Count; j++) {
                    second = (Sequence) set.elements[j];
                    if (first.StartsWith(second)) {
                        result.Add(first.Subsequence(second.Length()));
                    }
                }
            }
            return result;
        }
Example #42
0
        /**
         * Creates a new look-ahead set that is the combination of
         * this set with another set. The combination is created by
         * creating new token sequences that consist of appending all
         * elements from the specified set onto all elements in this
         * set. This is sometimes referred to as the cartesian
         * product.
         *
         * @param set            the set to combine with
         *
         * @return a new look-ahead set containing the combination
         */
        public LookAheadSet CreateCombination(LookAheadSet set) {
            LookAheadSet  result = new LookAheadSet(maxLength);
            Sequence      first;
            Sequence      second;

            // Handle special cases
            if (this.Size() <= 0) {
                return set;
            } else if (set.Size() <= 0) {
                return this;
            }

            // Create combinations
            for (int i = 0; i < elements.Count; i++) {
                first = (Sequence) elements[i];
                if (first.Length() >= maxLength) {
                    result.Add(first);
                } else if (first.Length() <= 0) {
                    result.AddAll(set);
                } else {
                    for (int j = 0; j < set.elements.Count; j++) {
                        second = (Sequence) set.elements[j];
                        result.Add(first.Concat(maxLength, second));
                    }
                }
            }
            return result;
        }
Example #43
0
 /**
  * Checks if some token sequence is present in both this set
  * and a specified one.
  *
  * @param set            the look-ahead set to compare with
  *
  * @return true if the look-ahead sets intersect, or
  *         false otherwise
  */
 public bool Intersects(LookAheadSet set) {
     for (int i = 0; i < elements.Count; i++) {
         if (set.Contains((Sequence) elements[i])) {
             return true;
         }
     }
     return false;
 }
        /**
         * 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;
            ProductionPattern  pattern;

            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;
        }
Example #45
0
 /**
  * Removes all the token sequences from a specified set. Only
  * sequences already in this set will be removed.
  *
  * @param set            the set to remove from
  */
 public void RemoveAll(LookAheadSet set) {
     for (int i = 0; i < set.elements.Count; i++) {
         Remove((Sequence) set.elements[i]);
     }
 }
        /**
         * Returns a look-ahead set with all conflics between
         * alternatives in a production pattern.
         *
         * @param pattern        the production pattern
         * @param maxLength      the maximum token sequence length
         *
         * @return a look-ahead set with the conflicts found
         *
         * @throws ParserCreationException if an inherent ambiguity was
         *             found among the look-ahead sets
         */
        private LookAheadSet FindConflicts(ProductionPattern pattern,
                                           int maxLength) {

            LookAheadSet  result = new LookAheadSet(maxLength);
            LookAheadSet  set1;
            LookAheadSet  set2;

            for (int i = 0; i < pattern.Count; i++) {
                set1 = pattern[i].LookAhead;
                for (int j = 0; j < i; j++) {
                    set2 = pattern[j].LookAhead;
                    result.AddAll(set1.CreateIntersection(set2));
                }
            }
            if (result.IsRepetitive()) {
                ThrowAmbiguityException(pattern.Name, null, result);
            }
            return result;
        }
Example #47
0
        /**
         * Creates a new look-ahead set that is the intersection of
         * this set with another set. The token sequences in the net
         * set will only have the repeat flag set if it was set in
         * both the identical token sequences.
         *
         * @param set            the set to intersect with
         *
         * @return a new look-ahead set containing the intersection
         */
        public LookAheadSet CreateIntersection(LookAheadSet set) {
            LookAheadSet  result = new LookAheadSet(maxLength);
            Sequence      seq1;
            Sequence      seq2;

            for (int i = 0; i < elements.Count; i++) {
                seq1 = (Sequence) elements[i];
                seq2 = set.FindSequence(seq1);
                if (seq2 != null && seq1.IsRepetitive()) {
                    result.Add(seq2);
                } else if (seq2 != null) {
                    result.Add(seq1);
                }
            }
            return result;
        }
        /**
         * Returns a look-ahead set with all conflicts between two
         * look-ahead sets.
         *
         * @param pattern        the pattern name being analyzed
         * @param location       the pattern location
         * @param set1           the first look-ahead set
         * @param set2           the second look-ahead set
         *
         * @return a look-ahead set with the conflicts found
         *
         * @throws ParserCreationException if an inherent ambiguity was
         *             found among the look-ahead sets
         */
        private LookAheadSet FindConflicts(string pattern,
                                           string location,
                                           LookAheadSet set1,
                                           LookAheadSet set2) {

            LookAheadSet  result;

            result = set1.CreateIntersection(set2);
            if (result.IsRepetitive()) {
                ThrowAmbiguityException(pattern, location, result);
            }
            return result;
        }
Example #49
0
        /**
         * Creates a new look-ahead set with overlaps from another. All
         * token sequences in this set that overlaps with the other set
         * will be added to the new look-ahead set.
         *
         * @param set            the look-ahead set to check with
         *
         * @return a new look-ahead set containing the overlaps
         */
        public LookAheadSet CreateOverlaps(LookAheadSet set) {
            LookAheadSet  result = new LookAheadSet(maxLength);
            Sequence      seq;

            for (int i = 0; i < elements.Count; i++) {
                seq = (Sequence) elements[i];
                if (set.IsOverlap(seq)) {
                    result.Add(seq);
                }
            }
            return result;
        }
        /**
         * Returns the union of all alternative look-ahead sets in a
         * production pattern.
         *
         * @param pattern        the production pattern
         *
         * @return a unified look-ahead set
         */
        private LookAheadSet FindUnion(ProductionPattern pattern) {
            LookAheadSet  result;
            int           length = 0;
            int           i;

            for (i = 0; i < pattern.Count; i++) {
                result = pattern[i].LookAhead;
                if (result.GetMaxLength() > length) {
                    length = result.GetMaxLength();
                }
            }
            result = new LookAheadSet(length);
            for (i = 0; i < pattern.Count; i++) {
                result.AddAll(pattern[i].LookAhead);
            }

            return result;
        }
Example #51
0
        /**
         * Creates a new identical look-ahead set, except for the
         * repeat flag being set in each token sequence.
         *
         * @return a new repetitive look-ahead set
         */
        public LookAheadSet CreateRepetitive() {
            LookAheadSet  result = new LookAheadSet(maxLength);
            Sequence      seq;

            for (int i = 0; i < elements.Count; i++) {
                seq = (Sequence) elements[i];
                if (seq.IsRepetitive()) {
                    result.Add(seq);
                } else {
                    result.Add(new Sequence(true, seq));
                }
            }
            return result;
        }
        /**
         * Throws a parse exception that matches the specified look-ahead
         * set. This method will take into account any initial matching
         * tokens in the look-ahead set.
         *
         * @param set            the look-ahead set to match
         *
         * @throws ParseException always thrown by this method
         */
        private void ThrowParseException(LookAheadSet set) {
            Token      token;
            ArrayList  list = new ArrayList();
            int[]      initials;

            // Read tokens until mismatch
            while (set.IsNext(this, 1)) {
                set = set.CreateNextSet(NextToken().Id);
            }

            // Find next token descriptions
            initials = set.GetInitialTokens();
            for (int i = 0; i < initials.Length; i++) {
                list.Add(GetTokenDescription(initials[i]));
            }

            // Create exception
            token = NextToken();
            throw new ParseException(ParseException.ErrorType.UNEXPECTED_TOKEN,
                                     token.ToShortString(),
                                     list,
                                     token.StartLine,
                                     token.StartColumn);
        }
        /**
         * Finds the look-ahead set for a production pattern alternative.
         * The pattern position and maximum look-ahead length must be
         * specified. It is also possible to specify a look-ahead set
         * filter, which will make sure that unnecessary token sequences
         * will be avoided.
         *
         * @param alt            the production pattern alternative
         * @param length         the maximum look-ahead length
         * @param pos            the pattern element position
         * @param stack          the call stack used for loop detection
         * @param filter         the look-ahead set filter
         *
         * @return the look-ahead set for the pattern alternative
         *
         * @throws ParserCreationException if an infinite loop was found
         *             in the grammar
         */
        private LookAheadSet FindLookAhead(ProductionPatternAlternative alt,
                                           int length,
                                           int pos,
                                           CallStack stack,
                                           LookAheadSet filter) {

            LookAheadSet  first;
            LookAheadSet  follow;
            LookAheadSet  overlaps;

            // Check trivial cases
            if (length <= 0 || pos >= alt.Count) {
                return new LookAheadSet(0);
            }

            // Find look-ahead for this element
            first = FindLookAhead(alt[pos], length, stack, filter);
            if (alt[pos].MinCount == 0) {
                first.AddEmpty();
            }

            // Find remaining look-ahead
            if (filter == null) {
                length -= first.GetMinLength();
                if (length > 0) {
                    follow = FindLookAhead(alt, length, pos + 1, stack, null);
                    first = first.CreateCombination(follow);
                }
            } else if (filter.IsOverlap(first)) {
                overlaps = first.CreateOverlaps(filter);
                length -= overlaps.GetMinLength();
                filter = filter.CreateFilter(overlaps);
                follow = FindLookAhead(alt, length, pos + 1, stack, filter);
                first.RemoveAll(overlaps);
                first.AddAll(overlaps.CreateCombination(follow));
            }

            return first;
        }
        /**
         * Throws a parser creation exception for an ambiguity. The
         * specified look-ahead set contains the token conflicts to be
         * reported.
         *
         * @param pattern        the production pattern name
         * @param location       the production pattern location, or null
         * @param set            the look-ahead set with conflicts
         *
         * @throws ParserCreationException always thrown by this method
         */
        private void ThrowAmbiguityException(string pattern,
                                             string location,
                                             LookAheadSet set) {

            ArrayList  list = new ArrayList();
            int[]      initials;

            // Find next token descriptions
            initials = set.GetInitialTokens();
            for (int i = 0; i < initials.Length; i++) {
                list.Add(GetTokenDescription(initials[i]));
            }

            // Create exception
            throw new ParserCreationException(
                ParserCreationException.ErrorType.INHERENT_AMBIGUITY,
                pattern,
                location,
                list);
        }