Mercury library  1.0
Translation of CFG grammars into an object model (Bachelor's thesis).
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties
Element.cs
Go to the documentation of this file.
1 using Mercury.Exceptions;
2 using Mercury.Nucleus.Trees;
3 using Mercury.Syntax;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Text;
8 
9 namespace Mercury.Interpreting
10 {
11 
12 //==<< ElementType >>========================================================
13 
15  public enum ElementType
16  {
18  Constant,
20  Variable,
22  Wildcard,
24  Structure,
25  }
26 
27 //=============================================================================
28 // IElement
29 //=============================================================================
30 
32  public interface IElement : IEquatable<IElement>
33  {
34  //--[ Properties ]---------------------------------------------------
35 
37  ElementType Type { get; }
38  }
39 
40 //=============================================================================
41 // Alternative
42 //=============================================================================
43 
48  public abstract class Alternative : IEquatable<Alternative>
49  {
50  //--[ Private methods ]----------------------------------------------
51 
52  private int? memhash = null;
53  protected HashSet<Symbol> smset;
54 
55  //--[ Constructors ]-------------------------------------------------
56 
67  public Alternative(SymbolType sm, IEnumerable<Symbol> symbols)
68  {
69  if (symbols == null) throw new ArgumentNullException("symbols");
70 
71  smset = new HashSet<Symbol>();
72  foreach(var symbol in symbols)
73  {
74  if (symbol == null) throw new ArgumentException("Argument 'symbols' contains null");
75  if (!sm.HasFlag(symbol.Type)) smset.Add(symbol);
76  }
77 
78  if ((sm == SymbolType.None) && (smset.Count == 0))
79  throw new ArgumentException("Empty alternative is not allowed");
80 
81  SymbolMask = sm;
82  Symbols = smset.ToList();
83  }
84 
85  //--[ Properties ]---------------------------------------------------
86 
92  public SymbolType SymbolMask { get; private set; }
93 
96  public IReadOnlyList<Symbol> Symbols { get; private set; }
97 
98  //--[ Methods ]------------------------------------------------------
99 
105  public bool MatchesSymbol(Symbol s)
106  { return (s != null) && (SymbolMask.HasFlag(s.Type) || smset.Contains(s)); }
107 
108  //--[ Overriden methods ]--------------------------------------------
109 
110  #region [ Object ]
111 
112  public override bool Equals(object obj)
113  {
114  Alternative other = obj as Alternative;
115  return (obj == null) ? false : Equals(other);
116  }
117 
118  public override int GetHashCode()
119  {
120  if (!memhash.HasValue)
121  {
122  memhash = 17 + 7 * (int) SymbolMask;
123  for (int ix = 0; ix < Symbols.Count; ++ix)
124  memhash = 31 * memhash + Symbols[ix].GetHashCode();
125  }
126 
127  return memhash.Value;
128  }
129 
130  public override string ToString()
131  {
132  StringBuilder sb = new StringBuilder();
133 
134  if (Symbols.Count != 0)
135  {
136  sb.Append(Symbols[0]);
137 
138  for (int ix = 1; ix < Symbols.Count; ++ix)
139  sb.Append('|').Append(Symbols[ix]);
140  }
141 
142  if (SymbolMask != SymbolType.None)
143  {
144  sb.Append(':');
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');
148  }
149 
150  return sb.ToString();
151  }
152 
153  #endregion
154 
155  //--[ Interface implementation ]-------------------------------------
156 
157  #region [ IEquatable ]
158 
159  public bool Equals(Alternative other)
160  {
161  return (SymbolMask == other.SymbolMask)
162  && (Symbols.Count == other.Symbols.Count)
163  && (Symbols.Zip(other.Symbols, (x, y) => x.Equals(y)).All(x => x));
164  }
165 
166  #endregion
167 
168  }
169 
170 //=============================================================================
171 // Constant
172 //=============================================================================
173 
178  public class Constant : Alternative, IElement, IEquatable<Constant>
179  {
180  //--[ Constructors ]-------------------------------------------------
181 
186  public Constant(Symbol symbol)
187  : this(new[] { symbol })
188  { }
189 
192  public Constant(IEnumerable<Symbol> symbols)
193  : this(SymbolType.None, symbols)
194  { }
195 
203  public Constant(SymbolType sm, IEnumerable<Symbol> symbols)
204  : base(sm, symbols)
205  { Type = ElementType.Constant; }
206 
207  //--[ Overriden methods ]--------------------------------------------
208 
209  #region [ Object ]
210 
211  public override bool Equals(object obj)
212  {
213  Constant other = obj as Constant;
214  return other == null ? false : Equals(other);
215  }
216 
217  public override int GetHashCode()
218  { return 23 * base.GetHashCode(); }
219 
220  public override string ToString()
221  { return base.ToString(); }
222 
223  #endregion
224 
225  //--[ Interface implementation ]-------------------------------------
226 
227  #region [ IElement ]
228 
229  public ElementType Type { get; private set; }
230 
231  #endregion
232 
233  #region [ IEquatable ]
234 
235  public bool Equals(IElement other)
236  {
237  return ((other != null) && (other.Type == ElementType.Constant))
238  ? Equals(other as Constant)
239  : false;
240  }
241 
242  public bool Equals(Constant other)
243  {
244  return (other != null)
245  && (GetHashCode() == other.GetHashCode())
246  && (base.Equals(other as Alternative));
247  }
248 
249  #endregion
250 
251  }
252 
253 //=============================================================================
254 // Variable
255 //=============================================================================
256 
261  public class Variable : Alternative, IElement, IEquatable<Variable>
262  {
263  //--[ Constructors ]-------------------------------------------------
264 
269  public Variable()
270  : this(Extensions.RandomString("FS.%.*"), SymbolType.Any, new Symbol[0])
271  { }
272 
282  public Variable(string name, SymbolType ws, IEnumerable<Symbol> symbols)
283  : base(ws, symbols)
284  {
285  if (!IsValidName(name)) throw new ArgumentException(string.Format("Invalid variable name '{0}'", name));
286  Type = ElementType.Variable;
287  Name = name;
288  }
289 
290  //--[ Properties ]---------------------------------------------------
291 
293  public string Name { get; private set; }
294 
295  //--[ Methods ]------------------------------------------------------
296 
307  public static bool IsValidName(string name)
308  {
309  return !string.IsNullOrEmpty(name)
310  && char.IsLetter(name[0])
311  && name.All(x => char.IsLetterOrDigit(x));
312  }
313 
314  //--[ Overriden methods ]--------------------------------------------
315 
316  #region [ Object ]
317 
318  public override bool Equals(object obj)
319  {
320  Variable other = obj as Variable;
321  return other == null ? false : Equals(other);
322  }
323 
324  public override int GetHashCode()
325  { return Name.GetHashCode() + 89 * base.GetHashCode(); }
326 
327  public override string ToString()
328  { return (new StringBuilder()).Append('#').Append(Name).Append(':').Append(base.ToString()).ToString(); }
329 
330  #endregion
331 
332  //--[ Interface implementation ]-------------------------------------
333 
334  #region [ IElement ]
335 
336  public ElementType Type { get; protected set; }
337 
338  #endregion
339 
340  #region [ IEquatable ]
341 
342  public bool Equals(IElement other)
343  {
344  return ((other != null) && (other.Type == ElementType.Variable))
345  ? Equals(other as Variable)
346  : false;
347  }
348 
349  public bool Equals(Variable other)
350  {
351  return (other != null)
352  && (GetHashCode() == other.GetHashCode())
353  && (Name == other.Name)
354  && (base.Equals(other));
355  }
356 
357  #endregion
358 
359  }
360 
361 //=============================================================================
362 // Wildcard
363 //=============================================================================
364 
370  public class Wildcard : Variable
371  {
372  //--[ Constructors ]-------------------------------------------------
373 
375  public Wildcard()
376  : this(null, SymbolType.Any, new Symbol[0])
377  { }
378 
387  public Wildcard(string name, SymbolType ws, IEnumerable<Symbol> symbols)
388  : base(name ?? Extensions.RandomString("WR.%.*"), ws, symbols)
389  { Type = ElementType.Wildcard; }
390 
391  //--[ Overriden methods ]--------------------------------------------
392 
393  #region [ Object ]
394 
395  public override bool Equals(object obj)
396  {
397  Wildcard other = obj as Wildcard;
398  return other == null ? false : Equals(other);
399  }
400 
401  public override int GetHashCode()
402  { return 7 * (base.GetHashCode() / 5); }
403 
404  public override string ToString()
405  { return "*" + base.ToString().Substring(1); }
406 
407  #endregion
408 
409  //--[ Interface implementation ]-------------------------------------
410 
411  #region [ IEquatable ]
412 
413  public new bool Equals(IElement other)
414  {
415  return ((other != null) && (other.Type == ElementType.Wildcard))
416  ? Equals(other as Wildcard)
417  : false;
418  }
419 
420  public bool Equals(Wildcard other)
421  {
422  return (other != null)
423  && (GetHashCode() == other.GetHashCode())
424  && (base.Equals(other));
425  }
426 
427  #endregion
428 
429  }
430 
431 //=============================================================================
432 // Structure
433 //=============================================================================
434 
439  public class Structure : Tree<IElement>, IElement
440  {
441  //--[ Private fields ]-----------------------------------------------
442 
443  private static Func<IElement, Tree<IElement>> transform =
444  x => x as Structure ?? new Tree<IElement>(x);
445 
446  //--[ Constructors ]-------------------------------------------------
447 
452  public Structure(IElement head)
453  : this (head, new IElement[0])
454  { }
455 
463  public Structure(IElement head, IEnumerable<IElement> subelements)
464  : base(head, subelements.Select(x => transform(x)))
465  {
466  if (head == null) throw new ArgumentNullException("value");
467 
468  this.Type = ElementType.Structure;
469  this.HasWildcard = Children.Any(x => x.Value.Type == ElementType.Wildcard);
470 
471  if ((head as Alternative) == null)
472  throw new InvalidElementException(this, "structure root must be an Alternative");
473  }
474 
475  //--[ Properties ]---------------------------------------------------
476 
484  public bool HasWildcard { get; private set; }
485 
486  //--[ Interface implementation ]-------------------------------------
487 
488  #region [ IElement ]
489 
490  public ElementType Type { get; private set; }
491 
492  #endregion
493 
494  #region [ IEquatable ]
495 
496  public bool Equals(IElement other)
497  {
498  return (other != null)
499  && (other.Type == ElementType.Structure)
500  && base.Equals(other as Tree<IElement>);
501  }
502 
503  #endregion
504 
505  }
506 }
SymbolType SymbolMask
Mask of symbol types this alternative matches regardless the symbol name.
Definition: Element.cs:92
Structure(IElement head)
Creates a new Structure structure with root only.
Definition: Element.cs:452
override bool Equals(object obj)
Definition: Element.cs:395
Maps token to symbol, keyword, number and string
Constant(IEnumerable< Symbol > symbols)
Constant that matches any of the specified symbols.
Definition: Element.cs:192
override bool Equals(object obj)
Definition: Element.cs:318
bool Equals(Constant other)
Definition: Element.cs:242
override int GetHashCode()
Definition: Element.cs:217
bool Equals(Alternative other)
Definition: Element.cs:159
Represents an alternative of elements. It may match specified symbols or symboltypes (Nonterminals...
Definition: Element.cs:48
Represents a tree of Mercury.Interpreting.IElement instances. Must match precisely to the parse tree...
Definition: Element.cs:439
Alternative(SymbolType sm, IEnumerable< Symbol > symbols)
Initializes a new instance of the Alternative class. If symbols contains symbols of type that is pre...
Definition: Element.cs:67
Constant(Symbol symbol)
Creates a Constant made of one symbol.
Definition: Element.cs:186
bool MatchesSymbol(Symbol s)
Indicates whether this alternative matches the given symbol.
Definition: Element.cs:105
Variable(string name, SymbolType ws, IEnumerable< Symbol > symbols)
Initializes a new instance of the variable class. See Mercury.Interpreting.Alternative's constructor ...
Definition: Element.cs:282
SymbolType
Represents a type of symbol. Implemented as Flags since Symbol type inference is ambiguous.
Definition: Symbol.cs:16
ElementType Type
Element type
Definition: Element.cs:37
Structure(IElement head, IEnumerable< IElement > subelements)
Creates a new Structure.
Definition: Element.cs:463
static bool IsValidName(string name)
Determines whether the specified string is a valid variable name.
Definition: Element.cs:307
new bool Equals(IElement other)
Definition: Element.cs:413
Represents a variable element that captures value and can be used on the RHS of the RewriteRule as an...
Definition: Element.cs:261
IReadOnlyList< Symbol > Symbols
List of specific symbols this alternative matches.
Definition: Element.cs:96
override string ToString()
Definition: Element.cs:220
bool Equals(IElement other)
Definition: Element.cs:496
ElementType
Element Type enumeration
Definition: Element.cs:15
bool Equals(Wildcard other)
Definition: Element.cs:420
override string ToString()
Definition: Element.cs:404
An element that matches zero or more values. Can be used as a variable, but the actioncall must be of...
Definition: Element.cs:370
Wildcard(string name, SymbolType ws, IEnumerable< Symbol > symbols)
Creates a new the Wildcard. See the Mercury.Interpreting.Alternative's constructor for more details...
Definition: Element.cs:387
Constant(SymbolType sm, IEnumerable< Symbol > symbols)
Initializes a new instance of the Constant class. See Mercury.Interpreting.Alternative's constructor ...
Definition: Element.cs:203
bool Equals(Variable other)
Definition: Element.cs:349
override string ToString()
Definition: Element.cs:130
bool Equals(IElement other)
Definition: Element.cs:235
Wildcard()
Creates a new Wildcard with a random name
Definition: Element.cs:375
Element interface
Definition: Element.cs:32
override string ToString()
Definition: Element.cs:327
A derivation tree
An exception representing a problem with Mercury.Interpreting.IElement descendants.
override bool Equals(object obj)
Definition: Element.cs:112
override int GetHashCode()
Definition: Element.cs:324
HashSet< Symbol > smset
Definition: Element.cs:53
Provides extension methods for the Mercury library.
Definition: Extensions.cs:12
bool Equals(IElement other)
Definition: Element.cs:342
override bool Equals(object obj)
Definition: Element.cs:211
Represents a single symbol of the grammar. This is an immutable class. For a symbol name to be val...
Definition: Symbol.cs:51
No failure
override int GetHashCode()
Definition: Element.cs:401
Constant element. Basically equivalent of Mercury.Interpreting.Alternative.
Definition: Element.cs:178
Variable()
Creates an anonymous variable, an equivalent of Mercury.Interpreting.Wildcard that matches exactly on...
Definition: Element.cs:269