Browse Source

feat: add a grammar_group option for cases like rfc3339

Sam Jaffe 3 tháng trước cách đây
mục cha
commit
17924a005a
5 tập tin đã thay đổi với 30 bổ sung6 xóa
  1. 5 0
      include/abnf/forward.h
  2. 8 2
      include/abnf/grammar.h
  3. 4 0
      src/grammar.cxx
  4. 8 3
      src/io.cxx
  5. 5 1
      src/parser.cxx

+ 5 - 0
include/abnf/forward.h

@@ -22,12 +22,17 @@ struct rule;
 using rule_part =
     std::variant<literal, char_range, reference, repeated, one_of>;
 
+class grammar_base;
+class grammar_group;
 class grammar;
 
 grammar parse(std::istream & in);
 grammar parse(std::istream && in);
+grammar_group parse_group(std::istream & in);
+grammar_group parse_group(std::istream && in);
 
 std::ostream & operator<<(std::ostream & os, rule const & rule);
+std::ostream & operator<<(std::ostream & os, grammar_base const & grammar);
 std::ostream & operator<<(std::ostream & os, grammar const & grammar);
 
 template <typename T>

+ 8 - 2
include/abnf/grammar.h

@@ -89,16 +89,21 @@ protected:
 
 private:
   friend bool operator==(grammar_base const &, grammar_base const &) = default;
+  friend std::ostream & operator<<(std::ostream &, grammar_base const &);
 
 private:
   static rule_store const s_default_rules_;
   rule_store rules_;
 };
 
-class grammar : public grammar_base {
+class grammar_group : public grammar_base {
 public:
-  using rule_store = std::map<std::string, rule, detail::iless>;
+  grammar_group(rule_store rules) : grammar_base(std::move(rules)) {}
+
+  bool satisfies(reference name, std::string_view text) const;
+};
 
+class grammar : public grammar_base {
 public:
   grammar(std::string_view name, rule base_rule, rule_store rules = {})
       : grammar_base(std::move(rules)), name_(name),
@@ -110,6 +115,7 @@ private:
   friend bool operator==(grammar const &, grammar const &) = default;
   friend std::ostream & operator<<(std::ostream &, grammar const &);
 
+private:
   std::string name_;
   rule base_rule_;
 };

+ 4 - 0
src/grammar.cxx

@@ -132,4 +132,8 @@ auto grammar_base::satisfies(std::string_view & text, rule const & rule) const
 bool grammar::satisfies(std::string_view text) const {
   return grammar_base::satisfies(text, base_rule_).valid;
 }
+
+bool grammar_group::satisfies(reference name, std::string_view text) const {
+  return grammar_base::satisfies(text, name).valid;
+}
 }

+ 8 - 3
src/io.cxx

@@ -45,11 +45,16 @@ std::ostream & operator<<(std::ostream & os, rule const & rule) {
   return os;
 }
 
-std::ostream & operator<<(std::ostream & os, grammar const & grammar) {
-  os << grammar.name_ << " =" << grammar.base_rule_ << "\n";
+std::ostream & operator<<(std::ostream & os, grammar_base const & grammar) {
+  std::string_view div = "";
   for (auto const & [name, rule] : grammar.rules_) {
-    os << "\n" << name << " =" << rule << "\n";
+    os << std::exchange(div, "\n") << name << " =" << rule << "\n";
   }
   return os;
 }
+
+std::ostream & operator<<(std::ostream & os, grammar const & grammar) {
+  os << grammar.name_ << " =" << grammar.base_rule_ << "\n\n";
+  return os << static_cast<grammar_base const &>(grammar);
+}
 }

+ 5 - 1
src/parser.cxx

@@ -1,7 +1,6 @@
 #include <cassert>
 #include <cctype>
 #include <charconv>
-#include <ios>
 #include <iostream>
 #include <sstream>
 #include <string>
@@ -12,6 +11,7 @@
 
 namespace abnf {
 grammar parse(std::istream && in) { return parse(in); }
+grammar_group parse_group(std::istream && in) { return parse_group(in); }
 
 static void append(rule & rule, rule_part const & part, bool is_one_of) {
   if (rule.rules.empty()) {
@@ -139,4 +139,8 @@ grammar parse(std::istream & in) {
   auto [name, rules] = parse_impl(in);
   return grammar(name, rules.extract(name).mapped(), rules);
 }
+
+grammar_group parse_group(std::istream & in) {
+  return grammar_group(parse_impl(in).second);
+}
 }