source: Common/RoseModel.cs

Last change on this file was 11, checked in by chronos, 5 years ago
  • Added: Generic classes for loading MATLAB .mdl files and Rational Rose .cat/.sub files.
File size: 20.8 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.IO;
6using System.Windows.Forms;
7using System.Drawing;
8
9namespace Rose
10{
11 enum ElementType {None, String, Ident, Number, SpecialChar};
12
13 class ParserPos
14 {
15 public int index;
16 public Point pos;
17 }
18
19 class Parser
20 {
21 public string content;
22 int index;
23 int prevIndex;
24 Point pos;
25 Point prevPos;
26 ElementType elementType;
27
28 public char ReadChar()
29 {
30 prevPos = pos;
31 prevIndex = index;
32 char result = content[index];
33 index++;
34 if (result == '\n')
35 {
36 pos.Y++;
37 pos.X = 1;
38 } else pos.X++;
39 return result;
40 }
41
42 public Parser()
43 {
44 Clear();
45 }
46
47 public void Clear()
48 {
49 pos = new Point(1, 1);
50 prevPos = pos;
51 index = 0;
52 }
53
54 public bool IsSpecialChar(char character)
55 {
56 return (character == '(') || (character == ')') || (character == '\r') || (character == '|') || (character == ',');
57 }
58
59 public string ReadNext()
60 {
61 string result = "";
62 bool finished = false;
63 elementType = ElementType.None;
64 while ((index < content.Length) && !finished)
65 {
66 char character = ReadChar();
67 if (elementType == ElementType.String)
68 {
69 if (character == '\"')
70 {
71 finished = true;
72 break;
73 } else
74 {
75 result = result + character;
76 }
77 } else
78 if (elementType == ElementType.Ident)
79 {
80 if (char.IsLetterOrDigit(character) || (character == '_'))
81 {
82 result = result + character;
83 } else
84 {
85 index = prevIndex;
86 pos = prevPos;
87 finished = true;
88 break;
89 }
90 } else
91 if (elementType == ElementType.Number)
92 {
93 if (char.IsNumber(character) || (character == '.'))
94 {
95 result = result + character;
96 }
97 else
98 {
99 index = prevIndex;
100 pos = prevPos;
101 finished = true;
102 break;
103 }
104 }
105 else
106 {
107 if (IsSpecialChar(character))
108 {
109 result = result + character;
110 break;
111 }
112 else
113 if (char.IsWhiteSpace(character))
114 {
115 if (result == "")
116 {
117 }
118 else
119 {
120 break;
121 }
122 }
123 else
124 if (char.IsLetter(character) || (character == '_') || (character == '@'))
125 {
126 result = result + character;
127 elementType = ElementType.Ident;
128 } else
129 if (char.IsNumber(character) || (character == '-'))
130 {
131 result = result + character;
132 elementType = ElementType.Number;
133 }
134 else
135 if (character == '\"')
136 {
137 elementType = ElementType.String;
138 }
139 else
140 {
141 ErrorMessage("Unsupported character '" + character + "'");
142 }
143 }
144 }
145 return result;
146 }
147
148 public bool CheckNext(string text)
149 {
150 ParserPos oldPos = GetPos();
151 string element = ReadNext();
152 SetPos(oldPos);
153 return element == text;
154 }
155
156 public void Expect(string text)
157 {
158 string element = ReadNext();
159 if (element != text)
160 {
161 ErrorMessage("Expected '" + text + "' but '" + element + "' found.");
162 }
163 }
164
165 public string ReadUntil(char character)
166 {
167 string result = "";
168 while ((index < content.Length) && (content[index] != character))
169 {
170 result += ReadChar();
171 }
172 return result;
173 }
174
175 public void ErrorMessage(string Text)
176 {
177 throw new Exception("Parsing error: " + Text + " (" + pos.X.ToString() + "," + pos.Y.ToString() + ")");
178 }
179
180 public ParserPos GetPos()
181 {
182 ParserPos result = new ParserPos();
183 result.pos = pos;
184 result.index = index;
185 return result;
186 }
187
188 public void SetPos(ParserPos parserPos)
189 {
190 pos = parserPos.pos;
191 index = parserPos.index;
192 }
193 }
194
195 class RoseItem
196 {
197 public string name;
198 public RoseItem parent;
199
200 public virtual string GetAsString(int indent = 0)
201 {
202 return string.Concat(Enumerable.Repeat(" ", indent)) + "name: " + name + Environment.NewLine;
203 }
204
205 public virtual List<RoseItem> Find(string text, bool exact = true)
206 {
207 return new List<RoseItem>();
208 }
209 }
210
211 class RoseString: RoseItem
212 {
213 public string value;
214
215 public RoseString(string value)
216 {
217 this.value = value;
218 }
219
220 public override string GetAsString(int indent = 0)
221 {
222 return base.GetAsString(indent) +
223 string.Concat(Enumerable.Repeat(" ", indent)) + "value: " + value + Environment.NewLine;
224 }
225
226 public override List<RoseItem> Find(string text, bool exact = true)
227 {
228 List<RoseItem> result = new List<RoseItem>();
229 if (((text == value) && exact) || ((value.Contains(text)) && !exact)) result.Add(this);
230 return result;
231 }
232 }
233
234 class RosePoint : RoseItem
235 {
236 public Point value;
237
238 public RosePoint()
239 {
240 this.value = new Point(0, 0);
241 }
242
243 public virtual bool Parse(Parser parser)
244 {
245 ParserPos oldPos = parser.GetPos();
246 parser.Expect("(");
247 Int32 output;
248 if(int.TryParse(parser.ReadNext(), out output))
249 value.X = output;
250 if (!parser.CheckNext(","))
251 {
252 parser.SetPos(oldPos);
253 return false;
254 }
255 parser.Expect(",");
256 if (int.TryParse(parser.ReadNext(), out output))
257 value.Y = output;
258 parser.Expect(")");
259 return true;
260 }
261
262 public override string GetAsString(int indent = 0)
263 {
264 return base.GetAsString(indent) +
265 string.Concat(Enumerable.Repeat(" ", indent)) + "pos: " + value.ToString() + Environment.NewLine;
266 }
267 }
268
269 class RoseValue : RoseItem
270 {
271 public string value;
272
273 public RoseValue()
274 {
275 value = "";
276 }
277
278 public bool Parse(Parser parser)
279 {
280 ParserPos oldPos = parser.GetPos();
281 parser.Expect("(");
282 if (!parser.CheckNext("value"))
283 {
284 parser.SetPos(oldPos);
285 return false;
286 }
287 parser.Expect("value");
288 name = parser.ReadNext();
289 if (parser.CheckNext("\r"))
290 {
291 parser.Expect("\r");
292 while (parser.CheckNext("|"))
293 {
294 parser.Expect("|");
295 value += parser.ReadUntil('\r') + Environment.NewLine;
296 parser.Expect("\r");
297 }
298 }
299 else
300 {
301 value = parser.ReadNext();
302 }
303 parser.Expect(")");
304 return true;
305 }
306
307 public override string GetAsString(int indent = 0)
308 {
309 return base.GetAsString(indent) +
310 string.Concat(Enumerable.Repeat(" ", indent)) + "value: " + value + Environment.NewLine;
311 }
312
313 public override List<RoseItem> Find(string text, bool exact = true)
314 {
315 List<RoseItem> result = new List<RoseItem>();
316 if (((text == value) && exact) || ((value.Contains(text)) && !exact)) result.Add(this);
317 return result;
318 }
319 }
320
321 class RoseList : RoseItem
322 {
323 public List<RoseItem> items;
324
325 public RoseList()
326 {
327 items = new List<RoseItem>();
328 }
329
330 public bool Parse(Parser parser)
331 {
332 ParserPos oldPos = parser.GetPos();
333 parser.Expect("(");
334 if (!parser.CheckNext("list"))
335 {
336 parser.SetPos(oldPos);
337 return false;
338 }
339 parser.Expect("list");
340 if (!parser.CheckNext("\r"))
341 {
342 name = parser.ReadNext();
343 }
344 else name = "";
345 if (!parser.CheckNext(")"))
346 {
347 parser.Expect("\r");
348 while (!parser.CheckNext(")"))
349 {
350 RoseObject obj = new RoseObject();
351 if (obj.Parse(parser))
352 {
353 obj.parent = this;
354 items.Add(obj);
355 }
356 else
357 {
358 if (parser.CheckNext("("))
359 {
360 RosePoint point = new RosePoint();
361 point.Parse(parser);
362 point.parent = this;
363 items.Add(point);
364 } else
365 {
366 // Read string
367 RoseString str = new RoseString(parser.ReadNext());
368 }
369 }
370 if (parser.CheckNext(")"))
371 {
372 break;
373 }
374 else
375 {
376 parser.Expect("\r");
377 }
378 }
379 }
380 parser.Expect(")");
381 return true;
382 }
383
384 public override string GetAsString(int indent = 0)
385 {
386 string result = string.Concat(Enumerable.Repeat(" ", indent)) + "list (" + Environment.NewLine;
387 foreach(RoseItem item in items)
388 {
389 result += item.GetAsString(indent + 1);
390 }
391 result = result + string.Concat(Enumerable.Repeat(" ", indent)) + ")" + Environment.NewLine;
392 return result;
393 }
394
395 public override List<RoseItem> Find(string text, bool exact = true)
396 {
397 List<RoseItem> result = new List<RoseItem>();
398 if (name == text) result.Add(this);
399
400 int i = 0;
401 while (i < items.Count)
402 {
403 result.AddRange(items[i].Find(text, exact));
404 i++;
405 }
406 return result;
407 }
408 }
409
410 class RoseObject : RoseItem
411 {
412 public string text; // kind
413 public string text2; // name
414 public string text3;
415 public string reference;
416 public List<KeyValuePair<string, RoseItem>> items;
417
418 public RoseObject()
419 {
420 items = new List<KeyValuePair<string, RoseItem>>();
421 text = "";
422 text2 = "";
423 reference = "";
424 }
425
426 public bool Parse(Parser parser)
427 {
428 ParserPos oldPos = parser.GetPos();
429 if (!parser.CheckNext("("))
430 {
431 parser.SetPos(oldPos);
432 return false;
433 }
434 parser.Expect("(");
435 if (!parser.CheckNext("object"))
436 {
437 parser.SetPos(oldPos);
438 return false;
439 }
440 parser.Expect("object");
441 name = parser.ReadNext();
442 if (!parser.CheckNext("\r"))
443 {
444 text = parser.ReadNext();
445 if (!parser.CheckNext("\r"))
446 {
447 text2 = parser.ReadNext();
448 if ((text2 != "") && (text2[0] == '@'))
449 {
450 reference = text2;
451 text2 = "";
452 } else
453 if (!parser.CheckNext("\r"))
454 {
455 text3 = parser.ReadNext();
456 if ((text3 != "") && (text3[0] == '@'))
457 {
458 reference = text3;
459 text3 = "";
460 }
461 else
462 if (!parser.CheckNext("\r"))
463 {
464 reference = parser.ReadNext();
465 }
466 }
467 }
468 }
469 parser.Expect("\r");
470 while (!parser.CheckNext(")"))
471 {
472 string key = parser.ReadNext();
473 if (parser.CheckNext("("))
474 {
475 RoseObject obj = new RoseObject();
476 if (obj.Parse(parser))
477 {
478 obj.parent = this;
479 items.Add(new KeyValuePair<string, RoseItem>(key, obj));
480 }
481 else
482 {
483 RoseList list = new RoseList();
484 if (list.Parse(parser))
485 {
486 list.parent = this;
487 items.Add(new KeyValuePair<string, RoseItem>(key, list));
488 }
489 else
490 {
491 RoseValue value = new RoseValue();
492 if (value.Parse(parser))
493 {
494 value.parent = this;
495 items.Add(new KeyValuePair<string, RoseItem>(key, value));
496 }
497 else
498 {
499 RosePoint point = new RosePoint();
500 if (point.Parse(parser))
501 {
502 point.parent = this;
503 items.Add(new KeyValuePair<string, RoseItem>(key, point));
504 } else
505 {
506 do
507 {
508 value.value = parser.ReadNext();
509 if (parser.CheckNext(")"))
510 break;
511 } while (true);
512 parser.Expect(")");
513 }
514 }
515 }
516 }
517 } else
518 if (parser.CheckNext("\r"))
519 {
520 RoseString value = new RoseString("");
521 parser.Expect("\r");
522 while(parser.CheckNext("|"))
523 {
524 parser.Expect("|");
525 value.value += parser.ReadUntil('\r') + Environment.NewLine;
526 parser.Expect("\r");
527 }
528
529 items.Add(new KeyValuePair<string, RoseItem>(key, value));
530 } else
531 {
532 RoseString value = new RoseString(parser.ReadNext());
533 items.Add(new KeyValuePair<string, RoseItem>(key, value));
534 }
535
536 if (parser.CheckNext(")"))
537 {
538 break;
539 }
540 else
541 {
542 while (parser.CheckNext("\r"))
543 parser.Expect("\r");
544 }
545 }
546 parser.Expect(")");
547 return true;
548 }
549
550 public override string GetAsString(int indent = 0)
551 {
552 string result = string.Concat(Enumerable.Repeat(" ", indent)) + "object (" + Environment.NewLine;
553 if (name != "") result += string.Concat(Enumerable.Repeat(" ", indent + 1)) + "name: " + name + Environment.NewLine;
554 if (text != "") result += string.Concat(Enumerable.Repeat(" ", indent + 1)) + "text: " + text + Environment.NewLine;
555 if (text2 != "") result += string.Concat(Enumerable.Repeat(" ", indent + 1)) + "text2: " + text2 + Environment.NewLine;
556 if (reference != "") result += string.Concat(Enumerable.Repeat(" ", indent + 1)) + "reference: " + reference + Environment.NewLine;
557 foreach (var item in items)
558 {
559 result += string.Concat(Enumerable.Repeat(" ", indent + 1)) + "key: " + item.Key + " (" + Environment.NewLine +
560 item.Value.GetAsString(indent + 2);
561 result += string.Concat(Enumerable.Repeat(" ", indent + 1)) + ")" + Environment.NewLine;
562 }
563 result = result + string.Concat(Enumerable.Repeat(" ", indent)) + ")" + Environment.NewLine;
564 return result;
565 }
566
567 public override List<RoseItem> Find(string text, bool exact = true)
568 {
569 List<RoseItem> result = new List<RoseItem>();
570 if ((((text == this.name) && exact) || ((this.text.Contains(name)) && !exact)) ||
571 (((text == this.text) && exact) || ((this.text.Contains(text)) && !exact)) ||
572 (((text == this.text2) && exact) || ((this.text2.Contains(text)) && !exact)) ||
573 (((text == this.reference) && exact) || ((this.reference.Contains(text)) && !exact))) result.Add(this);
574
575 int i = 0;
576 while (i < items.Count)
577 {
578 result.AddRange(items[i].Value.Find(text, exact));
579 i++;
580 }
581 return result;
582 }
583 }
584
585 class RoseModel
586 {
587 public List<RoseObject> objects;
588
589 public RoseModel()
590 {
591 objects = new List<RoseObject>();
592 }
593
594 public void ParseFile(string fileName)
595 {
596 //try
597 //{
598 objects.Clear();
599 Parser parser = new Parser();
600 parser.content = File.ReadAllText(fileName, Encoding.Default);
601
602 // Skip zero size files. They are probably files not accessible from current ClearCase view.
603 if (parser.content.Length == 0) return;
604
605 do
606 {
607 RoseObject obj = new RoseObject();
608 if (parser.CheckNext("\r")) parser.Expect("\r");
609 obj.Parse(parser);
610 objects.Add(obj);
611 parser.Expect("\r");
612 } while (parser.CheckNext("\r"));
613 //} catch (Exception e)
614 //{
615 // MessageBox.Show(e.ToString(), "Error");
616 //}
617 }
618
619 public string GetAsString()
620 {
621 string result = "";
622 foreach (var obj in objects)
623 {
624 result += obj.GetAsString() + Environment.NewLine;
625 }
626 return result;
627 }
628
629 public List<RoseItem> Find(string text, bool exact = true)
630 {
631 List<RoseItem> result = new List<RoseItem>();
632 int i = 0;
633 while (i < objects.Count)
634 {
635 result.AddRange(objects[i].Find(text, exact));
636 i++;
637 }
638 return result;
639 }
640 }
641}
Note: See TracBrowser for help on using the repository browser.