Flee
This commit is contained in:
589
Parsing/LookAheadSet.cs
Normal file
589
Parsing/LookAheadSet.cs
Normal file
@@ -0,0 +1,589 @@
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
|
||||
namespace Flee.Parsing
|
||||
{
|
||||
/*
|
||||
* A token look-ahead set. This class contains a set of token id
|
||||
* sequences. All sequences in the set are limited in length, so
|
||||
* that no single sequence is longer than a maximum value. This
|
||||
* class also filters out duplicates. Each token sequence also
|
||||
* contains a repeat flag, allowing the look-ahead set to contain
|
||||
* information about possible infinite repetitions of certain
|
||||
* sequences. That information is important when conflicts arise
|
||||
* between two look-ahead sets, as such a conflict cannot be
|
||||
* resolved if the conflicting sequences can be repeated (would
|
||||
* cause infinite loop).
|
||||
*/
|
||||
internal class LookAheadSet
|
||||
{
|
||||
private readonly ArrayList _elements = new ArrayList();
|
||||
private readonly int _maxLength;
|
||||
|
||||
public LookAheadSet(int maxLength)
|
||||
{
|
||||
this._maxLength = maxLength;
|
||||
}
|
||||
|
||||
public LookAheadSet(int maxLength, LookAheadSet set)
|
||||
: this(maxLength)
|
||||
{
|
||||
|
||||
AddAll(set);
|
||||
}
|
||||
|
||||
public int Size()
|
||||
{
|
||||
return _elements.Count;
|
||||
}
|
||||
|
||||
public int GetMinLength()
|
||||
{
|
||||
int min = -1;
|
||||
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
if (min < 0 || seq.Length() < min)
|
||||
{
|
||||
min = seq.Length();
|
||||
}
|
||||
}
|
||||
return (min < 0) ? 0 : min;
|
||||
}
|
||||
|
||||
public int GetMaxLength()
|
||||
{
|
||||
int max = 0;
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
if (seq.Length() > max)
|
||||
{
|
||||
max = seq.Length();
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public int[] GetInitialTokens()
|
||||
{
|
||||
ArrayList list = new ArrayList();
|
||||
int i;
|
||||
for (i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var token = ((Sequence)_elements[i]).GetToken(0);
|
||||
if (token != null && !list.Contains(token))
|
||||
{
|
||||
list.Add(token);
|
||||
}
|
||||
}
|
||||
var result = new int[list.Count];
|
||||
for (i = 0; i < list.Count; i++)
|
||||
{
|
||||
result[i] = (int)list[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool IsRepetitive()
|
||||
{
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
if (seq.IsRepetitive())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsNext(Parser parser)
|
||||
{
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
if (seq.IsNext(parser))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsNext(Parser parser, int length)
|
||||
{
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
if (seq.IsNext(parser, length))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsOverlap(LookAheadSet set)
|
||||
{
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
if (set.IsOverlap((Sequence)_elements[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsOverlap(Sequence seq)
|
||||
{
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var elem = (Sequence)_elements[i];
|
||||
if (seq.StartsWith(elem) || elem.StartsWith(seq))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool Contains(Sequence elem)
|
||||
{
|
||||
return FindSequence(elem) != null;
|
||||
}
|
||||
|
||||
public bool Intersects(LookAheadSet set)
|
||||
{
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
if (set.Contains((Sequence)_elements[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private Sequence FindSequence(Sequence elem)
|
||||
{
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
if (_elements[i].Equals(elem))
|
||||
{
|
||||
return (Sequence)_elements[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void Add(Sequence seq)
|
||||
{
|
||||
if (seq.Length() > _maxLength)
|
||||
{
|
||||
seq = new Sequence(_maxLength, seq);
|
||||
}
|
||||
if (!Contains(seq))
|
||||
{
|
||||
_elements.Add(seq);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(int token)
|
||||
{
|
||||
Add(new Sequence(false, token));
|
||||
}
|
||||
|
||||
public void AddAll(LookAheadSet set)
|
||||
{
|
||||
for (int i = 0; i < set._elements.Count; i++)
|
||||
{
|
||||
Add((Sequence)set._elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddEmpty()
|
||||
{
|
||||
Add(new Sequence());
|
||||
}
|
||||
|
||||
private void Remove(Sequence seq)
|
||||
{
|
||||
_elements.Remove(seq);
|
||||
}
|
||||
|
||||
public void RemoveAll(LookAheadSet set)
|
||||
{
|
||||
for (int i = 0; i < set._elements.Count; i++)
|
||||
{
|
||||
Remove((Sequence)set._elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public LookAheadSet CreateNextSet(int token)
|
||||
{
|
||||
LookAheadSet result = new LookAheadSet(_maxLength - 1);
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
var value = seq.GetToken(0);
|
||||
if (value != null && token == (int)value)
|
||||
{
|
||||
result.Add(seq.Subsequence(1));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public LookAheadSet CreateIntersection(LookAheadSet set)
|
||||
{
|
||||
LookAheadSet result = new LookAheadSet(_maxLength);
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq1 = (Sequence)_elements[i];
|
||||
var seq2 = set.FindSequence(seq1);
|
||||
if (seq2 != null && seq1.IsRepetitive())
|
||||
{
|
||||
result.Add(seq2);
|
||||
}
|
||||
else if (seq2 != null)
|
||||
{
|
||||
result.Add(seq1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public LookAheadSet CreateCombination(LookAheadSet set)
|
||||
{
|
||||
LookAheadSet result = new LookAheadSet(_maxLength);
|
||||
|
||||
// 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++)
|
||||
{
|
||||
var 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++)
|
||||
{
|
||||
var second = (Sequence)set._elements[j];
|
||||
result.Add(first.Concat(_maxLength, second));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public LookAheadSet CreateOverlaps(LookAheadSet set)
|
||||
{
|
||||
LookAheadSet result = new LookAheadSet(_maxLength);
|
||||
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
if (set.IsOverlap(seq))
|
||||
{
|
||||
result.Add(seq);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public LookAheadSet CreateFilter(LookAheadSet set)
|
||||
{
|
||||
LookAheadSet result = new LookAheadSet(_maxLength);
|
||||
|
||||
// Handle special cases
|
||||
if (this.Size() <= 0 || set.Size() <= 0)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// Create combinations
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var first = (Sequence)_elements[i];
|
||||
for (int j = 0; j < set._elements.Count; j++)
|
||||
{
|
||||
var second = (Sequence)set._elements[j];
|
||||
if (first.StartsWith(second))
|
||||
{
|
||||
result.Add(first.Subsequence(second.Length()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public LookAheadSet CreateRepetitive()
|
||||
{
|
||||
LookAheadSet result = new LookAheadSet(_maxLength);
|
||||
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
if (seq.IsRepetitive())
|
||||
{
|
||||
result.Add(seq);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add(new Sequence(true, seq));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ToString(null);
|
||||
}
|
||||
|
||||
public string ToString(Tokenizer tokenizer)
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
buffer.Append("{");
|
||||
for (int i = 0; i < _elements.Count; i++)
|
||||
{
|
||||
var seq = (Sequence)_elements[i];
|
||||
buffer.Append("\n ");
|
||||
buffer.Append(seq.ToString(tokenizer));
|
||||
}
|
||||
buffer.Append("\n}");
|
||||
return buffer.ToString();
|
||||
}
|
||||
|
||||
private class Sequence
|
||||
{
|
||||
private bool _repeat;
|
||||
private readonly ArrayList _tokens;
|
||||
|
||||
public Sequence()
|
||||
{
|
||||
this._repeat = false;
|
||||
this._tokens = new ArrayList(0);
|
||||
}
|
||||
|
||||
public Sequence(bool repeat, int token)
|
||||
{
|
||||
_repeat = false;
|
||||
_tokens = new ArrayList(1);
|
||||
_tokens.Add(token);
|
||||
}
|
||||
|
||||
public Sequence(int length, Sequence seq)
|
||||
{
|
||||
this._repeat = seq._repeat;
|
||||
this._tokens = new ArrayList(length);
|
||||
if (seq.Length() < length)
|
||||
{
|
||||
length = seq.Length();
|
||||
}
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
_tokens.Add(seq._tokens[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Sequence(bool repeat, Sequence seq)
|
||||
{
|
||||
this._repeat = repeat;
|
||||
this._tokens = seq._tokens;
|
||||
}
|
||||
|
||||
public int Length()
|
||||
{
|
||||
return _tokens.Count;
|
||||
}
|
||||
|
||||
public object GetToken(int pos)
|
||||
{
|
||||
if (pos >= 0 && pos < _tokens.Count)
|
||||
{
|
||||
return _tokens[pos];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Sequence)
|
||||
{
|
||||
return Equals((Sequence)obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool Equals(Sequence seq)
|
||||
{
|
||||
if (_tokens.Count != seq._tokens.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < _tokens.Count; i++)
|
||||
{
|
||||
if (!_tokens[i].Equals(seq._tokens[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _tokens.Count.GetHashCode();
|
||||
}
|
||||
|
||||
public bool StartsWith(Sequence seq)
|
||||
{
|
||||
if (Length() < seq.Length())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < seq._tokens.Count; i++)
|
||||
{
|
||||
if (!_tokens[i].Equals(seq._tokens[i]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsRepetitive()
|
||||
{
|
||||
return _repeat;
|
||||
}
|
||||
|
||||
public bool IsNext(Parser parser)
|
||||
{
|
||||
for (int i = 0; i < _tokens.Count; i++)
|
||||
{
|
||||
var id = (int)_tokens[i];
|
||||
var token = parser.PeekToken(i);
|
||||
if (token == null || token.Id != id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsNext(Parser parser, int length)
|
||||
{
|
||||
if (length > _tokens.Count)
|
||||
{
|
||||
length = _tokens.Count;
|
||||
}
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
var id = (int)_tokens[i];
|
||||
var token = parser.PeekToken(i);
|
||||
if (token == null || token.Id != id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return ToString(null);
|
||||
}
|
||||
|
||||
public string ToString(Tokenizer tokenizer)
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
if (tokenizer == null)
|
||||
{
|
||||
buffer.Append(_tokens.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.Append("[");
|
||||
for (int i = 0; i < _tokens.Count; i++)
|
||||
{
|
||||
var id = (int)_tokens[i];
|
||||
var str = tokenizer.GetPatternDescription(id);
|
||||
if (i > 0)
|
||||
{
|
||||
buffer.Append(" ");
|
||||
}
|
||||
buffer.Append(str);
|
||||
}
|
||||
buffer.Append("]");
|
||||
}
|
||||
if (_repeat)
|
||||
{
|
||||
buffer.Append(" *");
|
||||
}
|
||||
return buffer.ToString();
|
||||
}
|
||||
|
||||
public Sequence Concat(int length, Sequence seq)
|
||||
{
|
||||
Sequence res = new Sequence(length, this);
|
||||
|
||||
if (seq._repeat)
|
||||
{
|
||||
res._repeat = true;
|
||||
}
|
||||
length -= this.Length();
|
||||
if (length > seq.Length())
|
||||
{
|
||||
res._tokens.AddRange(seq._tokens);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
res._tokens.Add(seq._tokens[i]);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public Sequence Subsequence(int start)
|
||||
{
|
||||
Sequence res = new Sequence(Length(), this);
|
||||
|
||||
while (start > 0 && res._tokens.Count > 0)
|
||||
{
|
||||
res._tokens.RemoveAt(0);
|
||||
start--;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user