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