Mercury.Formats library 1.0 The library provides format parsers for the Mercury library components.

- Main Page
- Packages
- Classes
- Files

- File List

All Classes Namespaces Files Functions Properties
EntityParser.cs
Go to the documentation of this file.
1 using Mercury;
2 using Mercury.Scanning;
3 using Mercury.Interpreting;
4 using Mercury.Syntax;
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8
9 namespace Mercury.Formats.Basic
10 {
11 //=============================================================================
12 // GrammarEntityParser
13 //=============================================================================
14
18 public class GrammarEntityParser
19 {
20
21 //--[ Constructors ]-------------------------------------------------
22
28 public GrammarEntityParser(Symbol epsilon)
29 {
30 if (epsilon == null || epsilon.Type != SymbolType.Epsilon)
31 throw new ArgumentException("Required epsilon symbol for Grammar Entity Parser");
32
33 Epsilon = epsilon;
34 }
35
36 //--[ Methods ]------------------------------------------------------
37
41 public Symbol ParseSymbol(Token token)
42 {
43 FmtChk.AssertNotNull(token, "token");
44
45 string sname = token.Value.Unescape();
46 SymbolType stype = sname == Epsilon.Name ? SymbolType.Epsilon : SymbolType.Terminal | SymbolType.Nonterminal;
47
48 return new Symbol(sname, stype);
49 }
50
59 public Rule ParseRule(IList<Token> tokens)
60 {
61 FmtChk.AssertNotNull(tokens, "tokens");
62 FmtChk.AssertCount(3, tokens, "Not a rule");
63 FmtChk.AssertToken(tokens[1], "->", "Operator '->' missing");
64
65 Symbol lhs = ParseSymbol(tokens[0]);
66
67 return new Rule(lhs, tokens.Skip(2).Select(x => ParseSymbol(x)));
68 }
69
76 public IList<Rule> ParseMultiRule(IList<Token> tokens)
77 {
78 FmtChk.AssertNotNull(tokens, "tokens");
79 FmtChk.AssertCount(3, tokens, "Not a rule");
80
81 var prefix = tokens.Take(2).ToArray();
82 var rhs = new List<Token>();
83 var result = new List<Rule>();
84
85 foreach(Token token in tokens.Skip(2))
86 if (token.Value == "|")
87 {
88 result.Add(ParseRule(prefix.Concat(rhs).ToList()));
89 rhs.Clear();
90 }
91 else
92 rhs.Add(token);
93
94 result.Add(ParseRule(prefix.Concat(rhs).ToList()));
95 return result;
96 }
97
104 public Edge ParseEdge(IList<Token> tokens)
105 {
106 FmtChk.AssertNotNull(tokens, "tokens");
107 FmtChk.AssertCount(8, tokens, "Not an edge");
108 FmtChk.AssertPattern(new[] { "(", null, ",", null, ")", null, "->" }, tokens, x => x.Value);
109
110 int l = int.Parse(tokens[1].Value);
111 int r = int.Parse(tokens[3].Value);
112 int d = -1;
113
114 List<Token> lhs = new List<Token> { tokens[5], tokens[6] };
115 List<Token> rhs = new List<Token>();
116
117 for (int tokix = 7; tokix < tokens.Count; ++tokix)
118 if (tokens[tokix].Value == ".")
119 {
120 FmtChk.AssertTrue(d == -1, "Too many '.' markers in the edge");
121 d = tokix - 7;
122 }
123 else
124 rhs.Add(tokens[tokix]);
125
126 if (rhs.Count == 0)
127 rhs.Add(new Token(Epsilon.Name, TokenType.String, 0));
128
129 FmtChk.AssertFalse(d == -1, "Edge mark '.' missing");
130
131 return new Edge(ParseRule(lhs.Concat(rhs).ToList()), d, l, r);
132 }
133
134 public Symbol Epsilon { get; private set; }
135 }
136
137 //=============================================================================
138 // InterpreterEntityParser
139 //=============================================================================
140
149 public class InterpreterEntityParser<T> where T : class
150 {
151 //--[ Internals ]----------------------------------------------------
152
153 internal class AlternativeData
154 {
155 public AlternativeData()
156 {
157 WildcardSymbols = SymbolType.None;
158 Symbols = new List<Symbol>();
159 }
160
161 public SymbolType WildcardSymbols { get; set; }
162 public List<Symbol> Symbols { get; set; }
163 }
164
165 private GrammarEntityParser gep;
166 private IReadOnlyDictionary<string, InterpreterAction<T>> actions;
167 private IReadOnlyDictionary<string, string> aliases;
168
169 //--[ Constructors ]-------------------------------------------------
170
171 public InterpreterEntityParser(Symbol epsilon,
172 IReadOnlyDictionary<string, InterpreterAction<T>> actions,
173 IReadOnlyDictionary<string, string> aliases)
174 {
175 this.gep = new GrammarEntityParser(epsilon);
176 this.actions = actions;
177 this.aliases = aliases;
178 }
179
180 //--[ Methods ]------------------------------------------------------
181
187 public IElement ParseElement(IList<Token> tokens, int start, out int end)
188 {
189 FmtChk.AssertNotNull(tokens, "tokens");
190 FmtChk.AssertCount(start + 1, tokens);
191
192 if (tokens[start].Quoted) return ParseConstant(tokens, start, out end);
193
194 switch (tokens[start].Value)
195 {
196 case "?": end = start + 1;
197 return new Variable();
198 case "#": return ParseVariable (tokens, start, out end);
199 case "*": return ParseWildcard (tokens, start, out end);
200 case "[": return ParseStructure(tokens, start, out end);
201 default: return ParseConstant (tokens, start, out end);
202 }
203 }
204
219 public Constant ParseConstant(IList<Token> tokens, int start, out int end)
220 {
221 FmtChk.AssertNotNull(tokens, "tokens");
222 FmtChk.AssertCount(start + 1, tokens, "Not a constant");
223
224 List<Symbol> smlist = new List<Symbol>();
225 SymbolType mask = SymbolType.None;
226 while (tokens[start].Value != ":")
227 {
228 var name = tokens[start].Value.Unescape();
229 if (name == gep.Epsilon.Name)
230 mask |= SymbolType.Epsilon;
231 else
232 smlist.Add(new Symbol(name));
233
234 if ((start + 2 < tokens.Count)
235 && (tokens[start + 2].Value != "|")
236 && (tokens[start + 1].Value == "|"))
237 start += 2;
238 else
239 {
240 ++start;
241 break;
242 }
243 }
244
245 end = start;
246
247 if ((start + 1 < tokens.Count) && (tokens[start].Value == ":"))
248 {
249 foreach(char c in tokens[start + 1].Value)
250 {
251 switch (c)
252 {
253 case 'N': mask |= SymbolType.Nonterminal; break;
254 case 'T': mask |= SymbolType.Terminal; break;
255 case 'e': mask |= SymbolType.Epsilon; break;
256 default: throw new FormatException(string.Format("Unexpected flag {0} in an alternative", c));
257 }
258 }
259 end = start + 2;
260 }
261
262 return new Constant(mask, smlist);
263 }
264
276 public Variable ParseVariable(IList<Token> tokens, int start, out int end)
277 {
278 FmtChk.AssertNotNull(tokens, "tokens");
279 FmtChk.AssertCount(start + 2, tokens, "Not a variable");
280 FmtChk.AssertFalse(tokens[start].Quoted, "Not a variable");
281 FmtChk.AssertToken(tokens[start], "#");
282
283 if (tokens[start + 1].Position != tokens[start].Position + 1)
284 throw new FormatException(string.Format("Name of variable expected at position {0}", tokens[start].Position + 1));
285
286 var varname = tokens[start + 1].Value;
287 end = start + 2;
288
289 Constant cst = null;
290 if ((start + 2 < tokens.Count) && (tokens[start + 2].Value == ":"))
291 cst = ParseConstant(tokens, start + 3, out end);
292 else
293 cst = new Constant(SymbolType.Any, new Symbol[0]);
294
295 return new Variable(varname, cst.SymbolMask, cst.Symbols);
296 }
297
309 public Wildcard ParseWildcard(IList<Token> tokens, int start, out int end)
310 {
311 FmtChk.AssertNotNull(tokens, "tokens");
312 FmtChk.AssertCount(start + 1, tokens, "Not a wildcard");
313 FmtChk.AssertFalse(tokens[start].Quoted, "Not a wildcard");
314 FmtChk.AssertToken(tokens[start], "*");
315
316 end = ++start;
317
318 string name = null;
319 if ((start < tokens.Count) && (tokens[start].Position == tokens[start - 1].Position + 1))
320 {
321 name = tokens[start].Value;
322 ++start;
323 ++end;
324 }
325
326 Constant cst = null;
327 cst = ((start < tokens.Count) && (tokens[start].Value == ":"))
328 ? ParseConstant(tokens, start + 1, out end)
329 : new Constant(SymbolType.Any, new Symbol[0]);
330
331 return new Wildcard(name, cst.SymbolMask, cst.Symbols);
332 }
333
343 public Structure ParseStructure(IList<Token> tokens, int start, out int end)
344 {
345 FmtChk.AssertNotNull(tokens, "tokens");
346 FmtChk.AssertCount(start + 1, tokens, "Not a structure");
347 FmtChk.AssertFalse(tokens[start].Quoted, "Not a structure");
348 FmtChk.AssertToken(tokens[start], "[");
349
350 List<IElement> elements = new List<IElement>();
351 int ix = start + 1;
352 while ((ix < tokens.Count) && (tokens[ix].Value != "]"))
353 elements.Add(ParseElement(tokens, ix, out ix));
354
355 end = ix + 1;
356 FmtChk.AssertTrue(ix < tokens.Count, "Expected ']' at the end of strucutre");
357 FmtChk.AssertNotEmpty(elements, "Empty structure is not valid");
358
359 return new Structure(elements[0], elements.Skip(1));
360 }
361
369 public IFormalParameter ParseParameter(IList<Token> tokens, int start, out int end)
370 {
371 FmtChk.AssertNotNull(tokens, "tokens");
372 FmtChk.AssertCount(start + 1, tokens, "Not a parameter");
373
374 end = start + 1;
375 if (tokens[start].Quoted)
376 return ConstantParameter.StringParameter(tokens[start].Value.Unescape());
377
378 switch (tokens[start].Value)
379 {
380 case "(": return ParseActionCall(tokens, start, out end);
381
382 case "#":
383 FmtChk.AssertCount(start + 2, tokens);
384
385 end = start + 2;
386 return new VariableParameter(tokens[start + 1].Value);
387
388 default:
389 end = start + 1;
390 return ConstantParameter.AutoCreate(tokens[start].Value.Unescape());
391 }
392 }
393
404 public ActionCall<T> ParseActionCall(IList<Token> tokens, int start, out int end)
405 {
406 FmtChk.AssertNotNull(tokens, "tokens");
407 FmtChk.AssertCount(start + 3, tokens, "Not an action");
408 FmtChk.AssertFalse(tokens[start].Quoted, "Not an action");
409 FmtChk.AssertToken(tokens[start], "(");
410
411 string name = name = tokens[start + 1].Value;
412
413 InterpreterAction<T> action;
414 if (!actions.TryGetValue(name, out action))
415 {
416 string alias = null;
417 if (!aliases.TryGetValue(name, out alias) || !actions.TryGetValue(alias, out action))
418 throw new FormatException(string.Format("Action '{0}' not found", name));
419 }
420
421 IFormalParameter[] fparams = ParseParameters(tokens, start + 2, out end);
422 if (end >= tokens.Count || tokens[end].Value != ")")
423 throw new ArgumentException("Expected ')' at the end of action call");
424 ++end;
425
426 return new ActionCall<T>(action, fparams);
427 }
428
436 public IFormalParameter[] ParseParameters(IList<Token> tokens, int start, out int end)
437 {
438 FmtChk.AssertNotNull(tokens, "tokens");
439 FmtChk.AssertCount(start + 1, tokens, "No parameters");
440
441 List<IFormalParameter> fparams = new List<IFormalParameter>();
442
443 int fst = end = start;
444 while ((start < tokens.Count) && (tokens[start].Quoted || (tokens[start].Value != ")")))
445 {
446 fparams.Add(ParseParameter(tokens, start, out end));
447 start = end;
448 };
449
450 return fparams.ToArray();
451 }
452
461 public RewriteRule<T> ParseRewriteRule(IList<Token> tokens)
462 {
463 FmtChk.AssertNotNull(tokens, "tokens");
464 FmtChk.AssertNotEmpty(tokens);
465
466 int arrow = -1;
467 for (int ix = 0; (arrow == -1) && (ix < tokens.Count); ++ix)
468 if ((tokens[ix].Type == TokenType.Keyword) && (tokens[ix].Value == "==>"))
469 arrow = ix;
470
471 int end;
472 FmtChk.AssertTrue(arrow != -1, "Missing '==>' in rule");
473
474 Structure lhs = ParseElement(tokens, 0, out end) as Structure;
475 FmtChk.AssertNotNull(lhs, "Missing LHS structure");
476 FmtChk.AssertTrue(end == arrow, "Invalid LHS structure");
477
478 ActionCall<T> rhs = ParseActionCall(tokens, arrow + 1, out end);
479 if (end != tokens.Count) throw new ArgumentException(string.Format("Unexpected token '{0}' after action", tokens[end].Value));;
480
481 return new RewriteRule<T>(lhs, rhs);
482 }
483 }
484 }
Mercury.Formats.Basic.InterpreterEntityParser< T >.InterpreterEntityParser
InterpreterEntityParser(Symbol epsilon, IReadOnlyDictionary< string, InterpreterAction< T >> actions, IReadOnlyDictionary< string, string > aliases)
Definition: EntityParser.cs:171
Mercury.Formats.Basic.GrammarEntityParser.ParseSymbol
Symbol ParseSymbol(Token token)
Parses a symbol from a token.
Definition: EntityParser.cs:41
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseParameters
IFormalParameter[] ParseParameters(IList< Token > tokens, int start, out int end)
Parses the parameters of an action call.
Definition: EntityParser.cs:436
Mercury.Formats.Basic.GrammarEntityParser.GrammarEntityParser
GrammarEntityParser(Symbol epsilon)
Initializes a new instance of the GrammarEntityParser class.
Definition: EntityParser.cs:28
Mercury.Formats.Basic.GrammarEntityParser.ParseMultiRule
IList< Rule > ParseMultiRule(IList< Token > tokens)
Parses the multi-rule. It is of the form A -> RHS0 | RHS1 | ... where A -> RHS0 and A -> RHS1 are val...
Definition: EntityParser.cs:76
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseElement
IElement ParseElement(IList< Token > tokens, int start, out int end)
Parses the element.
Definition: EntityParser.cs:187
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseStructure
Structure ParseStructure(IList< Token > tokens, int start, out int end)
Parses the structure. It is of the form [Root Elements...] where Root is an Mercury.Interpreting.Alternative and Elements is a list of elements.
Definition: EntityParser.cs:343
Mercury.Formats.Basic.GrammarEntityParser.ParseRule
Rule ParseRule(IList< Token > tokens)
Parses the rule. The rule is of the format A -> X Y Z... where A is a nonterminal symbols and X...
Definition: EntityParser.cs:59
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseWildcard
Wildcard ParseWildcard(IList< Token > tokens, int start, out int end)
Parses the wildcard. It is of the form *name:alternative. The same conditions hold as in ParseVariabl...
Definition: EntityParser.cs:309
Mercury.Formats.Basic.GrammarEntityParser.ParseEdge
Edge ParseEdge(IList< Token > tokens)
Parses the edge. It is of the form (l, r) A -> alpha . beta where l <= r and A -> alpha beta is a val...
Definition: EntityParser.cs:104
Mercury.Formats.Basic.GrammarEntityParser
Class for parsing grammar entities used in Mercury.
Definition: EntityParser.cs:18
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseParameter
IFormalParameter ParseParameter(IList< Token > tokens, int start, out int end)
Parses the parameter. It might be a constant or an action call.
Definition: EntityParser.cs:369
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseActionCall
ActionCall< T > ParseActionCall(IList< Token > tokens, int start, out int end)
Parses the action call. It is of the form (f x y z...) where f is a name of an action and x...
Definition: EntityParser.cs:404
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseConstant
Constant ParseConstant(IList< Token > tokens, int start, out int end)
Parses the constant. It is of the form symbols:mask where symbols is a list of symbols separated by |...
Definition: EntityParser.cs:219
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseRewriteRule
RewriteRule< T > ParseRewriteRule(IList< Token > tokens)
Parses the rewrite rule. It is of the form LHS ==> RHS where LHS is a Mercury.Interpreting.Structure and RHS is an Mercury.Interpreting.ActionCall{T}.
Definition: EntityParser.cs:461
Mercury.Formats.Basic.InterpreterEntityParser< T >.ParseVariable
Variable ParseVariable(IList< Token > tokens, int start, out int end)
Parses the variable. It is of the form #name:alternative where name is a variable name and alternativ...
Definition: EntityParser.cs:276