1 using System;
  2 using System.Collections;
  3 
  4 namespace soulcm.scm2html
  5 {
  6     public class LinkerVisitor : Visitor
  7     {
  8         public LinkerVisitor() : 
  9             domain(null)currentParser(null)currentRule(null)stage(Stage.addParsers)
 10         {
 11         }
 12         public enum Stage
 13         {
 14             addParsersresolveRules
 15         }
 16         public override void Visit(OptionalParser& parser)
 17         {
 18             parser.Child()->Accept(*this);
 19         }
 20         public override void Visit(KleeneParser& parser)
 21         {
 22             parser.Child()->Accept(*this);
 23         }
 24         public override void Visit(PositiveParser& parser)
 25         {
 26             parser.Child()->Accept(*this);
 27         }
 28         public override void Visit(ExpectationParser& parser)
 29         {
 30             parser.Child()->Accept(*this);
 31         }
 32         public override void Visit(GroupingParser& parser)
 33         {
 34             parser.Child()->Accept(*this);
 35         }
 36         public override void Visit(SequenceParser& parser)
 37         {
 38             parser.Left()->Accept(*this);
 39             parser.Right()->Accept(*this);
 40         }
 41         public override void Visit(AlternativeParser& parser)
 42         {
 43             parser.Left()->Accept(*this);
 44             parser.Right()->Accept(*this);
 45         }
 46         public override void Visit(DifferenceParser& parser)
 47         {
 48             parser.Left()->Accept(*this);
 49             parser.Right()->Accept(*this);
 50         }
 51         public override void Visit(ListParser& parser)
 52         {
 53             parser.Child()->Accept(*this);
 54         }
 55         public override void Visit(ActionParser& parser)
 56         {
 57             parser.Child()->Accept(*this);
 58         }
 59         public override void Visit(NonterminalParser& parser)
 60         {
 61             currentRule->AddNonterminal(&parser);
 62             RuleParser* rule = currentParser->GetRule(parser.RuleName());
 63             parser.SetRule(rule);
 64             if (rule->Parameters().Count() != parser.Arguments().Count())
 65             {
 66                 throw Exception("Rule \'" + ToUtf8(rule->Name()) + "\' takes " + ToString(rule->Parameters().Count()) + " parameters (" + ToString(parser.Arguments().Count()) + " arguments supplied). Detected in parser \'" + ToUtf8(currentParser->Name()) + "\' rule \'" + ToUtf8(currentRule->Name()) + "\'.");
 67             }
 68         }
 69         public override void Visit(RuleParser& parser)
 70         {
 71             currentRule = &parser;
 72             parser.Definition()->Accept(*this);
 73         }
 74         public override void Visit(GrammarParser& parser)
 75         {
 76             if (stage == Stage.addParsers)
 77             {
 78                 domain->AddParser(&parser);
 79             }
 80             else if (stage == Stage.resolveRules)
 81             {
 82                 currentParser = &parser;
 83                 for (const ustring& u : parser.Usings())
 84                 {
 85                     List<ustring> components = u.Split('.');
 86                     if (components.Count() != 2)
 87                     {
 88                         throw Exception("invalid using \'" + ToUtf8(u) + "\' in parser \'" + ToUtf8(parser.Name()) + "\'");
 89                     }
 90                     const ustring& parserName = components[0];
 91                     const ustring& ruleName = components[1];
 92                     GrammarParser* targetParser = domain->GetParser(parserName);
 93                     RuleParser* rule = targetParser->GetRule(ruleName);
 94                     parser.MapRule(rule);
 95                 }
 96                 for (const UniquePtr<RuleParser>& rule : parser.Rules())
 97                 {
 98                     rule->Accept(*this);
 99                 }
100                 for (const Pair<ustringustring>& ruleInfo : parser.RuleInfos())
101                 {
102                     RuleParser* rule = parser.GetRule(ruleInfo.first);
103                     rule->SetInfo(ruleInfo.second);
104                 }
105             }
106         }
107         public override void Visit(ParserFile& parserFile)
108         {
109             for (const UniquePtr<GrammarParser>& parser : parserFile.Parsers())
110             {
111                 parser->Accept(*this);
112             }
113         }
114         public override void Visit(Domain& domain)
115         {
116             this->domain = &domain;
117             stage = Stage.addParsers;
118             for (ParserFile* parserFile : domain.ParserFiles())
119             {
120                 parserFile->Accept(*this);
121             }
122             stage = Stage.resolveRules;
123             for (ParserFile* parserFile : domain.ParserFiles())
124             {
125                 parserFile->Accept(*this);
126             }
127         }
128         private Domain* domain;
129         private Stage stage;
130         private GrammarParser* currentParser;
131         private RuleParser* currentRule;
132     }
133 } // namespace soulcm.scm2html