about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2020-07-16T19·28+0100
committertazjin <mail@tazj.in>2020-07-16T19·53+0000
commit5ae2a2b847f94e39932c7abd06662d990773649a (patch)
tree0d2b45c6fb629d81a6e3fdd20f1796f3669d3335
parentd579ceb7830406ae743aa3da274017d5e8a7bfa7 (diff)
refactor(3p/nix/libexpr): Extract static helpers out of parser.y r/1322
Moves several of the static helper functions into a new parser.cc
file.

Once the rest of the code is usefully extracted, these will be moved
to a private namespace.

Change-Id: I0d7b53dcefe31bb5c6bad3ad7f5fcb48276bf799
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1218
Tested-by: BuildkiteCI
Reviewed-by: isomer <isomer@tvl.fyi>
-rw-r--r--third_party/nix/src/libexpr/CMakeLists.txt1
-rw-r--r--third_party/nix/src/libexpr/parser.cc186
-rw-r--r--third_party/nix/src/libexpr/parser.hh10
-rw-r--r--third_party/nix/src/libexpr/parser.y190
4 files changed, 202 insertions, 185 deletions
diff --git a/third_party/nix/src/libexpr/CMakeLists.txt b/third_party/nix/src/libexpr/CMakeLists.txt
index d2e991657b..693b618c66 100644
--- a/third_party/nix/src/libexpr/CMakeLists.txt
+++ b/third_party/nix/src/libexpr/CMakeLists.txt
@@ -59,6 +59,7 @@ target_sources(nixexpr
     json-to-value.cc
     names.cc
     nixexpr.cc
+    parser.cc
     primops.cc
     symbol-table.cc
     value-to-json.cc
diff --git a/third_party/nix/src/libexpr/parser.cc b/third_party/nix/src/libexpr/parser.cc
new file mode 100644
index 0000000000..50b7cc3ff8
--- /dev/null
+++ b/third_party/nix/src/libexpr/parser.cc
@@ -0,0 +1,186 @@
+#include "libexpr/parser.hh"
+
+namespace nix {
+
+void addAttr(ExprAttrs* attrs, AttrPath& attrPath, Expr* e, const Pos& pos) {
+  AttrPath::iterator i;
+  // All attrpaths have at least one attr
+  assert(!attrPath.empty());
+  // Checking attrPath validity.
+  // ===========================
+  for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
+    if (const auto* sym = std::get_if<Symbol>(&(*i)); sym && sym->set()) {
+      ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*sym);
+      if (j != attrs->attrs.end()) {
+        if (!j->second.inherited) {
+          ExprAttrs* attrs2 = dynamic_cast<ExprAttrs*>(j->second.e);
+          if (!attrs2) {
+            dupAttr(attrPath, pos, j->second.pos);
+          }
+          attrs = attrs2;
+        } else {
+          dupAttr(attrPath, pos, j->second.pos);
+        }
+      } else {
+        ExprAttrs* nested = new ExprAttrs;
+        attrs->attrs[*sym] = ExprAttrs::AttrDef(nested, pos);
+        attrs = nested;
+      }
+    } else {
+      // Yes, this code does not handle all conditions
+      // exhaustively. We use std::get to throw if the condition
+      // that isn't covered happens, which is potentially a
+      // behaviour change from the previous default constructed
+      // Symbol. It should alert us about anything untoward going
+      // on here.
+      auto* expr = std::get<Expr*>(*i);
+
+      ExprAttrs* nested = new ExprAttrs;
+      attrs->dynamicAttrs.push_back(
+          ExprAttrs::DynamicAttrDef(expr, nested, pos));
+      attrs = nested;
+    }
+  }
+  // Expr insertion.
+  // ==========================
+  if (auto* sym = std::get_if<Symbol>(&(*i)); sym && sym->set()) {
+    ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*sym);
+    if (j != attrs->attrs.end()) {
+      // This attr path is already defined. However, if both
+      // e and the expr pointed by the attr path are two attribute sets,
+      // we want to merge them.
+      // Otherwise, throw an error.
+      auto ae = dynamic_cast<ExprAttrs*>(e);
+      auto jAttrs = dynamic_cast<ExprAttrs*>(j->second.e);
+      if (jAttrs && ae) {
+        for (auto& ad : ae->attrs) {
+          auto j2 = jAttrs->attrs.find(ad.first);
+          if (j2 !=
+              jAttrs->attrs.end()) {  // Attr already defined in iAttrs, error.
+            dupAttr(ad.first, j2->second.pos, ad.second.pos);
+          }
+          jAttrs->attrs[ad.first] = ad.second;
+        }
+      } else {
+        dupAttr(attrPath, pos, j->second.pos);
+      }
+    } else {
+      // This attr path is not defined. Let's create it.
+      attrs->attrs[*sym] = ExprAttrs::AttrDef(e, pos);
+    }
+  } else {
+    // Same caveat as the identical line above.
+    auto* expr = std::get<Expr*>(*i);
+    attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(expr, e, pos));
+  }
+}
+
+void addFormal(const Pos& pos, Formals* formals, const Formal& formal) {
+  if (formals->argNames.find(formal.name) != formals->argNames.end())
+    throw ParseError(format("duplicate formal function argument '%1%' at %2%") %
+                     formal.name % pos);
+  formals->formals.push_front(formal);
+  formals->argNames.insert(formal.name);
+}
+
+Expr* stripIndentation(const Pos& pos, SymbolTable& symbols,
+                       std::vector<Expr*>& es) {
+  if (es.empty()) {
+    return new ExprString(symbols.Create(""));
+  }
+
+  /* Figure out the minimum indentation.  Note that by design
+     whitespace-only final lines are not taken into account.  (So
+     the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */
+  bool atStartOfLine = true; /* = seen only whitespace in the current line */
+  size_t minIndent = 1000000;
+  size_t curIndent = 0;
+  for (auto& i : es) {
+    ExprIndStr* e = dynamic_cast<ExprIndStr*>(i);
+    if (!e) {
+      /* Anti-quotations end the current start-of-line whitespace. */
+      if (atStartOfLine) {
+        atStartOfLine = false;
+        if (curIndent < minIndent) {
+          minIndent = curIndent;
+        }
+      }
+      continue;
+    }
+    for (size_t j = 0; j < e->s.size(); ++j) {
+      if (atStartOfLine) {
+        if (e->s[j] == ' ')
+          curIndent++;
+        else if (e->s[j] == '\n') {
+          /* Empty line, doesn't influence minimum
+             indentation. */
+          curIndent = 0;
+        } else {
+          atStartOfLine = false;
+          if (curIndent < minIndent) {
+            minIndent = curIndent;
+          }
+        }
+      } else if (e->s[j] == '\n') {
+        atStartOfLine = true;
+        curIndent = 0;
+      }
+    }
+  }
+
+  /* Strip spaces from each line. */
+  std::vector<Expr*>* es2 = new std::vector<Expr*>;
+  atStartOfLine = true;
+  size_t curDropped = 0;
+  size_t n = es.size();
+  for (std::vector<Expr*>::iterator i = es.begin(); i != es.end(); ++i, --n) {
+    ExprIndStr* e = dynamic_cast<ExprIndStr*>(*i);
+    if (!e) {
+      atStartOfLine = false;
+      curDropped = 0;
+      es2->push_back(*i);
+      continue;
+    }
+
+    std::string s2;
+    for (size_t j = 0; j < e->s.size(); ++j) {
+      if (atStartOfLine) {
+        if (e->s[j] == ' ') {
+          if (curDropped++ >= minIndent) s2 += e->s[j];
+        } else if (e->s[j] == '\n') {
+          curDropped = 0;
+          s2 += e->s[j];
+        } else {
+          atStartOfLine = false;
+          curDropped = 0;
+          s2 += e->s[j];
+        }
+      } else {
+        s2 += e->s[j];
+        if (e->s[j] == '\n') {
+          atStartOfLine = true;
+        }
+      }
+    }
+
+    /* Remove the last line if it is empty and consists only of
+       spaces. */
+    if (n == 1) {
+      std::string::size_type p = s2.find_last_of('\n');
+      if (p != std::string::npos &&
+          s2.find_first_not_of(' ', p + 1) == std::string::npos) {
+        s2 = std::string(s2, 0, p + 1);
+      }
+    }
+
+    es2->push_back(new ExprString(symbols.Create(s2)));
+  }
+
+  /* If this is a single string, then don't do a concatenation. */
+  return es2->size() == 1 && dynamic_cast<ExprString*>((*es2)[0])
+             ? (*es2)[0]
+             : new ExprConcatStrings(pos, true, es2);
+}
+
+
+}  // namespace nix
diff --git a/third_party/nix/src/libexpr/parser.hh b/third_party/nix/src/libexpr/parser.hh
index ae0e932147..3de8280bf5 100644
--- a/third_party/nix/src/libexpr/parser.hh
+++ b/third_party/nix/src/libexpr/parser.hh
@@ -15,6 +15,8 @@
   int yylex(YYSTYPE* yylval_param, YYLTYPE* yylloc_param, yyscan_t yyscanner, \
             nix::ParseData* data)
 
