Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/18/13 21:33:56 (11 years ago)
Author:
gkronber
Message:

#2026 worked on brute force solver for GPDL problems.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/HeuristicLab.Problems.GPDL/CodeGenerator/BruteForceCodeGen.cs

    r10062 r10067  
    11using System;
    22using System.Collections.Generic;
     3using System.Diagnostics;
    34using System.IO;
    45using System.Linq;
    56using System.Text;
    67using System.Threading.Tasks;
     8using HeuristicLab.Grammars;
     9using Attribute = HeuristicLab.Grammars.Attribute;
    710
    811namespace CodeGenerator {
     
    1720    private string solverTemplate = @"
    1821namespace ?PROBLEMNAME? {
    19   private static class Grammar {
     22  internal static class Grammar {
    2023    ?GRAMMARCLASSCODE?
    2124  }
    22   private sealed class PartiallyProcessedSeq {
    23     private PartiallyProcessedSeq parent;
    24     private int alt;
     25  internal sealed class PartiallyProcessedSeq {
    2526    private IEnumerable<string> remaining;
    26     public 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      }
    4445    }
    4546    public IEnumerable<int> Path {
    4647      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
    5661  }
    5762  public sealed class ?IDENT?Solver {
     
    7176
    7277    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() {
    7786      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) {
    8290        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            }
    88118          }
    89119        } 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    }
    96137
    97138    private void Start() {
    98139      // generate possible paths through the grammar and evaluate each of them   
    99140      var bestF = ?MAXIMIZATION? ? double.NegativeInfinity : double.PositiveInfinity;
     141      int n = 0;
    100142      foreach(var path in GeneratePaths()) {
     143        var length = path.Count();
    101144        currentPath = path;
    102145        var f = Calculate();
     146        n++;
    103147        if(IsBetter(f, bestF)) bestF = f;
    104         Console.WriteLine(""{0}\t{1}"",bestF, f);
    105       }
    106     }
    107 
    108     private IEnumerator<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;
    109153
    110154    public double Calculate() {
    111       try {
    112         ?FITNESSFUNCTION?
    113       } catch(Exception e) {
    114         throw;
    115       }
     155      ?FITNESSFUNCTION?
    116156    }
    117157
     
    137177      problemSourceCode.Replace("?PROBLEMNAME?", ast.Name);
    138178
    139       // write to a file for debugging
     179      // write the source file to disk
    140180      using (var stream = new StreamWriter(ast.Name + ".cs")) {
    141181        stream.WriteLine(problemSourceCode.ToString());
     
    144184
    145185    private void GenerateProblem(GPDefNode ast, StringBuilder problemSourceCode) {
     186      var grammar = CreateGrammarFromAst(ast);
    146187      var problemClassCode =
    147188        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))
    150191          .Replace("?IDENT?", ast.Name)
    151192          .Replace("?FITNESSFUNCTION?", ast.FitnessFunctionNode.SrcCode)
    152           .Replace("?INTERPRETERSOURCE?", GenerateInterpreterSource(ast))
     193          .Replace("?INTERPRETERSOURCE?", GenerateInterpreterSource(grammar))
    153194          .Replace("?INITCODE?", ast.InitCodeNode.SrcCode)
    154195          .Replace("?ADDITIONALCODE?", ast.ClassCodeNode.SrcCode)
     
    160201    }
    161202
    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) {
    163252      var sb = new StringBuilder();
    164253      // 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("};");
    166258      // GetAlternatives
    167259      sb.AppendFormat("public static IEnumerable<IEnumerable<string>> GetAlternatives(string symbol) {{");
    168260      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("}");
    182279      // 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
    187285
    188286    // produces helper methods for the attributes of all terminal nodes
     
    216314    private string GeneratePathGeneratorCode(GPDefNode ast) {
    217315      var sb = new StringBuilder();
    218       foreach (var s in ast.NonTerminals) {
     316      foreach (var s in ast.NonTerminals.OfType<NonTerminalNode>()) {
    219317        sb.Append(GeneratePathGeneratorCode(s));
    220318      }
    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
    238366      // 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();
    240370      // 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
    250377      // generate entry method for evaluation. This is called from the min/max function
    251378      // 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("}");
    253384
    254385      // 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(TerminalNode s) {
     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) {
    265396      var sb = new StringBuilder();
    266397      // 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);
    269400      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());
    271402
    272403      // 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) {
    274405        // read next symbol
    275406        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, SymbolNode s) {
    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);
    286417      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());
    288419      // 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
    293422
    294423      // 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);
    296425      if (alts.Count() > 1) {
     426        // read next symbol
     427        sb.AppendLine("path.MoveNext();");
    297428        int i = 0;
    298429        sb.AppendLine("switch(path.Current) {");
     
    300431        foreach (var l in alts) {
    301432          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));
    304435          }
    305436          sb.AppendLine("break;").AppendLine("}");
    306437        }
    307         sb.AppendLine("} else throw new System.InvalidOperationException()").AppendLine();
     438        sb.AppendLine("default: throw new System.InvalidOperationException();").AppendLine("}");
    308439      } 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));
    311442        }
    312443      }
     
    316447
    317448    // 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;
    321451      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);
    326456        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());
    330458      }
    331459    }
Note: See TracChangeset for help on using the changeset viewer.