Changeset 10067
- Timestamp:
- 10/18/13 21:33:56 (11 years ago)
- Location:
- branches/HeuristicLab.Problems.GPDL
- Files:
-
- 1 added
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/HeuristicLab.Problems.GPDL/CodeGenerator/BruteForceCodeGen.cs
r10062 r10067 1 1 using System; 2 2 using System.Collections.Generic; 3 using System.Diagnostics; 3 4 using System.IO; 4 5 using System.Linq; 5 6 using System.Text; 6 7 using System.Threading.Tasks; 8 using HeuristicLab.Grammars; 9 using Attribute = HeuristicLab.Grammars.Attribute; 7 10 8 11 namespace CodeGenerator { … … 17 20 private string solverTemplate = @" 18 21 namespace ?PROBLEMNAME? { 19 privatestatic class Grammar {22 internal static class Grammar { 20 23 ?GRAMMARCLASSCODE? 21 24 } 22 private sealed class PartiallyProcessedSeq { 23 private PartiallyProcessedSeq parent; 24 private int alt; 25 internal sealed class PartiallyProcessedSeq { 25 26 private IEnumerable<string> remaining; 26 p ublic PartiallyProcessedSeq(IEnumerable<string> alternative) {27 this.remaining = alternative;28 } 29 public PartiallyProcessedSeq CreateAlternative(int p, IEnumerable<string> alternative) {30 var child = new PartiallyProcessedSeq(alternative.Concat(remaining));31 child.parent = this;32 } 33 public bool TryProcessToNextSymbolWithAlternatives(out string symbol) { 34 remaining = remaining.SkipWhile(s=>Grammar.NumberOfAlternatives(s)==0);35 if( remaining.Any()) {36 symbol = remaining.First();37 remaining = remaining.Skip(1);38 return true;39 } else { 40 symbol = null;41 return false;42 }43 27 private IEnumerable<int> path; 28 public PartiallyProcessedSeq(IEnumerable<string> remaining) : this (Enumerable.Empty<int>(), remaining) { 29 } 30 public PartiallyProcessedSeq(IEnumerable<int> path, IEnumerable<string> remaining) { 31 this.path = path; 32 this.remaining = remaining; 33 } 34 35 public bool MoveNext() { 36 if(!remaining.Any()) return false; 37 else remaining = remaining.Skip(1); 38 return true; 39 } 40 41 public string Current { 42 get { 43 return remaining.FirstOrDefault(); 44 } 44 45 } 45 46 public IEnumerable<int> Path { 46 47 get { 47 var cur = this; 48 var List<int> path = new List<int>(); 49 while(cur.parent!=null) { 50 path.Append(cur.p); 51 cur = cur.parent; 52 } 53 return path.Reverse(); 54 } 55 } 48 return path; 49 } 50 } 51 public IEnumerable<string> Remaining { 52 get { 53 return remaining; 54 } 55 } 56 public override string ToString() { 57 return path.Aggregate("""", (str, p) => str + "" "" + p) + "" >> "" + 58 remaining.Aggregate("""", (str, r) => str + "" "" + r); 59 } 60 56 61 } 57 62 public sealed class ?IDENT?Solver { … … 71 76 72 77 private bool IsBetter(double a, double b) { 73 ?MAXIMIZATION? ? a > b : a < b; 74 } 75 76 private IEnumerable<IEnumerator<int>> GeneratePaths() { 78 return ?MAXIMIZATION? ? a > b : a < b; 79 } 80 81 #region path generator (BFS in the grammar to generate solutions) 82 ?PATHGENERATORCODE? 83 #endregion 84 85 private IEnumerable<IEnumerable<int>> GeneratePaths() { 77 86 var queue = new Queue<PartiallyProcessedSeq>(); 78 foreach(var alt in Grammar.GetAlternatives(Grammar.RootSymbol)) 79 queue.Enqueue(new PartiallyProcessedSeq(alt)); 80 81 while(queue.Count > 0) { 87 queue.Enqueue(new PartiallyProcessedSeq(new string[] { Grammar.RootSymbol })); 88 89 while (queue.Count > 0) { 82 90 var e = queue.Dequeue(); 83 string ntSöymbol; 84 if(e.TryProcessToNextNtSymbol(out ntSymbol)) { 85 int i=0; 86 foreach(var alt in Grammar.GetAlternatives(symbol)) { 87 queue.Enqueue(new e.CreateAlternative(i++, alt)); 91 var symb = e.Current; // the next symbol to generate paths for 92 // Console.WriteLine(""Out: "" + e); 93 94 var lastSymbol = !e.MoveNext(); 95 96 if (Grammar.IsTerminal(symb)) { 97 // generate all paths for the terminal 98 if (lastSymbol) { 99 var pathsForSymb = GeneratePathsFor(symb); 100 if (pathsForSymb.Any()) { 101 foreach (var path in GeneratePathsFor(symb)) { 102 yield return e.Path.Concat(path); 103 } 104 } else { 105 yield return e.Path; 106 } 107 } else { 108 var paths = GeneratePathsFor(symb); 109 if(!paths.Any() || paths.Count() == 1) { 110 yield return e.Path; 111 } else { 112 foreach (var path in paths) { 113 var eAlt = new PartiallyProcessedSeq(e.Path.Concat(path), e.Remaining); 114 queue.Enqueue(eAlt); 115 // Console.WriteLine(""In: "" + eAlt); 116 } 117 } 88 118 } 89 119 } else { 90 yield return e.Path; 91 } 92 } 93 } 94 95 ?PATHGENERATORCODE? 120 // non-terminal -> generate alternatives if necessary 121 var alts = Grammar.GetAlternatives(symb); 122 if (alts.Count() == 1) { 123 var eAlt = new PartiallyProcessedSeq(e.Path, alts.Single().Concat(e.Remaining)); 124 queue.Enqueue(eAlt); 125 // Console.WriteLine(""In: "" + eAlt); 126 } else { 127 int i = 0; 128 foreach (var alt in alts) { 129 var eAlt = new PartiallyProcessedSeq(e.Path.Concat(new int[] { i++ }), alt.Concat(e.Remaining)); 130 queue.Enqueue(eAlt); 131 // Console.WriteLine(""In: "" + eAlt); 132 } 133 } 134 } 135 } 136 } 96 137 97 138 private void Start() { 98 139 // generate possible paths through the grammar and evaluate each of them 99 140 var bestF = ?MAXIMIZATION? ? double.NegativeInfinity : double.PositiveInfinity; 141 int n = 0; 100 142 foreach(var path in GeneratePaths()) { 143 var length = path.Count(); 101 144 currentPath = path; 102 145 var f = Calculate(); 146 n++; 103 147 if(IsBetter(f, bestF)) bestF = f; 104 Console.WriteLine(""{0}\t{1}"",bestF, f);105 } 106 } 107 108 private IEnumera tor<int> currentPath;148 if (n%1000 == 0) Console.WriteLine(""{0}\t{1}\t{2}\t{3}"",n, length, bestF, f); 149 } 150 } 151 152 private IEnumerable<int> currentPath; 109 153 110 154 public double Calculate() { 111 try { 112 ?FITNESSFUNCTION? 113 } catch(Exception e) { 114 throw; 115 } 155 ?FITNESSFUNCTION? 116 156 } 117 157 … … 137 177 problemSourceCode.Replace("?PROBLEMNAME?", ast.Name); 138 178 139 // write t o a file for debugging179 // write the source file to disk 140 180 using (var stream = new StreamWriter(ast.Name + ".cs")) { 141 181 stream.WriteLine(problemSourceCode.ToString()); … … 144 184 145 185 private void GenerateProblem(GPDefNode ast, StringBuilder problemSourceCode) { 186 var grammar = CreateGrammarFromAst(ast); 146 187 var problemClassCode = 147 188 solverTemplate 148 .Replace("?MAXIMIZATION?", ast.FitnessFunctionNode.Maximization.ToString() )149 .Replace("?GRAMMARCLASSCODE?", GenerateGrammarClassCode( ast))189 .Replace("?MAXIMIZATION?", ast.FitnessFunctionNode.Maximization.ToString().ToLowerInvariant()) 190 .Replace("?GRAMMARCLASSCODE?", GenerateGrammarClassCode(grammar)) 150 191 .Replace("?IDENT?", ast.Name) 151 192 .Replace("?FITNESSFUNCTION?", ast.FitnessFunctionNode.SrcCode) 152 .Replace("?INTERPRETERSOURCE?", GenerateInterpreterSource( ast))193 .Replace("?INTERPRETERSOURCE?", GenerateInterpreterSource(grammar)) 153 194 .Replace("?INITCODE?", ast.InitCodeNode.SrcCode) 154 195 .Replace("?ADDITIONALCODE?", ast.ClassCodeNode.SrcCode) … … 160 201 } 161 202 162 private string GenerateGrammarClassCode(GPDefNode ast) { 203 private AttributedGrammar CreateGrammarFromAst(GPDefNode ast) { 204 string startSymbolName = ast.Rules.First().NtSymbol; 205 var startSymbolNode = ast.NonTerminals.Single(nt => nt.Ident == startSymbolName); 206 // create startSymbol 207 var g = new AttributedGrammar(new Symbol(startSymbolName, ParseSymbolAttributes(startSymbolNode.FormalParameters))); 208 foreach (var rule in ast.Rules) { 209 // create nt-symbol 210 var ntSymbolName = rule.NtSymbol; 211 var ntSymbolNode = ast.NonTerminals.Single(nt => nt.Ident == ntSymbolName); 212 var attributes = ParseSymbolAttributes(ntSymbolNode.FormalParameters); 213 var ntSymbol = new Symbol(ntSymbolName, attributes); 214 foreach (var alt in GetAlternatives(rule.Alternatives)) { 215 g.AddProductionRule(ntSymbol, alt); 216 } 217 // local initialization code 218 if (!string.IsNullOrEmpty(rule.LocalCode)) g.AddLocalDefinitions(ntSymbol, rule.LocalCode); 219 } 220 return g; 221 } 222 223 private IEnumerable<IAttribute> ParseSymbolAttributes(string formalParameters) { 224 return (from fieldDef in Util.ExtractParameters(formalParameters) 225 select new Attribute(fieldDef.Identifier, fieldDef.Type, AttributeType.Parse(fieldDef.RefOrOut))). 226 ToList(); 227 } 228 229 private IEnumerable<Sequence> GetAlternatives(AlternativesNode altNode) { 230 foreach (var alt in altNode.Alternatives) { 231 yield return GetSequence(alt.Sequence); 232 } 233 } 234 235 private Sequence GetSequence(IEnumerable<RuleExprNode> sequence) { 236 Debug.Assert(sequence.All(s => s is CallSymbolNode || s is RuleActionNode)); 237 var l = new List<ISymbol>(); 238 foreach (var node in sequence) { 239 var callSymbolNode = node as CallSymbolNode; 240 var actionNode = node as RuleActionNode; 241 if (callSymbolNode != null) { 242 l.Add(new Symbol(callSymbolNode.Ident, ParseSymbolAttributes(callSymbolNode.ActualParameter))); 243 } else if (actionNode != null) { 244 l.Add(new SemanticSymbol("SEM", actionNode.SrcCode)); 245 } 246 } 247 return new Sequence(l); 248 } 249 250 251 private string GenerateGrammarClassCode(IGrammar grammar) { 163 252 var sb = new StringBuilder(); 164 253 // RootSymbol 165 sb.AppendFormat("public static string RootSymbol {{ get {{ return {0}; }} }}", ast.Rules.First().NtSymbol).AppendLine(); 254 sb.AppendFormat("public static string RootSymbol {{ get {{ return \"{0}\"; }} }}", grammar.StartSymbol.Name).AppendLine(); 255 sb.AppendLine("public static HashSet<string> terminalSymbols = new HashSet<string>() {"); 256 sb.AppendFormat("{0}", grammar.TerminalSymbols.Aggregate("", (str, symb) => str + "\"" + symb.Name + "\", ")); 257 sb.AppendLine("};"); 166 258 // GetAlternatives 167 259 sb.AppendFormat("public static IEnumerable<IEnumerable<string>> GetAlternatives(string symbol) {{"); 168 260 sb.AppendFormat("switch(symbol) {{ ").AppendLine(); 169 foreach (var ntSymbol in ast.NonTerminals) { 170 sb.AppendFormat("case {0}: {{ ").AppendLine(); 171 var rule = ast.Rules.Single(r => r.NtSymbol == ntSymbol.Ident); 172 sb.AppendFormat("return new string[][] {{}}", rule.RuleExpr); 173 sb.AppendLine("break;}}"); 174 } 175 foreach (var tSymbol in ast.NonTerminals) { 176 177 } 178 sb.AppendFormat(" else {{ throw new InvalidOperationException(\"Unkown symbol: \"+symbol); }}"); 179 sb.AppendLine("}}"); 180 sb.AppendFormat("}}").AppendLine(); 181 261 foreach (var ntSymbol in grammar.NonTerminalSymbols) { 262 sb.AppendFormat("case \"{0}\": {{ ", ntSymbol.Name).AppendLine(); 263 sb.Append("return new string[][] { ").AppendLine(); 264 foreach (var alt in grammar.GetAlternatives(ntSymbol)) { 265 sb.Append("new string[] { ") 266 .Append(alt.Skip(1).Aggregate("\"" + alt.First().Name + "\"", (str, symb) => str + ", \"" + symb.Name + "\"")) 267 .AppendLine("},"); 268 } 269 sb.Append("};"); 270 sb.AppendLine("}"); 271 } 272 sb.AppendLine(" default: { throw new InvalidOperationException(\"Unkown symbol: \"+symbol); }"); 273 sb.AppendLine("}"); 274 sb.AppendLine("}"); 275 276 sb.AppendLine("public static bool IsTerminal(string symbol) {"); 277 sb.AppendFormat("return terminalSymbols.Contains(symbol);"); 278 sb.AppendLine("}"); 182 279 // NumberOfAlternatives 183 sb.AppendFormat( 184 "public static int NumberOfAlternatives(string symbol) {{ return GetAlternatives(symbol).Count(); }}").AppendLine(); 185 return sb.ToString(); 186 } 280 sb.AppendLine( 281 "public static int NumberOfAlternatives(string symbol) { return GetAlternatives(symbol).Count(); }"); 282 return sb.ToString(); 283 } 284 187 285 188 286 // produces helper methods for the attributes of all terminal nodes … … 216 314 private string GeneratePathGeneratorCode(GPDefNode ast) { 217 315 var sb = new StringBuilder(); 218 foreach (var s in ast.NonTerminals ) {316 foreach (var s in ast.NonTerminals.OfType<NonTerminalNode>()) { 219 317 sb.Append(GeneratePathGeneratorCode(s)); 220 318 } 221 foreach (var s in ast.Terminals) { 222 sb.Append(GeneratePathGeneratorCode(s)); 223 } 224 return sb.ToString(); 225 } 226 227 // generates code for a breath-first-search generating all possible paths through the grammar 228 private string GeneratePathGeneratorCode(SymbolNode s) { 229 var sb = new StringBuilder(); 230 231 return sb.ToString(); 232 } 233 234 private string GenerateInterpreterSource(GPDefNode definition) { 235 var sb = new StringBuilder(); 236 // create a grammar instance based on the AST 237 var g = new Grammar(definition.NonTerminals, definition.Terminals, definition.Rules); 319 320 sb.Append(GeneratePathGeneratorCode(ast.Terminals.OfType<TerminalNode>())); 321 return sb.ToString(); 322 } 323 324 private string GeneratePathGeneratorCode(NonTerminalNode s) { 325 var sb = new StringBuilder(); 326 327 return sb.ToString(); 328 } 329 330 // generates a method for the terminal that returns all an IEnumerable of int[] representing each possible combination of values for that terminal 331 private string GeneratePathGeneratorCode(IEnumerable<TerminalNode> terminals) { 332 var sb = new StringBuilder(); 333 sb.AppendLine("private IEnumerable<IEnumerable<int>> GeneratePathsFor(string tSymbol) {"); 334 sb.AppendLine("switch(tSymbol) {"); 335 foreach (var t in terminals) { 336 sb.AppendFormat("case \"{0}\": {{", t.Ident).AppendLine(); 337 if (t.FieldDefinitions.Any()) { 338 int i = 0; 339 // open for loop for each field 340 foreach (var f in t.FieldDefinitions) { 341 sb.AppendFormat("for(int i{0}=0; i{0} < GetAllowed{1}_{2}().Length; i{0}++) {{", i++, t.Ident, f.Identifier) 342 . 343 AppendLine(); 344 } 345 sb.AppendFormat("yield return new int[] {{ {0} }};", 346 Enumerable.Range(0, i).Select(ii => "i" + ii + ", ").Aggregate((str, e) => str + e)); 347 // close braces 348 while (i-- > 0) { 349 sb.AppendLine("}"); 350 } 351 sb.AppendLine("break;"); 352 } else { 353 sb.AppendLine("yield return Enumerable.Empty<int>();"); 354 sb.AppendLine("break;"); 355 } 356 sb.AppendLine("}"); 357 } 358 sb.AppendLine("} }"); 359 return sb.ToString(); 360 } 361 362 private string GenerateInterpreterSource(AttributedGrammar grammar) { 363 var sb = new StringBuilder(); 364 365 238 366 // find formal parameters of root node 239 string formalParameter = definition.NonTerminals.Single(nt => nt.Ident == g.RootSymbol).FormalParameters; 367 var attr = grammar.StartSymbol.Attributes; 368 369 var formalParameter = grammar.StartSymbol.GetAttributeString(); 240 370 // actual parameter are the same as formalparameter only without type identifier 241 var actualParameterEnumerable = 242 Util.ExtractFormalParameters(formalParameter).Select(e => e.RefOrOut + " " + e.Identifier); 243 string actualParameter = string.Empty; 244 // generate a string of actual parameters beginning with: ', a0, a1, ...' 245 if (actualParameterEnumerable.Any()) { 246 foreach (var e in actualParameterEnumerable) { 247 actualParameter += ", " + e; 248 } 249 } 371 string actualParameter; 372 if (attr.Any()) 373 actualParameter = attr.Skip(1).Aggregate(attr.First().AttributeType + " " + attr.First().Name, (str, a) => str + ", " + a.AttributeType + " " + a.Name); 374 else 375 actualParameter = string.Empty; 376 250 377 // generate entry method for evaluation. This is called from the min/max function 251 378 // e.g.: ProgramRoot(ref int a0) { ProgramRoot(rootNode , ref a0); } 252 sb.AppendFormat("void {0}({1}) {{ {0}(currentPath {2}); }}", g.RootSymbol, formalParameter, actualParameter).AppendLine(); 379 sb.AppendFormat("void {0}({1}) {{", grammar.StartSymbol.Name, formalParameter).AppendLine(); 380 sb.AppendLine(" var path = currentPath.GetEnumerator();"); 381 sb.AppendFormat("{0}(path, {1});", grammar.StartSymbol.Name, actualParameter).AppendLine(); 382 sb.AppendLine("if(path.MoveNext()) throw new InvalidOperationException(); // assert that the full path has been processed"); 383 sb.AppendLine("}"); 253 384 254 385 // generate methods for all nonterminals and terminals using the grammar instance 255 foreach (var s in definition.NonTerminals) {256 sb.AppendLine(GenerateInterpreterMethod(g , s));257 } 258 foreach (var s in definition.Terminals) {259 sb.AppendLine(GenerateTerminalInterpreterMethod( (TerminalNode)s));260 } 261 return sb.ToString(); 262 } 263 264 private string GenerateTerminalInterpreterMethod( TerminalNodes) {386 foreach (var s in grammar.NonTerminalSymbols) { 387 sb.AppendLine(GenerateInterpreterMethod(grammar, s)); 388 } 389 foreach (var s in grammar.TerminalSymbols) { 390 sb.AppendLine(GenerateTerminalInterpreterMethod(s)); 391 } 392 return sb.ToString(); 393 } 394 395 private string GenerateTerminalInterpreterMethod(ISymbol s) { 265 396 var sb = new StringBuilder(); 266 397 // if the terminal symbol has attributes then we must create values for these attributes 267 if (!s. FormalParameters.Any())268 sb.AppendFormat("private void {0}(IEnumerator<int> path) {{", s. Ident);398 if (!s.Attributes.Any()) 399 sb.AppendFormat("private void {0}(IEnumerator<int> path) {{", s.Name); 269 400 else 270 sb.AppendFormat("private void {0}(IEnumerator<int> path, {1}) {{", s. Ident, s.FormalParameters);401 sb.AppendFormat("private void {0}(IEnumerator<int> path, {1}) {{", s.Name, s.GetAttributeString()); 271 402 272 403 // each field must match a formal parameter, assign a value for each parameter 273 foreach (var element in s. FieldDefinitions) {404 foreach (var element in s.Attributes) { 274 405 // read next symbol 275 406 sb.AppendLine("path.MoveNext();"); 276 sb.AppendFormat("{0} = Get{1}_{0}Element(path.Current)", element. Identifier, s.Ident).AppendLine(";");277 } 278 sb.AppendLine("}"); 279 return sb.ToString(); 280 } 281 282 private string GenerateInterpreterMethod( Grammar g, SymbolNodes) {283 var sb = new StringBuilder(); 284 if (!s. FormalParameters.Any())285 sb.AppendFormat("private void {0}(IEnumerator<int> path) {{", s. Ident);407 sb.AppendFormat("{0} = Get{1}_{0}Element(path.Current)", element.Name, s.Name).AppendLine(";"); 408 } 409 sb.AppendLine("}"); 410 return sb.ToString(); 411 } 412 413 private string GenerateInterpreterMethod(AttributedGrammar g, ISymbol s) { 414 var sb = new StringBuilder(); 415 if (!s.Attributes.Any()) 416 sb.AppendFormat("private void {0}(IEnumerator<int> path) {{", s.Name); 286 417 else 287 sb.AppendFormat("private void {0}(IEnumerator<int> path, {1}) {{", s. Ident, s.FormalParameters);418 sb.AppendFormat("private void {0}(IEnumerator<int> path, {1}) {{", s.Name, s.GetAttributeString()); 288 419 // generate local definitions 289 sb.AppendLine(g.GetLocalDefinitions(s.Ident)); 290 291 // read next symbol 292 sb.AppendLine("path.MoveNext();"); 420 sb.AppendLine(g.GetLocalDefinitions(s)); 421 293 422 294 423 // if there are alternatives for this symbol -> choose alternative based on the path 295 var alts = g.GetAlternatives(s .Ident);424 var alts = g.GetAlternatives(s); 296 425 if (alts.Count() > 1) { 426 // read next symbol 427 sb.AppendLine("path.MoveNext();"); 297 428 int i = 0; 298 429 sb.AppendLine("switch(path.Current) {"); … … 300 431 foreach (var l in alts) { 301 432 sb.AppendFormat("case {0}: {{ ", i).AppendLine(); 302 foreach (var e in g.GetSequenceWithSemanticActions(s.Ident, i++)) {303 sb.AppendLine(GenerateSourceForAction( e));433 foreach (var altS in g.GetAlternativeWithSemanticActions(s, i++)) { 434 sb.AppendLine(GenerateSourceForAction(altS)); 304 435 } 305 436 sb.AppendLine("break;").AppendLine("}"); 306 437 } 307 sb.AppendLine(" } else throw new System.InvalidOperationException()").AppendLine();438 sb.AppendLine("default: throw new System.InvalidOperationException();").AppendLine("}"); 308 439 } else { 309 foreach (var e in g.GetSequenceWithSemanticActions(s.Ident, 0)) {310 sb.AppendLine(GenerateSourceForAction( e));440 foreach (var altS in g.GetAlternativeWithSemanticActions(s, 0)) { 441 sb.AppendLine(GenerateSourceForAction(altS)); 311 442 } 312 443 } … … 316 447 317 448 // helper for generating calls to other symbol methods 318 private string GenerateSourceForAction(RuleExprNode e) { 319 var action = e as RuleActionNode; 320 var call = e as CallSymbolNode; 449 private string GenerateSourceForAction(ISymbol s) { 450 var action = s as SemanticSymbol; 321 451 if (action != null) { 322 return action. SrcCode + ";";323 } else if (call != null){324 if (! call.ActualParameter.Any())325 return string.Format("{0}(path);", call.Ident);452 return action.Code + ";"; 453 } else { 454 if (!s.Attributes.Any()) 455 return string.Format("{0}(path);", s.Name); 326 456 else 327 return string.Format("{0}(path, {1});", call.Ident, call.ActualParameter); 328 } else { 329 throw new ArgumentException(); 457 return string.Format("{0}(path, {1});", s.Name, s.GetAttributeString()); 330 458 } 331 459 } -
branches/HeuristicLab.Problems.GPDL/CodeGenerator/CodeGenerator.csproj
r10062 r10067 32 32 </PropertyGroup> 33 33 <ItemGroup> 34 <Reference Include="System" /> 34 35 <Reference Include="System.Core" /> 35 36 </ItemGroup> … … 39 40 </ItemGroup> 40 41 <ItemGroup> 42 <ProjectReference Include="..\HeuristicLab.Grammars\3.3\HeuristicLab.Grammars-3.3.csproj"> 43 <Project>{A5452B63-B33B-4F9F-9E81-98B75EDB5612}</Project> 44 <Name>HeuristicLab.Grammars-3.3</Name> 45 </ProjectReference> 41 46 <ProjectReference Include="..\HeuristicLab.Problems.GPDL\3.4\HeuristicLab.Problems.GPDL-3.4.csproj"> 42 47 <Project>{E4EE5AFB-D552-447B-8A16-6CBE7938AF32}</Project> -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/Attribute.cs
r10063 r10067 23 23 24 24 namespace HeuristicLab.Grammars { 25 public sealed class AttributeType { 26 public static readonly AttributeType In = new AttributeType(""); 27 public static readonly AttributeType Out = new AttributeType("out"); 28 public static readonly AttributeType Ref = new AttributeType("ref"); 29 private string attributeType; 30 private AttributeType(string attributeType) { 31 this.attributeType = attributeType; 32 } 33 34 public static AttributeType Parse(string attributeType) { 35 if (string.IsNullOrEmpty(attributeType)) return In; 36 else if (attributeType == "ref") return Ref; 37 else if (attributeType == "out") return Out; 38 else throw new ArgumentException("Unknown attribute type string.", attributeType); 39 } 40 41 public override string ToString() { 42 return attributeType; 43 } 44 }; 45 25 46 public class Attribute : IAttribute { 26 47 public AttributeType AttributeType { get; private set; } 27 48 public string Type { get; private set; } 28 49 public string Name { get; private set; } 50 51 public Attribute(string name, string type) 52 : this(name, type, AttributeType.In) { 53 } 54 55 public Attribute(string name, string type, AttributeType attributeType) { 56 this.Name = name; 57 this.Type = type; 58 this.AttributeType = attributeType; 59 } 60 61 public override string ToString() { 62 return AttributeType + " " + Type + " " + Name; 63 } 29 64 } 30 65 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/AttributedGrammar.cs
r10051 r10067 24 24 using System.Diagnostics; 25 25 using System.Linq; 26 using System.Text.RegularExpressions;27 26 28 27 namespace HeuristicLab.Grammars { 29 28 public class AttributedGrammar : Grammar { 29 private Dictionary<ISymbol, string> localDefinitions = new Dictionary<ISymbol, string>(); 30 private Dictionary<ISymbol, IList<Sequence>> alternatives = new Dictionary<ISymbol, IList<Sequence>>(); 31 30 32 public AttributedGrammar(ISymbol startSymbol) 31 33 : base(startSymbol) { … … 34 36 } 35 37 36 private static Regex ruleExpr = new Regex(@"\s*(?<ntSymbol>\w+)\s*(?<formPar>\<\w+\>)+\s*->\s*(?<alternative>\w+\s*(?<actPar>\<\w+\>)+(?:\s+\w+\s*(?<actPar>\<\w+\>)+)*)(?:\s*\|\s*(?<alternative>\w+\s*(?<formPar>\<\w+\>)+(?:\s+\w+\s*(?<formPar>\<\w+\>)+)*))*"); 37 private static Regex empty = new Regex(@"^\s*$"); 38 public static Grammar FromString(string gStr) { 39 var lines = gStr.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 40 lines = lines.Where(l => !empty.IsMatch(l)).ToArray(); // remove empty lines 38 public IEnumerable<Sequence> GetAlternativesWithSemanticActions(ISymbol ntSymbol) { 39 Debug.Assert(!ntSymbol.Equals(EmptySymbol)); 40 return alternatives[ntSymbol]; 41 } 42 public Sequence GetAlternativeWithSemanticActions(ISymbol ntSymbol, int index) { 43 Debug.Assert(!ntSymbol.Equals(EmptySymbol)); 44 return alternatives[ntSymbol][index]; 45 } 41 46 42 // first line is the rule for the start-symbol43 var m = ruleExpr.Match(lines.First());44 var startSymbol = new Symbol(m.Groups["ntSymbol"].Value); 45 46 var g = new Grammar(startSymbol);47 foreach (var alt in m.Groups["alternative"].Captures) {48 g.AddProductionRule(startSymbol, new Sequence(alt.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => new Symbol(n))));47 public override void AddProductionRule(ISymbol ntSymbol, Sequence production) { 48 base.AddProductionRule(ntSymbol, new Sequence(production.Where(symb => !(symb is SemanticSymbol)).ToList())); 49 50 IList<Sequence> list; 51 if (!alternatives.TryGetValue(ntSymbol, out list)) { 52 list = new List<Sequence>(); 53 alternatives.Add(ntSymbol, list); 49 54 } 50 foreach (var line in lines.Skip(1)) { 51 m = ruleExpr.Match(line); 52 var ntSymbol = new Symbol(m.Groups["ntSymbol"].Value); 53 foreach (var alt in m.Groups["alternative"].Captures) { 54 g.AddProductionRule(ntSymbol, new Sequence(alt.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => new Symbol(n)))); 55 } 56 } 55 // make sure that there is not equivalent production registered already 56 Debug.Assert(!list.Any(s => s.SequenceEqual(production))); 57 57 58 return g;58 list.Add(production); 59 59 } 60 61 public void AddLocalDefinitions(ISymbol ntSymbol, string localDefCode) { 62 Debug.Assert(!ntSymbol.Equals(EmptySymbol)); 63 Debug.Assert(!localDefinitions.ContainsKey(ntSymbol)); 64 65 localDefinitions.Add(ntSymbol, localDefCode); 66 } 67 public string GetLocalDefinitions(ISymbol ntSymbol) { 68 string code; 69 if (localDefinitions.TryGetValue(ntSymbol, out code)) return code; 70 else return string.Empty; 71 } 72 73 74 75 //private static Regex ruleExpr = new Regex(@"\s*(?<ntSymbol>\w+)\s*(?<formPar>\<\w+\>)+\s*->\s*(?<alternative>\w+\s*(?<actPar>\<\w+\>)+(?:\s+\w+\s*(?<actPar>\<\w+\>)+)*)(?:\s*\|\s*(?<alternative>\w+\s*(?<formPar>\<\w+\>)+(?:\s+\w+\s*(?<formPar>\<\w+\>)+)*))*"); 76 //private static Regex empty = new Regex(@"^\s*$"); 77 //public static Grammar FromString(string gStr) { 78 // var lines = gStr.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 79 // lines = lines.Where(l => !empty.IsMatch(l)).ToArray(); // remove empty lines 80 81 // // first line is the rule for the start-symbol 82 // var m = ruleExpr.Match(lines.First()); 83 // var startSymbol = new Symbol(m.Groups["ntSymbol"].Value); 84 85 // var g = new Grammar(startSymbol); 86 // foreach (var alt in m.Groups["alternative"].Captures) { 87 // g.AddProductionRule(startSymbol, new Sequence(alt.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => new Symbol(n)))); 88 // } 89 // foreach (var line in lines.Skip(1)) { 90 // m = ruleExpr.Match(line); 91 // var ntSymbol = new Symbol(m.Groups["ntSymbol"].Value); 92 // foreach (var alt in m.Groups["alternative"].Captures) { 93 // g.AddProductionRule(ntSymbol, new Sequence(alt.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => new Symbol(n)))); 94 // } 95 // } 96 97 // return g; 98 //} 60 99 } 61 100 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/Grammar.cs
r10051 r10067 54 54 } 55 55 56 public v oid AddProductionRule(ISymbol ntSymbol, Sequence production) {56 public virtual void AddProductionRule(ISymbol ntSymbol, Sequence production) { 57 57 Debug.Assert(ntSymbol != EmptySymbol); 58 58 … … 96 96 var g = new Grammar(startSymbol); 97 97 foreach (var alt in m.Groups["alternative"].Captures) { 98 g.AddProductionRule(startSymbol, new Sequence(alt.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => new Symbol(n)) ));98 g.AddProductionRule(startSymbol, new Sequence(alt.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => new Symbol(n)).ToList<ISymbol>())); 99 99 } 100 100 foreach (var line in lines.Skip(1)) { … … 102 102 var ntSymbol = new Symbol(m.Groups["ntSymbol"].Value); 103 103 foreach (var alt in m.Groups["alternative"].Captures) { 104 g.AddProductionRule(ntSymbol, new Sequence(alt.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => new Symbol(n)) ));104 g.AddProductionRule(ntSymbol, new Sequence(alt.ToString().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).Select(n => new Symbol(n)).ToList<ISymbol>())); 105 105 } 106 106 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/HeuristicLab.Grammars-3.3.csproj
r10063 r10067 105 105 <Compile Include="AttributedGrammar.cs" /> 106 106 <Compile Include="Attribute.cs" /> 107 <Compile Include="SemanticSymbol.cs" /> 107 108 <Compile Include="Sequence.cs" /> 108 109 <Compile Include="Test.cs" /> -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/Interfaces/IAttribute.cs
r10051 r10067 20 20 #endregion 21 21 22 using System; 23 22 24 namespace HeuristicLab.Grammars { 23 public enum AttributeType { In, Out, Ref }; 25 24 26 public interface IAttribute { 25 27 AttributeType AttributeType { get; } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/Interfaces/ISymbol.cs
r10051 r10067 20 20 #endregion 21 21 22 using System.Collections.Generic; 23 22 24 namespace HeuristicLab.Grammars { 23 25 public interface ISymbol { 24 26 string Name { get; } 25 IAttribute Attribute { get; } 27 IEnumerable<IAttribute> Attributes { get; } 28 string GetAttributeString(); 26 29 } 27 30 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/Language.cs
r10051 r10067 31 31 public class Language : IEnumerable<IEnumerable<string>> { 32 32 private class PartiallyProcessedSequence { 33 private SequenceterminalSeq;33 private List<ISymbol> terminalSeq; 34 34 private Sequence remainingSeq; 35 35 private IGrammar grammar; … … 38 38 private PartiallyProcessedSequence(PartiallyProcessedSequence parent) { 39 39 this.parent = parent; 40 this.terminalSeq = new Sequence();40 this.terminalSeq = new List<ISymbol>(); 41 41 } 42 42 43 43 public PartiallyProcessedSequence(Sequence seq, IGrammar g) { 44 this.terminalSeq = new Sequence();44 this.terminalSeq = new List<ISymbol>(); 45 45 this.remainingSeq = seq; 46 46 this.grammar = g; … … 59 59 ntSymbol = enumerator.Current; 60 60 61 remainingSeq = new Sequence(remainingSeq.Skip(i + 1) );61 remainingSeq = new Sequence(remainingSeq.Skip(i + 1).ToList()); 62 62 return true; 63 63 } … … 66 66 var p = new PartiallyProcessedSequence(this); 67 67 p.grammar = grammar; 68 p.remainingSeq = new Sequence(seq.Concat(remainingSeq) );68 p.remainingSeq = new Sequence(seq.Concat(remainingSeq).ToList()); 69 69 return p; 70 70 } 71 public SequenceGetSequence() {71 public IList<ISymbol> GetSequence() { 72 72 if (parent == null) return terminalSeq; 73 73 else { 74 return new Sequence(parent.GetSequence().Concat(terminalSeq) );74 return new Sequence(parent.GetSequence().Concat(terminalSeq).ToList()); 75 75 } 76 76 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/Sequence.cs
r10063 r10067 21 21 22 22 using System.Collections.Generic; 23 using System.Collections.ObjectModel; 23 24 using System.Linq; 24 25 using System.Text; 25 26 26 27 namespace HeuristicLab.Grammars { 27 public class Sequence : List<ISymbol> { 28 public Sequence() 29 : base() { 30 } 31 32 public Sequence(IEnumerable<ISymbol> seq) 33 : base() { 34 this.AddRange(seq); 35 } 36 public IEnumerator<ISymbol> GetEnumerator() { 37 return (IEnumerator<ISymbol>)base.GetEnumerator(); 28 public class Sequence : ReadOnlyCollection<ISymbol> { 29 public Sequence(IList<ISymbol> seq) 30 : base(seq) { 38 31 } 39 32 … … 50 43 51 44 public override string ToString() { 52 var b = new StringBuilder(); 53 ForEach(s => b.AppendFormat("{0} ", s)); 54 return b.ToString(); 45 return this.Aggregate("", (str, symb) => str + symb); 55 46 } 56 47 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Grammars/3.3/Symbol.cs
r10063 r10067 21 21 22 22 using System; 23 using System.Collections.Generic; 24 using System.Linq; 25 23 26 namespace HeuristicLab.Grammars { 24 public class Symbol : ISymbol , IEquatable<ISymbol>{27 public class Symbol : ISymbol { 25 28 public string Name { get; private set; } 26 public I Attribute Attribute{ get; private set; }27 public Symbol(string name, I Attribute attribute= null) {29 public IEnumerable<IAttribute> Attributes { get; private set; } 30 public Symbol(string name, IEnumerable<IAttribute> attributes = null) { 28 31 this.Name = name; 29 this.Attribute = attribute; 32 if (attributes != null) this.Attributes = attributes; 33 else this.Attributes = Enumerable.Empty<IAttribute>(); 30 34 } 31 35 32 public bool Equals(ISymbol other) { 33 return Name == other.Name; 36 public string GetAttributeString() { 37 if (!Attributes.Any()) return string.Empty; 38 return Attributes.Skip(1).Aggregate(Attributes.First().ToString(), (str, a) => str + ", " + a.ToString()); 34 39 } 35 40 … … 37 42 if (obj == null) return false; 38 43 if (obj == this) return true; 39 var other = obj as ISymbol;44 var other = obj as Symbol; 40 45 if (other == null) return false; 41 return Equals(other);46 return this.Name == other.Name; // compare names only 42 47 } 43 48 … … 45 50 return Name.GetHashCode(); 46 51 } 52 53 public override string ToString() { 54 return Name + "<" + GetAttributeString() + ">"; 55 } 47 56 } 48 57 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Problems.GPDL/3.4/AST.cs
r9842 r10067 118 118 public string NtSymbol { get; set; } 119 119 public string LocalCode { get; set; } 120 public RuleExprNode RuleExpr{ get; set; }120 public AlternativesNode Alternatives { get; set; } 121 121 } 122 122 … … 124 124 125 125 public class AlternativesNode : RuleExprNode { 126 private List< RuleExprNode> alt;127 public IEnumerable< RuleExprNode> Alternatives { get { return alt; } }126 private List<SequenceNode> alt; 127 public IEnumerable<SequenceNode> Alternatives { get { return alt; } } 128 128 public AlternativesNode() { 129 this.alt = new List< RuleExprNode>();129 this.alt = new List<SequenceNode>(); 130 130 } 131 public void Add( RuleExprNode expr) {131 public void Add(SequenceNode expr) { 132 132 alt.Add(expr); 133 133 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Problems.GPDL/3.4/GPDef.atg
r10049 r10067 148 148 myTNode.Ident = identStr; 149 149 myTNode.FormalParameters = src; 150 myTNode.FieldDefinitions = Util.Extract FormalParameters(src);150 myTNode.FieldDefinitions = Util.ExtractParameters(src); 151 151 .) 152 152 [ "CONSTRAINTS" ConstraintDef<out constraints> … … 188 188 /******************************************************/ 189 189 RuleDef<out RuleNode rule> = (. 190 RuleExprNode expr= null;190 AlternativesNode alternatives = null; 191 191 string identStr = null; 192 192 RuleNode myRule = null; … … 204 204 .) 205 205 ] 206 SynExpr<out expr> '.' (. 207 myRule.RuleExpr = expr; 208 .) 209 . 210 211 /******************************************************/ 212 SynExpr<out RuleExprNode expr > = (. 213 expr = null; 214 AlternativesNode alt = null; 215 .) 216 SynTerm<out expr> (. 206 SynExpr<out alternatives> '.' (. 207 myRule.Alternatives = alternatives; 208 .) 209 . 210 211 /******************************************************/ 212 SynExpr<out AlternativesNode alt > = (. 217 213 alt = new AlternativesNode(); 218 alt.Add(expr); 214 SequenceNode seq = null; 215 .) 216 SynTerm<out seq> (. 217 alt.Add(seq); 219 218 .) 220 219 { 221 '|' SynTerm<out expr> (. alt.Add(expr); expr = alt; .)220 '|' SynTerm<out seq> (. alt.Add(seq); .) 222 221 } 223 222 . 224 223 225 224 /******************************************************/ 226 SynTerm<out RuleExprNode expr> = (. SequenceNode seq = null;expr = null; .)225 SynTerm<out SequenceNode seq> = (. seq = new SequenceNode(); RuleExprNode expr = null; .) 227 226 SynFact<out expr> (. 228 seq = new SequenceNode();229 227 seq.Add(expr); 230 228 .) 231 229 { 232 SynFact<out expr> (. seq.Add(expr); expr = seq;.)230 SynFact<out expr> (. seq.Add(expr); .) 233 231 } 234 232 . -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Problems.GPDL/3.4/HeuristicLab.Problems.GPDL-3.4.csproj
r10065 r10067 106 106 <ItemGroup> 107 107 <Compile Include="AST.cs" /> 108 <Compile Include="Grammar.cs" />109 108 <Compile Include="Parser.cs" /> 110 109 <Compile Include="Scanner.cs" /> -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Problems.GPDL/3.4/Parser.cs
r10065 r10067 216 216 myTNode.Ident = identStr; 217 217 myTNode.FormalParameters = src; 218 myTNode.FieldDefinitions = Util.Extract FormalParameters(src);218 myTNode.FieldDefinitions = Util.ExtractParameters(src); 219 219 220 220 if (la.kind == 15) { … … 227 227 228 228 void RuleDef(out RuleNode rule) { 229 RuleExprNode expr= null;229 AlternativesNode alternatives = null; 230 230 string identStr = null; 231 231 RuleNode myRule = null; … … 249 249 250 250 } 251 SynExpr(out expr);251 SynExpr(out alternatives); 252 252 Expect(13); 253 myRule. RuleExpr = expr;253 myRule.Alternatives = alternatives; 254 254 255 255 } … … 304 304 } 305 305 306 void SynExpr(out RuleExprNode expr ) { 307 expr = null; 308 AlternativesNode alt = null; 309 310 SynTerm(out expr); 306 void SynExpr(out AlternativesNode alt ) { 311 307 alt = new AlternativesNode(); 312 alt.Add(expr); 308 SequenceNode seq = null; 309 310 SynTerm(out seq); 311 alt.Add(seq); 313 312 314 313 while (la.kind == 22) { 315 314 Get(); 316 SynTerm(out expr);317 alt.Add( expr); expr = alt;318 } 319 } 320 321 void SynTerm(out RuleExprNode expr) {322 SequenceNode seq = null;expr = null;315 SynTerm(out seq); 316 alt.Add(seq); 317 } 318 } 319 320 void SynTerm(out SequenceNode seq) { 321 seq = new SequenceNode(); RuleExprNode expr = null; 323 322 SynFact(out expr); 324 seq = new SequenceNode();325 323 seq.Add(expr); 326 324 327 325 while (la.kind == 1 || la.kind == 14) { 328 326 SynFact(out expr); 329 seq.Add(expr); expr = seq;327 seq.Add(expr); 330 328 } 331 329 } -
branches/HeuristicLab.Problems.GPDL/HeuristicLab.Problems.GPDL/3.4/Util.cs
r9872 r10067 25 25 26 26 public class Util { 27 private static Regex formalParameterExpr = new Regex(@"\s*,?\s*((?<refOrOut>(out|ref))\s+)?(?<type>[_\w]*)\s+(?<id>[_\w]*)\s*"); 28 public static IEnumerable<TerminalNode.FieldDefinition> ExtractFormalParameters(string formalParameterSrc) { 29 var match = formalParameterExpr.Match(formalParameterSrc); 27 // simplistic regex for formal parameters, any string of non-whitespace and not comma characters is allowed as a type name 28 private static string refOrOutGroup = @"(?:(?<refOrOut>(out|ref))\s+)"; // "ref " | "out " 29 private static string typeGroup = @"(?:(?<type>[^ ,\f\n\r\t\v]*)\s+)"; 30 private static string identGroup = @"(?<id>[\w]+)\s*"; 31 private static Regex formalParameterExpr = new Regex(@"\s*,?\s*" + refOrOutGroup + "?" + typeGroup + "?" + identGroup, RegexOptions.ECMAScript); 32 public static IEnumerable<TerminalNode.FieldDefinition> ExtractParameters(string formalParameterSrc) { 33 30 34 var matches = formalParameterExpr.Matches(formalParameterSrc); 31 35
Note: See TracChangeset
for help on using the changeset viewer.