Files
Flee/Parsing/ProductionPatternAlternative.cs

213 lines
5.3 KiB
C#

using System;
using System.Collections;
using System.Text;
namespace Flee.Parsing
{
/**
* A production pattern alternative. This class represents a list of
* production pattern elements. In order to provide productions that
* cannot be represented with the element occurance counters, multiple
* alternatives must be created and added to the same production
* pattern. A production pattern alternative is always contained
* within a production pattern.
*/
internal class ProductionPatternAlternative
{
private ProductionPattern _pattern;
private readonly ArrayList _elements = new ArrayList();
private LookAheadSet _lookAhead = null;
public ProductionPatternAlternative()
{
}
public ProductionPattern Pattern => _pattern;
public ProductionPattern GetPattern()
{
return Pattern;
}
internal LookAheadSet LookAhead
{
get
{
return _lookAhead;
}
set
{
_lookAhead = value;
}
}
public int Count => _elements.Count;
public int GetElementCount()
{
return Count;
}
public ProductionPatternElement this[int index] => (ProductionPatternElement)_elements[index];
public ProductionPatternElement GetElement(int pos)
{
return this[pos];
}
public bool IsLeftRecursive()
{
for (int i = 0; i < _elements.Count; i++)
{
var elem = (ProductionPatternElement)_elements[i];
if (elem.Id == _pattern.Id)
{
return true;
}
else if (elem.MinCount > 0)
{
break;
}
}
return false;
}
public bool IsRightRecursive()
{
for (int i = _elements.Count - 1; i >= 0; i--)
{
var elem = (ProductionPatternElement)_elements[i];
if (elem.Id == _pattern.Id)
{
return true;
}
else if (elem.MinCount > 0)
{
break;
}
}
return false;
}
public bool IsMatchingEmpty()
{
return GetMinElementCount() == 0;
}
internal void SetPattern(ProductionPattern pattern)
{
this._pattern = pattern;
}
public int GetMinElementCount()
{
int min = 0;
for (int i = 0; i < _elements.Count; i++)
{
var elem = (ProductionPatternElement)_elements[i];
min += elem.MinCount;
}
return min;
}
public int GetMaxElementCount()
{
int max = 0;
for (int i = 0; i < _elements.Count; i++)
{
var elem = (ProductionPatternElement)_elements[i];
if (elem.MaxCount >= Int32.MaxValue)
{
return Int32.MaxValue;
}
else
{
max += elem.MaxCount;
}
}
return max;
}
public void AddToken(int id, int min, int max)
{
AddElement(new ProductionPatternElement(true, id, min, max));
}
public void AddProduction(int id, int min, int max)
{
AddElement(new ProductionPatternElement(false, id, min, max));
}
public void AddElement(ProductionPatternElement elem)
{
_elements.Add(elem);
}
public void AddElement(ProductionPatternElement elem,
int min,
int max)
{
if (elem.IsToken())
{
AddToken(elem.Id, min, max);
}
else
{
AddProduction(elem.Id, min, max);
}
}
public override bool Equals(object obj)
{
if (obj is ProductionPatternAlternative)
{
return Equals((ProductionPatternAlternative)obj);
}
else
{
return false;
}
}
public bool Equals(ProductionPatternAlternative alt)
{
if (_elements.Count != alt._elements.Count)
{
return false;
}
for (int i = 0; i < _elements.Count; i++)
{
if (!_elements[i].Equals(alt._elements[i]))
{
return false;
}
}
return true;
}
public override int GetHashCode()
{
return _elements.Count.GetHashCode();
}
public override string ToString()
{
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < _elements.Count; i++)
{
if (i > 0)
{
buffer.Append(" ");
}
buffer.Append(_elements[i]);
}
return buffer.ToString();
}
}
}