+#define CUR_POS makeCurPos(*yylocp, data)
+
 namespace nix {
 
 struct ParseData {
@@ -44,4 +46,12 @@ static void dupAttr(Symbol attr, const Pos& pos, const Pos& prevPos) {
                    attr % pos % prevPos);
 }
 
+void addAttr(ExprAttrs* attrs, AttrPath& attrPath, Expr* e, const Pos& pos);
+
+void addFormal(const Pos& pos, Formals* formals, const Formal& formal);
+
+Expr* stripIndentation(const Pos& pos, SymbolTable& symbols,
+                       std::vector<Expr*>& es);
+
+
 }  // namespace nix
diff --git a/third_party/nix/src/libexpr/parser.y b/third_party/nix/src/libexpr/parser.y
index 9df9b3081a..2ec1cf6c55 100644
--- a/third_party/nix/src/libexpr/parser.y
+++ b/third_party/nix/src/libexpr/parser.y
@@ -24,197 +24,17 @@ using namespace nix;
 
 namespace nix {
 
-static void addAttr(ExprAttrs * attrs, AttrPath & attrPath,
-    Expr * e, const Pos & pos)
-{
-    AttrPath::iterator i;
-    // All attrpaths have at least one attr
-    assert(!attrPath.empty());
-    // Checking attrPath validity.
-    // ===========================
-    for (i = attrPath.begin(); i + 1 < attrPath.end(); i++) {
-        if (const auto* sym = std::get_if<Symbol>(&(*i)); sym && sym->set()) {
-            ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*sym);
-            if (j != attrs->attrs.end()) {
-                if (!j->second.inherited) {
-                    ExprAttrs * attrs2 = dynamic_cast<ExprAttrs *>(j->second.e);
-                    if (!attrs2) { dupAttr(attrPath, pos, j->second.pos); }
-                    attrs = attrs2;
-                } else {
-                    dupAttr(attrPath, pos, j->second.pos);
-                }
-            } else {
-                ExprAttrs* nested = new ExprAttrs;
-                attrs->attrs[*sym] = ExprAttrs::AttrDef(nested, pos);
-                attrs = nested;
-            }
-        } else {
-          // Yes, this code does not handle all conditions
-          // exhaustively. We use std::get to throw if the condition
-          // that isn't covered happens, which is potentially a
-          // behaviour change from the previous default constructed
-          // Symbol. It should alert us about anything untoward going
-          // on here.
-          auto* expr = std::get<Expr*>(*i);
-
-          ExprAttrs *nested = new ExprAttrs;
-          attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(expr, nested, pos));
-          attrs = nested;
-        }
-    }
-    // Expr insertion.
-    // ==========================
-    if (auto* sym = std::get_if<Symbol>(&(*i)); sym && sym->set()) {
-        ExprAttrs::AttrDefs::iterator j = attrs->attrs.find(*sym);
-        if (j != attrs->attrs.end()) {
-            // This attr path is already defined. However, if both
-            // e and the expr pointed by the attr path are two attribute sets,
-            // we want to merge them.
-            // Otherwise, throw an error.
-            auto ae = dynamic_cast<ExprAttrs *>(e);
-            auto jAttrs = dynamic_cast<ExprAttrs *>(j->second.e);
-            if (jAttrs && ae) {
-                for (auto & ad : ae->attrs) {
-                    auto j2 = jAttrs->attrs.find(ad.first);
-                    if (j2 != jAttrs->attrs.end()) {// Attr already defined in iAttrs, error.
-                        dupAttr(ad.first, j2->second.pos, ad.second.pos);
-                    }
-                    jAttrs->attrs[ad.first] = ad.second;
-                }
-            } else {
-                dupAttr(attrPath, pos, j->second.pos);
-            }
-        } else {
-            // This attr path is not defined. Let's create it.
-            attrs->attrs[*sym] = ExprAttrs::AttrDef(e, pos);
-        }
-    } else {
-        // Same caveat as the identical line above.
-        auto* expr = std::get<Expr*>(*i);
-        attrs->dynamicAttrs.push_back(ExprAttrs::DynamicAttrDef(expr, e, pos));
-    }
+static inline Pos makeCurPos(const YYLTYPE& loc, ParseData* data) {
+  return Pos(data->path, loc.first_line, loc.first_column);
 }
 
