Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file was 9842, checked in by gkronber, 11 years ago

#2026 added rudimentary error checking to GPDL parser ATG. Added GPL license headers to all files. Created a first set of unit tests.

File size: 6.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26
27public class Grammar {
28  private class Sequence : List<string> {
29    public override string ToString() {
30      var sb = new StringBuilder();
31      foreach (var e in this) {
32        sb.Append(e).Append(" ");
33      }
34      return sb.ToString();
35    }
36  }
37  private class Alternatives : List<Sequence> {
38    public override string ToString() {
39      var sb = new StringBuilder();
40      if (Count == 0)
41        sb.Append("EPS");
42      else
43        sb.Append(this[0]);
44      foreach (var e in this.Skip(1)) {
45        sb.Append("| ").Append(e);
46      }
47      return sb.ToString();
48    }
49  }
50
51  private Dictionary<string, Alternatives> alternatives = new Dictionary<string, Alternatives>();
52  private Dictionary<string, string> localDefinitions = new Dictionary<string, string>();
53  private Dictionary<string, List<IEnumerable<RuleExprNode>>> seqWithActions = new Dictionary<string, List<IEnumerable<RuleExprNode>>>();
54  public string RootSymbol { get; private set; }
55  public IEnumerable<string> Symbols { get; private set; }
56
57  public Grammar(IEnumerable<SymbolNode> ntSymbols, IEnumerable<SymbolNode> tSymbols, List<RuleNode> ruleNodes) {
58    CheckGrammarConstraints(ntSymbols, tSymbols, ruleNodes);
59    foreach (var ruleNode in ruleNodes) {
60      alternatives[ruleNode.NtSymbol] = ToAlternatives(ruleNode.RuleExpr);
61      localDefinitions[ruleNode.NtSymbol] = ruleNode.LocalCode;
62      seqWithActions[ruleNode.NtSymbol] = ToAlternativesWithActions(ruleNode.RuleExpr);
63    }
64    RootSymbol = ruleNodes.First().NtSymbol;
65    Symbols = ntSymbols.Select(n => n.Ident).Concat(tSymbols.Select(n => n.Ident)).ToList();
66  }
67
68  private List<IEnumerable<RuleExprNode>> ToAlternativesWithActions(RuleExprNode ruleExprNode) {
69    var l = new List<IEnumerable<RuleExprNode>>();
70    var altNode = ruleExprNode as AlternativesNode;
71    if (altNode != null) {
72      l.AddRange(altNode.Alternatives.Select(expr => Flatten(expr)));
73    } else {
74      l.Add(Flatten(ruleExprNode));
75    }
76    return l;
77  }
78
79  private IEnumerable<RuleExprNode> Flatten(RuleExprNode expr) {
80    var seqNode = expr as SequenceNode;
81    var callNode = expr as CallSymbolNode;
82    var actionNode = expr as RuleActionNode;
83    if (seqNode != null) {
84      return seqNode.Sequence;
85    } else if (callNode != null) {
86      return Enumerable.Repeat(callNode, 1);
87    } else if (actionNode != null) {
88      return Enumerable.Repeat(actionNode, 1);
89    } else {
90      throw new NotSupportedException();
91    }
92  }
93
94  public IEnumerable<List<string>> GetAlternatives(string sy) {
95    if (!alternatives.ContainsKey(sy)) return Enumerable.Empty<List<string>>();
96    return alternatives[sy];
97  }
98
99  public string GetLocalDefinitions(string sy) {
100    if (!localDefinitions.ContainsKey(sy)) return string.Empty;
101    return localDefinitions[sy];
102  }
103
104  private Alternatives ToAlternatives(RuleExprNode ruleExprNode) {
105    var alt = new Alternatives();
106    var altNode = ruleExprNode as AlternativesNode;
107    if (altNode != null) {
108      alt.AddRange(altNode.Alternatives.Select(expr => ToSequence(expr)));
109    } else {
110      alt.Add(ToSequence(ruleExprNode));
111    }
112    return alt;
113  }
114
115  private Sequence ToSequence(RuleExprNode ruleExprNode) {
116    var seqNode = ruleExprNode as SequenceNode;
117    var callNode = ruleExprNode as CallSymbolNode;
118    var actionNode = ruleExprNode as RuleActionNode;
119    var seq = new Sequence();
120    if (seqNode != null) {
121      // keep only the nodes refering to symbols
122      seq.AddRange(seqNode.Sequence.OfType<CallSymbolNode>().Select(n => n.Ident));
123    } else if (callNode != null) {
124      seq.Add(callNode.Ident);
125    } else if (actionNode != null) {
126      throw new NotSupportedException();
127    } else {
128      throw new NotSupportedException();
129    }
130    return seq;
131  }
132
133  public IEnumerable<RuleExprNode> GetSequenceWithSemanticActions(string sy, int altIdx) {
134    return seqWithActions[sy][altIdx];
135  }
136
137  // should be checked when reading the grammar?
138  private void CheckGrammarConstraints(IEnumerable<SymbolNode> ntSymbols, IEnumerable<SymbolNode> tSymbols, List<RuleNode> rules) {
139    /* rules:
140     *  - one rule for each non-terminal symbol
141     *  - LL(1)
142     *  - alternatives have to be single-symbol chains
143     *  - all symbols used on the right hand side have to be defined
144     */
145
146    //// only one rule for non-terminal symbols
147    //var dupSymbols = rules.GroupBy(r => r.NtSymbol).Where(g => g.Count() > 1);
148    //if (dupSymbols.Count() > 0) throw new ArgumentException("Two grammar rules for " + dupSymbols.Select(g => g.Key).Aggregate("", (s, s1) => s + ", " + s1));
149
150    //// a rule for all non-terminal symbols
151    //foreach (var ntSymbol in ntSymbols) {
152    //  if (rules.All(r => r.NtSymbol != ntSymbol.Ident)) throw new ArgumentException("No grammar rule for NTSymbol " + ntSymbol);
153    //}
154
155    //foreach (var r in rules) {
156
157    //}
158  }
159
160  public override string ToString() {
161    var sb = new StringBuilder();
162    foreach (var entry in alternatives) {
163      sb.Append(entry.Key).Append(" -> ").AppendLine(entry.Value.ToString());
164    }
165    return sb.ToString();
166  }
167
168}
Note: See TracBrowser for help on using the repository browser.