Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GPDL/HeuristicLab.Problems.GPDL/3.4/Grammar.cs @ 9727

Last change on this file since 9727 was 9430, checked in by gkronber, 11 years ago

initial import of GPDL parser plugin

File size: 5.2 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5
6public class Grammar {
7  private class Sequence : List<string> {
8    public override string ToString() {
9      var sb = new StringBuilder();
10      foreach (var e in this) {
11        sb.Append(e).Append(" ");
12      }
13      return sb.ToString();
14    }
15  }
16  private class Alternatives : List<Sequence> {
17    public override string ToString() {
18      var sb = new StringBuilder();
19      if (Count == 0)
20        sb.Append("EPS");
21      else
22        sb.Append(this[0]);
23      foreach (var e in this.Skip(1)) {
24        sb.Append("| ").Append(e);
25      }
26      return sb.ToString();
27    }
28  }
29
30  private Dictionary<string, Alternatives> alternatives = new Dictionary<string, Alternatives>();
31  private Dictionary<string, string> localDefinitions = new Dictionary<string, string>();
32  private Dictionary<string, List<IEnumerable<RuleExprNode>>> seqWithActions = new Dictionary<string, List<IEnumerable<RuleExprNode>>>();
33  public string RootSymbol { get; private set; }
34  public IEnumerable<string> Symbols { get; private set; }
35
36  public Grammar(IEnumerable<SymbolNode> ntSymbols, IEnumerable<SymbolNode> tSymbols, List<RuleNode> ruleNodes) {
37    CheckGrammarConstraints(ntSymbols, tSymbols, ruleNodes);
38    foreach (var ruleNode in ruleNodes) {
39      alternatives[ruleNode.NtSymbol] = ToAlternatives(ruleNode.RuleExpr);
40      localDefinitions[ruleNode.NtSymbol] = ruleNode.LocalCode;
41      seqWithActions[ruleNode.NtSymbol] = ToAlternativesWithActions(ruleNode.RuleExpr);
42    }
43    RootSymbol = ruleNodes.First().NtSymbol;
44    Symbols = ntSymbols.Select(n => n.Ident).Concat(tSymbols.Select(n => n.Ident)).ToList();
45  }
46
47  private List<IEnumerable<RuleExprNode>> ToAlternativesWithActions(RuleExprNode ruleExprNode) {
48    var l = new List<IEnumerable<RuleExprNode>>();
49    var altNode = ruleExprNode as AlternativesNode;
50    if (altNode != null) {
51      l.AddRange(altNode.Alternatives.Select(expr => Flatten(expr)));
52    } else {
53      l.Add(Flatten(ruleExprNode));
54    }
55    return l;
56  }
57
58  private IEnumerable<RuleExprNode> Flatten(RuleExprNode expr) {
59    var seqNode = expr as SequenceNode;
60    var callNode = expr as CallSymbolNode;
61    var actionNode = expr as RuleActionNode;
62    if (seqNode != null) {
63      return seqNode.Sequence;
64    } else if (callNode != null) {
65      return Enumerable.Repeat(callNode, 1);
66    } else if (actionNode != null) {
67      return Enumerable.Repeat(actionNode, 1);
68    } else {
69      throw new NotSupportedException();
70    }
71  }
72
73  public IEnumerable<List<string>> GetAlternatives(string sy) {
74    if (!alternatives.ContainsKey(sy)) return Enumerable.Empty<List<string>>();
75    return alternatives[sy];
76  }
77
78  public string GetLocalDefinitions(string sy) {
79    if (!localDefinitions.ContainsKey(sy)) return string.Empty;
80    return localDefinitions[sy];
81  }
82
83  private Alternatives ToAlternatives(RuleExprNode ruleExprNode) {
84    var alt = new Alternatives();
85    var altNode = ruleExprNode as AlternativesNode;
86    if (altNode != null) {
87      alt.AddRange(altNode.Alternatives.Select(expr => ToSequence(expr)));
88    } else {
89      alt.Add(ToSequence(ruleExprNode));
90    }
91    return alt;
92  }
93
94  private Sequence ToSequence(RuleExprNode ruleExprNode) {
95    var seqNode = ruleExprNode as SequenceNode;
96    var callNode = ruleExprNode as CallSymbolNode;
97    var actionNode = ruleExprNode as RuleActionNode;
98    var seq = new Sequence();
99    if (seqNode != null) {
100      // keep only the nodes refering to symbols
101      seq.AddRange(seqNode.Sequence.OfType<CallSymbolNode>().Select(n => n.Ident));
102    } else if (callNode != null) {
103      seq.Add(callNode.Ident);
104    } else if (actionNode != null) {
105      throw new NotSupportedException();
106    } else {
107      throw new NotSupportedException();
108    }
109    return seq;
110  }
111
112  public IEnumerable<RuleExprNode> GetSequenceWithSemanticActions(string sy, int altIdx) {
113    return seqWithActions[sy][altIdx];
114  }
115
116  // should be checked when reading the grammar?
117  private void CheckGrammarConstraints(IEnumerable<SymbolNode> ntSymbols, IEnumerable<SymbolNode> tSymbols, List<RuleNode> rules) {
118    /* rules:
119     *  - one rule for each non-terminal symbol
120     *  - LL(1)
121     *  - alternatives have to be single-symbol chains
122     *  - all symbols used on the right hand side have to be defined
123     */
124
125    //// only one rule for non-terminal symbols
126    //var dupSymbols = rules.GroupBy(r => r.NtSymbol).Where(g => g.Count() > 1);
127    //if (dupSymbols.Count() > 0) throw new ArgumentException("Two grammar rules for " + dupSymbols.Select(g => g.Key).Aggregate("", (s, s1) => s + ", " + s1));
128
129    //// a rule for all non-terminal symbols
130    //foreach (var ntSymbol in ntSymbols) {
131    //  if (rules.All(r => r.NtSymbol != ntSymbol.Ident)) throw new ArgumentException("No grammar rule for NTSymbol " + ntSymbol);
132    //}
133
134    //foreach (var r in rules) {
135
136    //}
137  }
138
139  public override string ToString() {
140    var sb = new StringBuilder();
141    foreach (var entry in alternatives) {
142      sb.Append(entry.Key).Append(" -> ").AppendLine(entry.Value.ToString());
143    }
144    return sb.ToString();
145  }
146
147}
Note: See TracBrowser for help on using the repository browser.