-
-static void addFormal(const Pos & pos, Formals * formals, const Formal & formal)
-{
-    if (formals->argNames.find(formal.name) != formals->argNames.end())
-        throw ParseError(format("duplicate formal function argument '%1%' at %2%")
-            % formal.name % pos);
-    formals->formals.push_front(formal);
-    formals->argNames.insert(formal.name);
+void yyerror(YYLTYPE* loc, yyscan_t scanner, ParseData* data,
+             const char* error) {
+  data->error = (format("%1%, at %2%") % error % makeCurPos(*loc, data)).str();
 }
 
-
-static Expr * stripIndentation(const Pos & pos, SymbolTable & symbols, std::vector<Expr *> & es)
-{
-    if (es.empty()) { return new ExprString(symbols.Create("")); }
-
-    /* Figure out the minimum indentation.  Note that by design
-       whitespace-only final lines are not taken into account.  (So
-       the " " in "\n ''" is ignored, but the " " in "\n foo''" is.) */
-    bool atStartOfLine = true; /* = seen only whitespace in the current line */
-    size_t minIndent = 1000000;
-    size_t curIndent = 0;
-    for (auto & i : es) {
-        ExprIndStr * e = dynamic_cast<ExprIndStr *>(i);
-        if (!e) {
-            /* Anti-quotations end the current start-of-line whitespace. */
-            if (atStartOfLine) {
-                atStartOfLine = false;
-                if (curIndent < minIndent) { minIndent = curIndent; }
-            }
-            continue;
-        }
-        for (size_t j = 0; j < e->s.size(); ++j) {
-            if (atStartOfLine) {
-                if (e->s[j] == ' ')
-                    curIndent++;
-                else if (e->s[j] == '\n') {
-                    /* Empty line, doesn't influence minimum
-                       indentation. */
-                    curIndent = 0;
-                } else {
-                    atStartOfLine = false;
-                    if (curIndent < minIndent) { minIndent = curIndent; }
-                }
-            } else if (e->s[j] == '\n') {
-                atStartOfLine = true;
-                curIndent = 0;
-            }
-        }
-    }
-
-    /* Strip spaces from each line. */
-    std::vector<Expr *> * es2 = new std::vector<Expr *>;
-    atStartOfLine = true;
-    size_t curDropped = 0;
-    size_t n = es.size();
-    for (std::vector<Expr *>::iterator i = es.begin(); i != es.end(); ++i, --n) {
-        ExprIndStr * e = dynamic_cast<ExprIndStr *>(*i);
-        if (!e) {
-            atStartOfLine = false;
-            curDropped = 0;
-            es2->push_back(*i);
-            continue;
-        }
-
-        std::string s2;
-        for (size_t j = 0; j < e->s.size(); ++j) {
-            if (atStartOfLine) {
-                if (e->s[j] == ' ') {
-                    if (curDropped++ >= minIndent)
-                        s2 += e->s[j];
-                }
-                else if (e->s[j] == '\n') {
-                    curDropped = 0;
-                    s2 += e->s[j];
-                } else {
-                    atStartOfLine = false;
-                    curDropped = 0;
-                    s2 += e->s[j];
-                }
-            } else {
-                s2 += e->s[j];
-                if (e->s[j] == '\n') { atStartOfLine = true; }
-            }
-        }
-
-        /* Remove the last line if it is empty and consists only of
-           spaces. */
-        if (n == 1) {
-            std::string::size_type p = s2.find_last_of('\n');
-            if (p != std::string::npos && s2.find_first_not_of(' ', p + 1) == std::string::npos) {
-                s2 = std::string(s2, 0, p + 1);
-            }
-        }
-
-        es2->push_back(new ExprString(symbols.Create(s2)));
-    }
-
-    /* If this is a single string, then don't do a concatenation. */
-    return es2->size() == 1 && dynamic_cast<ExprString *>((*es2)[0]) ? (*es2)[0] : new ExprConcatStrings(pos, true, es2);
-}
-
-
-static inline Pos makeCurPos(const YYLTYPE & loc, ParseData * data)
-{
-    return Pos(data->path, loc.first_line, loc.first_column);
 }
 
-#define CUR_POS makeCurPos(*yylocp, data)
-
-
-}
-
-
-void yyerror(YYLTYPE * loc, yyscan_t scanner, ParseData * data, const char * error)
-{
-    data->error = (format("%1%, at %2%")
-        % error % makeCurPos(*loc, data)).str();
-}
-
-
 %}
 
 %union {