Forráskód Böngészése

refactor: cleanup parse() for generic handling

Sam Jaffe 3 hónapja
szülő
commit
4ab4e9a82c
2 módosított fájl, 20 hozzáadás és 16 törlés
  1. 0 1
      include/abnf/grammar.h
  2. 20 15
      src/parser.cxx

+ 0 - 1
include/abnf/grammar.h

@@ -98,7 +98,6 @@ private:
 
 private:
   friend std::ostream & operator<<(std::ostream &, grammar const &);
-  friend grammar parse(std::istream &);
 
   std::string name_;
   rule base_rule_;

+ 20 - 15
src/parser.cxx

@@ -1,6 +1,7 @@
 #include <cassert>
 #include <cctype>
 #include <charconv>
+#include <ios>
 #include <iostream>
 #include <sstream>
 #include <string>
@@ -105,33 +106,37 @@ static std::string parse_rule(std::istream & in, std::string const & name,
   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;
   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;
   in >> name;
   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(); }
     name = token;
     in >> token; // = OR /=
-    if ((one_of = (token == "/="))) { rule = rval.rules_[name]; }
+    if ((is_one_of = (token == "/="))) { rule = store[name]; }
   }
   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);
 }
 }