|
@@ -1,6 +1,7 @@
|
|
|
#include <cassert>
|
|
#include <cassert>
|
|
|
#include <cctype>
|
|
#include <cctype>
|
|
|
#include <charconv>
|
|
#include <charconv>
|
|
|
|
|
+#include <ios>
|
|
|
#include <iostream>
|
|
#include <iostream>
|
|
|
#include <sstream>
|
|
#include <sstream>
|
|
|
#include <string>
|
|
#include <string>
|
|
@@ -105,33 +106,37 @@ static std::string parse_rule(std::istream & in, std::string const & name,
|
|
|
return "";
|
|
return "";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-grammar parse(std::istream & in) {
|
|
|
|
|
- grammar rval;
|
|
|
|
|
|
|
+static auto parse_impl(std::istream & in) {
|
|
|
|
|
+ std::string first_rule;
|
|
|
|
|
+ grammar::rule_store store;
|
|
|
|
|
+
|
|
|
std::string name;
|
|
std::string name;
|
|
|
rule rule;
|
|
rule rule;
|
|
|
|
|
|
|
|
- auto push_rule = [&rval, &name, &rule]() {
|
|
|
|
|
- if (name.empty() || not std::isalpha(name[0])) {
|
|
|
|
|
- // PASS
|
|
|
|
|
- } else if (rval.name_.empty()) {
|
|
|
|
|
- rval.name_ = std::move(name);
|
|
|
|
|
- rval.base_rule_ = std::move(rule);
|
|
|
|
|
- } else {
|
|
|
|
|
- rval.rules_.insert_or_assign(std::move(name), std::move(rule));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ auto push_rule = [&]() {
|
|
|
|
|
+ if (name.empty() || not std::isalpha(name[0])) { return; }
|
|
|
|
|
+ if (first_rule.empty()) { first_rule = name; }
|
|
|
|
|
+
|
|
|
|
|
+ store.insert_or_assign(std::move(name), std::move(rule));
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- bool one_of = false;
|
|
|
|
|
|
|
+ bool is_one_of = false;
|
|
|
std::string token;
|
|
std::string token;
|
|
|
in >> name;
|
|
in >> name;
|
|
|
in >> token; // =
|
|
in >> token; // =
|
|
|
- while (not(token = parse_rule(in, name, rule, one_of)).empty()) {
|
|
|
|
|
|
|
+ while (not(token = parse_rule(in, name, rule, is_one_of)).empty()) {
|
|
|
if (token != name) { push_rule(); }
|
|
if (token != name) { push_rule(); }
|
|
|
name = token;
|
|
name = token;
|
|
|
in >> token; // = OR /=
|
|
in >> token; // = OR /=
|
|
|
- if ((one_of = (token == "/="))) { rule = rval.rules_[name]; }
|
|
|
|
|
|
|
+ if ((is_one_of = (token == "/="))) { rule = store[name]; }
|
|
|
}
|
|
}
|
|
|
push_rule();
|
|
push_rule();
|
|
|
- return rval;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ return std::make_pair(first_rule, std::move(store));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+grammar parse(std::istream & in) {
|
|
|
|
|
+ auto [name, rules] = parse_impl(in);
|
|
|
|
|
+ return grammar(name, rules.extract(name).mapped(), rules);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|