瀏覽代碼

cmArgumentParser: Generalize expected argument count

Replace the boolean expectation with an integer count.
Brad King 3 年之前
父節點
當前提交
f5d2f6076a
共有 2 個文件被更改,包括 51 次插入33 次删除
  1. 37 31
      Source/cmArgumentParser.cxx
  2. 14 2
      Source/cmArgumentParser.h

+ 37 - 31
Source/cmArgumentParser.cxx

@@ -34,64 +34,69 @@ auto KeywordActionMap::Find(cm::string_view name) const -> const_iterator
   return (it != this->end() && it->first == name) ? it : this->end();
 }
 
-void Instance::Bind(std::function<Continue(cm::string_view)> f)
+void Instance::Bind(std::function<Continue(cm::string_view)> f,
+                    ExpectAtLeast expect)
 {
   this->KeywordValueFunc = std::move(f);
-  this->ExpectValue = true;
+  this->KeywordValuesExpected = expect.Count;
 }
 
 void Instance::Bind(bool& val)
 {
   val = true;
-  this->KeywordValueFunc = nullptr;
-  this->ExpectValue = false;
+  this->Bind(nullptr, ExpectAtLeast{ 0 });
 }
 
 void Instance::Bind(std::string& val)
 {
-  this->KeywordValueFunc = [&val](cm::string_view arg) -> Continue {
-    val = std::string(arg);
-    return Continue::No;
-  };
-  this->ExpectValue = true;
+  this->Bind(
+    [&val](cm::string_view arg) -> Continue {
+      val = std::string(arg);
+      return Continue::No;
+    },
+    ExpectAtLeast{ 1 });
 }
 
 void Instance::Bind(Maybe<std::string>& val)
 {
-  this->KeywordValueFunc = [&val](cm::string_view arg) -> Continue {
-    static_cast<std::string&>(val) = std::string(arg);
-    return Continue::No;
-  };
-  this->ExpectValue = false;
+  this->Bind(
+    [&val](cm::string_view arg) -> Continue {
+      static_cast<std::string&>(val) = std::string(arg);
+      return Continue::No;
+    },
+    ExpectAtLeast{ 0 });
 }
 
 void Instance::Bind(MaybeEmpty<std::vector<std::string>>& val)
 {
-  this->KeywordValueFunc = [&val](cm::string_view arg) -> Continue {
-    val.emplace_back(arg);
-    return Continue::Yes;
-  };
-  this->ExpectValue = false;
+  this->Bind(
+    [&val](cm::string_view arg) -> Continue {
+      val.emplace_back(arg);
+      return Continue::Yes;
+    },
+    ExpectAtLeast{ 0 });
 }
 
 void Instance::Bind(NonEmpty<std::vector<std::string>>& val)
 {
-  this->KeywordValueFunc = [&val](cm::string_view arg) -> Continue {
-    val.emplace_back(arg);
-    return Continue::Yes;
-  };
-  this->ExpectValue = true;
+  this->Bind(
+    [&val](cm::string_view arg) -> Continue {
+      val.emplace_back(arg);
+      return Continue::Yes;
+    },
+    ExpectAtLeast{ 1 });
 }
 
 void Instance::Bind(std::vector<std::vector<std::string>>& multiVal)
 {
   multiVal.emplace_back();
   std::vector<std::string>& val = multiVal.back();
-  this->KeywordValueFunc = [&val](cm::string_view arg) -> Continue {
-    val.emplace_back(arg);
-    return Continue::Yes;
-  };
-  this->ExpectValue = false;
+  this->Bind(
+    [&val](cm::string_view arg) -> Continue {
+      val.emplace_back(arg);
+      return Continue::Yes;
+    },
+    ExpectAtLeast{ 0 });
 }
 
 void Instance::Consume(cm::string_view arg)
@@ -100,6 +105,7 @@ void Instance::Consume(cm::string_view arg)
   if (it != this->Bindings.Keywords.end()) {
     this->FinishKeyword();
     this->Keyword = it->first;
+    this->KeywordValuesSeen = 0;
     if (this->Bindings.ParsedKeyword) {
       this->Bindings.ParsedKeyword(*this, it->first);
     }
@@ -115,7 +121,7 @@ void Instance::Consume(cm::string_view arg)
         this->KeywordValueFunc = nullptr;
         break;
     }
-    this->ExpectValue = false;
+    ++this->KeywordValuesSeen;
     return;
   }
 
@@ -129,7 +135,7 @@ void Instance::FinishKeyword()
   if (this->Keyword.empty()) {
     return;
   }
-  if (this->ExpectValue) {
+  if (this->KeywordValuesSeen < this->KeywordValuesExpected) {
     if (this->ParseResults != nullptr) {
       this->ParseResults->AddKeywordError(this->Keyword,
                                           "  missing required value\n");

+ 14 - 2
Source/cmArgumentParser.h

@@ -68,6 +68,16 @@ enum class Continue
   Yes,
 };
 
+struct ExpectAtLeast
+{
+  std::size_t Count = 0;
+
+  ExpectAtLeast(std::size_t count)
+    : Count(count)
+  {
+  }
+};
+
 class Instance;
 using KeywordAction = std::function<void(Instance&)>;
 using KeywordNameAction = std::function<void(Instance&, cm::string_view)>;
@@ -93,6 +103,7 @@ public:
 class Base
 {
 public:
+  using ExpectAtLeast = ArgumentParser::ExpectAtLeast;
   using Continue = ArgumentParser::Continue;
   using Instance = ArgumentParser::Instance;
   using ParseResult = ArgumentParser::ParseResult;
@@ -136,7 +147,7 @@ public:
   {
   }
 
-  void Bind(std::function<Continue(cm::string_view)> f);
+  void Bind(std::function<Continue(cm::string_view)> f, ExpectAtLeast expect);
   void Bind(bool& val);
   void Bind(std::string& val);
   void Bind(Maybe<std::string>& val);
@@ -170,8 +181,9 @@ private:
   void* Result = nullptr;
 
   cm::string_view Keyword;
+  std::size_t KeywordValuesSeen = 0;
+  std::size_t KeywordValuesExpected = 0;
   std::function<Continue(cm::string_view)> KeywordValueFunc;
-  bool ExpectValue = false;
 
   void Consume(cm::string_view arg);
   void FinishKeyword();