diff --git a/src/DataTree.cc b/src/DataTree.cc
index 56f506ede216c5599ab4b9d303ae931064c26063..df018564ec058515d0171363404fe9294feee818 100644
--- a/src/DataTree.cc
+++ b/src/DataTree.cc
@@ -945,6 +945,23 @@ DataTree::writePowerDerivHeader(ostream &output) const
     output << "double getPowerDeriv(double x, double p, int k);" << endl;
 }
 
+vector<string>
+DataTree::strsplit(string_view str, char delim)
+{
+  vector<string> result;
+  while (true)
+    {
+      size_t idx {str.find(delim)};
+      if (auto sub {str.substr(0, idx)};
+          !sub.empty())
+        result.emplace_back(sub);
+      if (idx == string_view::npos)
+        break;
+      str.remove_prefix(idx+1);
+    }
+  return result;
+}
+
 string
 DataTree::packageDir(const string &package)
 {
diff --git a/src/DataTree.hh b/src/DataTree.hh
index 192f788fded8b30b474996ef9c69d23a2c79f1e7..8299a0ee4a830a7a6634a8660b704ec33e1c4f02 100644
--- a/src/DataTree.hh
+++ b/src/DataTree.hh
@@ -355,6 +355,11 @@ public:
     no_commutativity = true;
   }
 
+  /* Equivalent of MATLAB/Octave’s strsplit, except that it ignores empty
+     substring components (MATLAB/Octave adds them to the output); in
+     particular, returns an empty vector given an empty string. */
+  static vector<string> strsplit(string_view str, char delim);
+
   /*! Takes a MATLAB/Octave package name (possibly with several levels nested using dots),
     and returns the name of the corresponding filesystem directory (which
     is created by the function if it does not exist).
diff --git a/src/ParsingDriver.cc b/src/ParsingDriver.cc
index 006354310738725ab52419b7ffd8ce163e3eb8b8..b82fe92e8f7ed8aa4159407aab92b21e467460dc 100644
--- a/src/ParsingDriver.cc
+++ b/src/ParsingDriver.cc
@@ -2587,8 +2587,8 @@ ParsingDriver::add_model_equal(expr_t arg1, expr_t arg2)
       // If the equation has a “bind” or “relax” tag (occbin case)
       if (!eq_tags.contains("name"))
         error("An equation with a 'bind' or 'relax' tag must have a 'name' tag");
-      auto regimes_bind = strsplit(eq_tags["bind"], ',');
-      auto regimes_relax = strsplit(eq_tags["relax"], ',');
+      auto regimes_bind = DataTree::strsplit(eq_tags["bind"], ',');
+      auto regimes_relax = DataTree::strsplit(eq_tags["relax"], ',');
       auto regimes_all = regimes_bind;
       regimes_all.insert(regimes_all.end(), regimes_relax.begin(), regimes_relax.end()); // Concatenate the two vectors
       for (const auto &regime : regimes_all)
@@ -3732,25 +3732,6 @@ ParsingDriver::set_pac_target_info_component_kind(PacTargetKind kind)
   get<3>(pac_target_info_component) = kind;
 }
 
-vector<string>
-ParsingDriver::strsplit(const string &str, char delim)
-{
-  vector<string> result;
-  size_t idx = 0;
-  while (idx < str.size())
-    {
-      size_t idx2 = str.find(delim, idx);
-      if (idx2 == string::npos)
-        {
-          result.push_back(str.substr(idx));
-          break;
-        }
-      result.push_back(str.substr(idx, idx2-idx));
-      idx = idx2 + 1;
-    }
-  return result;
-}
-
 bool
 ParsingDriver::isSymbolIdentifier(const string &str)
 {
diff --git a/src/ParsingDriver.hh b/src/ParsingDriver.hh
index 38f69c8249150e4ab1fb8f11bc61546db7b8b645..53b2f4b3424c9eb5392e34fd5d22f2df6afd9b58 100644
--- a/src/ParsingDriver.hh
+++ b/src/ParsingDriver.hh
@@ -932,8 +932,6 @@ public:
   void set_pac_target_info_component_kind(PacTargetKind kind);
   // Add a resid statement
   void resid();
-  // Equivalent of MATLAB’s strsplit. Returns an empty vector given an empty string.
-  static vector<string> strsplit(const string &str, char delim);
   // Returns true iff the string is a legal symbol identifier (see NAME token in lexer)
   static bool isSymbolIdentifier(const string &str);
   // Given an Occbin regime name, returns the corresponding auxiliary parameter