1 using Mercury.Exceptions;
2 using Mercury.Nucleus.Trees;
5 using System.Collections.Generic;
9 namespace Mercury.Interpreting
32 public interface IElement : IEquatable<IElement>
52 private int? memhash = null;
53 protected HashSet<Symbol>
smset;
69 if (symbols == null)
throw new ArgumentNullException(
"symbols");
71 smset =
new HashSet<Symbol>();
72 foreach(var symbol
in symbols)
74 if (symbol == null)
throw new ArgumentException(
"Argument 'symbols' contains null");
75 if (!sm.HasFlag(symbol.Type)) smset.Add(symbol);
78 if ((sm ==
SymbolType.None) && (smset.Count == 0))
79 throw new ArgumentException(
"Empty alternative is not allowed");
82 Symbols = smset.ToList();
96 public IReadOnlyList<Symbol> Symbols {
get;
private set; }
106 {
return (s != null) && (SymbolMask.HasFlag(s.Type) || smset.Contains(s)); }
115 return (obj == null) ?
false : Equals(other);
120 if (!memhash.HasValue)
122 memhash = 17 + 7 * (int) SymbolMask;
123 for (
int ix = 0; ix < Symbols.Count; ++ix)
124 memhash = 31 * memhash + Symbols[ix].GetHashCode();
127 return memhash.Value;
132 StringBuilder sb =
new StringBuilder();
134 if (Symbols.Count != 0)
136 sb.Append(Symbols[0]);
138 for (
int ix = 1; ix < Symbols.Count; ++ix)
139 sb.Append(
'|').Append(Symbols[ix]);
145 if (SymbolMask.HasFlag(
SymbolType.Nonterminal)) sb.Append(
'N');
146 if (SymbolMask.HasFlag(
SymbolType.Terminal)) sb.Append(
'T');
147 if (SymbolMask.HasFlag(
SymbolType.Epsilon)) sb.Append(
'e');
150 return sb.ToString();
157 #region [ IEquatable ]
162 && (Symbols.Count == other.Symbols.Count)
163 && (Symbols.Zip(other.
Symbols, (x, y) => x.Equals(y)).
All(x => x));
187 : this(new[] { symbol })
205 { Type = ElementType.Constant; }
214 return other == null ?
false : Equals(other);
218 {
return 23 * base.GetHashCode(); }
221 {
return base.ToString(); }
233 #region [ IEquatable ]
244 return (other != null)
245 && (GetHashCode() == other.GetHashCode())
285 if (!IsValidName(name))
throw new ArgumentException(
string.Format(
"Invalid variable name '{0}'", name));
286 Type = ElementType.Variable;
293 public string Name {
get;
private set; }
309 return !string.IsNullOrEmpty(name)
310 &&
char.IsLetter(name[0])
311 && name.All(x => char.IsLetterOrDigit(x));
321 return other == null ?
false : Equals(other);
325 {
return Name.GetHashCode() + 89 * base.GetHashCode(); }
328 {
return (
new StringBuilder()).Append(
'#').Append(Name).Append(
':').Append(base.ToString()).ToString(); }
340 #region [ IEquatable ]
351 return (other != null)
352 && (GetHashCode() == other.GetHashCode())
353 && (Name == other.Name)
354 && (base.Equals(other));
388 : base(name ??
Extensions.RandomString(
"WR.%.*"), ws, symbols)
389 { Type = ElementType.Wildcard; }
398 return other == null ?
false : Equals(other);
402 {
return 7 * (base.GetHashCode() / 5); }
405 {
return "*" + base.ToString().Substring(1); }
411 #region [ IEquatable ]
422 return (other != null)
423 && (GetHashCode() == other.GetHashCode())
424 && (base.Equals(other));
443 private static Func<IElement, Tree<IElement>> transform =
444 x => x as
Structure ??
new Tree<IElement>(x);
464 : base(head, subelements.Select(x => transform(x)))
466 if (head == null)
throw new ArgumentNullException(
"value");
468 this.Type = ElementType.Structure;
469 this.HasWildcard = Children.Any(x => x.Value.Type == ElementType.Wildcard);
484 public bool HasWildcard {
get;
private set; }
494 #region [ IEquatable ]
498 return (other != null)
499 && (other.Type == ElementType.Structure)
500 && base.Equals(other as Tree<IElement>);
SymbolType SymbolMask
Mask of symbol types this alternative matches regardless the symbol name.
Structure(IElement head)
Creates a new Structure structure with root only.
override bool Equals(object obj)
Maps token to symbol, keyword, number and string
override int GetHashCode()
Constant(IEnumerable< Symbol > symbols)
Constant that matches any of the specified symbols.
override bool Equals(object obj)
bool Equals(Constant other)
override int GetHashCode()
bool Equals(Alternative other)
Represents an alternative of elements. It may match specified symbols or symboltypes (Nonterminals...
Represents a tree of Mercury.Interpreting.IElement instances. Must match precisely to the parse tree...
Alternative(SymbolType sm, IEnumerable< Symbol > symbols)
Initializes a new instance of the Alternative class. If symbols contains symbols of type that is pre...
Constant(Symbol symbol)
Creates a Constant made of one symbol.
bool MatchesSymbol(Symbol s)
Indicates whether this alternative matches the given symbol.
Variable(string name, SymbolType ws, IEnumerable< Symbol > symbols)
Initializes a new instance of the variable class. See Mercury.Interpreting.Alternative's constructor ...
SymbolType
Represents a type of symbol. Implemented as Flags since Symbol type inference is ambiguous.
ElementType Type
Element type
Structure(IElement head, IEnumerable< IElement > subelements)
Creates a new Structure.
static bool IsValidName(string name)
Determines whether the specified string is a valid variable name.
new bool Equals(IElement other)
Represents a variable element that captures value and can be used on the RHS of the RewriteRule as an...
IReadOnlyList< Symbol > Symbols
List of specific symbols this alternative matches.
override string ToString()
bool Equals(IElement other)
ElementType
Element Type enumeration
bool Equals(Wildcard other)
override string ToString()
An element that matches zero or more values. Can be used as a variable, but the actioncall must be of...
Wildcard(string name, SymbolType ws, IEnumerable< Symbol > symbols)
Creates a new the Wildcard. See the Mercury.Interpreting.Alternative's constructor for more details...
Constant(SymbolType sm, IEnumerable< Symbol > symbols)
Initializes a new instance of the Constant class. See Mercury.Interpreting.Alternative's constructor ...
bool Equals(Variable other)
override string ToString()
bool Equals(IElement other)
Wildcard()
Creates a new Wildcard with a random name
override string ToString()
An exception representing a problem with Mercury.Interpreting.IElement descendants.
override bool Equals(object obj)
override int GetHashCode()
Provides extension methods for the Mercury library.
bool Equals(IElement other)
override bool Equals(object obj)
Represents a single symbol of the grammar. This is an immutable class. For a symbol name to be val...
override int GetHashCode()
Constant element. Basically equivalent of Mercury.Interpreting.Alternative.
Variable()
Creates an anonymous variable, an equivalent of Mercury.Interpreting.Wildcard that matches exactly on...