1 using Mercury.Scanning;
2 using Mercury.Interpreting;
5 using System.Collections.Generic;
9 namespace Mercury.Formats.Basic
53 public class RewriteRulesParser<T> : IDisposable
56 private static Tokenizer inputTokenizer = null;
60 private StreamReader source = null;
61 private string filename = null;
62 private Symbol epsilon;
64 private IReadOnlyDictionary<string, InterpreterAction<T>> actions;
65 private IReadOnlyDictionary<string, string> aliases;
82 IEnumerable<InterpreterAction<T>> actions, IReadOnlyDictionary<string,string> aliases = null)
84 if (reader == null)
throw new ArgumentNullException(
"reader");
85 if (actions == null)
throw new ArgumentNullException(
"actions");
88 this.epsilon = epsilon;
90 this.actions = actions.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase);
91 this.aliases = aliases ??
new Dictionary<string, string>();
93 var keywords =
new[] {
"==>" }.Concat(this.aliases.Select(x => x.Key));
95 inputTokenizer =
new Tokenizer(
"@_", keywords, TokenizerOptions.CompiledMatch);
99 IEnumerable<InterpreterAction<T>> actions, IReadOnlyDictionary<string, string> aliases = null)
100 : this(new StreamReader(filename), epsilon, actions, aliases)
101 { this.filename = filename; }
105 private RewriteRuleCollection<T> GetRules(ref
int linenum)
109 var tokens =
new List<Token>();
110 var ruletok =
new List<Token>();
111 var builder =
new RewriteRuleCollectionBuilder<T>();
115 Action parse = delegate()
117 if (ruletok.Count != 0)
118 builder.AddRewriteRule(iep.ParseRewriteRule(ruletok));
124 while((line = source.ReadLine()) != null)
128 tokens.AddRange(inputTokenizer.Tokenize(line));
130 if ((tokens.Count == 0) || (tokens[0].Value ==
"#"))
133 if (tokens.Any(x => (x.Type == TokenType.Keyword) && (x.Value ==
"==>")))
140 ruletok.AddRange(tokens);
143 if (ruletok.Count != 0)
146 return builder.GetCollection();
159 {
return GetRules(ref linenum); }
162 string msg = filename == null
163 ? string.Format(
"In {0}: {1}", linenum, ex.Message)
164 :
string.Format(
"In {0} line {1}: {2}", filename, linenum, ex.Message);
166 throw new FormatException(msg, ex);
172 #region [ IDisposable ]
175 {
if (filename != null) source.Close(); }