PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/Otp/Erlang/PatternMatcher.cs

https://github.com/saleyn/otp.net
C# | 210 lines | 119 code | 28 blank | 63 comment | 4 complexity | db91fc41c7f08398131dfeb4e31e379b MD5 | raw file
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using ErlObject = Otp.Erlang.Object;
  8. using ErlVarBind = Otp.Erlang.VarBind;
  9. namespace Otp.Erlang
  10. {
  11. public delegate void PatternMatchAction(
  12. PatternMatcher.Pattern pattern, ErlObject term,
  13. ErlVarBind binding, params object[] args);
  14. public delegate void PatternMatchAction<TContext>(
  15. TContext ctx, PatternMatcher.Pattern pattern, ErlObject term,
  16. ErlVarBind binding, params object[] args);
  17. public delegate void PatternMatchAction<TContext, TErlTerm>(
  18. TContext ctx, PatternMatcher.Pattern pattern, TErlTerm term,
  19. ErlVarBind binding, params object[] args) where TErlTerm : ErlObject;
  20. /// <summary>
  21. /// Pattern matcher that implements a container of patterns to be
  22. /// matched against a given Erlang term. On successful match, the
  23. /// corresponding action registered with that pattern gets invoked
  24. /// </summary>
  25. public class PatternMatcher : IEnumerable<PatternMatcher.Pattern>
  26. {
  27. #region Local Classes
  28. public struct Pattern
  29. {
  30. public readonly int ID;
  31. public readonly PatternMatchAction Action;
  32. public readonly Erlang.Object Term;
  33. public Pattern(int id, PatternMatchAction b, Erlang.Object p)
  34. {
  35. ID = id; Action = b; Term = p;
  36. }
  37. public Pattern(int id, PatternMatchAction b, string pattern, params object[] args)
  38. {
  39. ID = id; Action = b; Term = Object.Format(pattern, args);
  40. }
  41. }
  42. #endregion
  43. #region Fields
  44. List<Pattern> m_patterns = new List<Pattern>();
  45. int m_lastID = 0;
  46. #endregion
  47. #region Public
  48. /// <summary>
  49. /// Add a matching pattern to the collection
  50. /// </summary>
  51. /// <param name="pattern">Pattern to compile</param>
  52. /// <param name="action">Action to invoke on successful match</param>
  53. /// <returns>ID of the newly added pattern</returns>
  54. public int Add(string pattern, PatternMatchAction action)
  55. {
  56. return Add(ErlObject.Format(pattern), action);
  57. }
  58. /// <summary>
  59. /// Add a matching pattern to the collection
  60. /// </summary>
  61. /// <param name="pattern">Pattern to compile</param>
  62. /// <param name="action">Action to invoke on successful match</param>
  63. /// <param name="args">Arguments used in the pattern</param>
  64. /// <returns>ID of the newly added pattern</returns>
  65. public int Add<TErlTerm>(TErlTerm pattern, PatternMatchAction action) where TErlTerm : ErlObject
  66. {
  67. int id = ++m_lastID;
  68. var pt = new Pattern(id, (p, t, b, args) => action(p, t.Cast<TErlTerm>(), b, args), pattern);
  69. m_patterns.Add(pt);
  70. return id;
  71. }
  72. /// <summary>
  73. /// Add a matching pattern to the collection
  74. /// </summary>
  75. /// <typeparam name="TContext">Type of context passed to action</typeparam>
  76. /// <param name="context">Context passed to action</param>
  77. /// <param name="pattern">Pattern to compile</param>
  78. /// <param name="action">Action to invoke on successful match</param>
  79. /// <returns>ID of the newly added pattern</returns>
  80. public int Add<TContext>(TContext context, string pattern, PatternMatchAction<TContext> action)
  81. {
  82. return Add(context, ErlObject.Format(pattern), action);
  83. }
  84. /// <summary>
  85. /// Add a matching pattern to the collection
  86. /// </summary>
  87. /// <typeparam name="TContext">Type of context passed to action</typeparam>
  88. /// <param name="context">Context passed to action</param>
  89. /// <param name="pattern">Pattern to compile</param>
  90. /// <param name="action">Action to invoke on successful match</param>
  91. /// <returns>ID of the newly added pattern</returns>
  92. public int Add<TContext, TErlTerm>(TContext context, string pattern,
  93. PatternMatchAction<TContext, TErlTerm> action
  94. ) where TErlTerm : ErlObject
  95. {
  96. return Add(context, ErlObject.Format(pattern).Cast<TErlTerm>(), action);
  97. }
  98. /// <summary>
  99. /// Add a matching pattern to the collection
  100. /// </summary>
  101. /// <typeparam name="TContext">Type of context passed to action</typeparam>
  102. /// <param name="context">Context passed to action</param>
  103. /// <param name="action">Action to invoke on successful match</param>
  104. /// <param name="pattern">Compiled pattern containing variables to match</param>
  105. /// <returns>ID of the newly added pattern</returns>
  106. public int Add<TContext>(TContext context, ErlObject pattern, PatternMatchAction<TContext> action)
  107. {
  108. int id = ++m_lastID;
  109. var pt = new Pattern(id, (p, t, b, args) => action(context, p, t, b, args), pattern);
  110. m_patterns.Add(pt);
  111. return id;
  112. }
  113. /// <summary>
  114. /// Add a matching pattern to the collection
  115. /// </summary>
  116. /// <typeparam name="TContext">Type of context passed to action</typeparam>
  117. /// <param name="context">Context passed to action</param>
  118. /// <param name="action">Action to invoke on successful match</param>
  119. /// <param name="pattern">Compiled pattern containing variables to match</param>
  120. /// <returns>ID of the newly added pattern</returns>
  121. public int Add<TContext, TErlTerm>(
  122. TContext context,
  123. TErlTerm pattern,
  124. PatternMatchAction<TContext, TErlTerm> action) where TErlTerm : ErlObject
  125. {
  126. int id = ++m_lastID;
  127. var pt = new Pattern(id, (p, t, b, args) => action(context, p, t.Cast<TErlTerm>(), b, args), pattern);
  128. m_patterns.Add(pt);
  129. return id;
  130. }
  131. /// <summary>
  132. /// Remove pattern from collection given its ID
  133. /// </summary>
  134. public void Remove(int id)
  135. {
  136. int i = m_patterns.FindIndex(d => d.ID == id);
  137. if (i != -1)
  138. m_patterns.RemoveAt(i);
  139. }
  140. /// <summary>
  141. /// Match a term against the patterns in the collection.
  142. /// The first successful match will result in invokation of the action
  143. /// associated with the pattern
  144. /// </summary>
  145. /// <param name="term">Term to match against patterns</param>
  146. /// <returns>ID of the pattern that matched, or -1 if there were no matches</returns>
  147. public int Match<TErlTerm>(TErlTerm term, params object[] args) where TErlTerm : ErlObject
  148. {
  149. var binding = new VarBind();
  150. foreach (var p in m_patterns)
  151. {
  152. if (p.Term.match(term, binding))
  153. {
  154. p.Action(p, term, binding, args);
  155. return p.ID;
  156. }
  157. binding.clear();
  158. }
  159. return -1;
  160. }
  161. /// <summary>
  162. /// Clear the collection of patterns
  163. /// </summary>
  164. public void Clear()
  165. {
  166. m_patterns.Clear();
  167. }
  168. public string PatternsToString
  169. {
  170. get { return (new Erlang.List(m_patterns.Select(p => p.Term).ToArray())).ToString(); }
  171. }
  172. IEnumerator IEnumerable.GetEnumerator()
  173. {
  174. return m_patterns.GetEnumerator();
  175. }
  176. IEnumerator<Pattern> IEnumerable<PatternMatcher.Pattern>.GetEnumerator()
  177. {
  178. return m_patterns.GetEnumerator();
  179. }
  180. #endregion
  181. }
  182. }