about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--011load.cc6
-rw-r--r--013literal_string.cc73
-rw-r--r--050scenario.cc5
-rw-r--r--072scenario_screen.cc1
4 files changed, 78 insertions, 7 deletions
diff --git a/011load.cc b/011load.cc
index 94f73634..7d9c3047 100644
--- a/011load.cc
+++ b/011load.cc
@@ -19,12 +19,14 @@ vector<recipe_number> load(string form) {
 vector<recipe_number> load(istream& in) {
   vector<recipe_number> result;
   while (!in.eof()) {
+//?     cerr << "===\n"; //? 1
     skip_whitespace_and_comments(in);
     if (in.eof()) break;
     string command = next_word(in);
     // Command Handlers
     if (command == "recipe") {
       string recipe_name = next_word(in);
+//?       cerr << "recipe: " << recipe_name << '\n'; //? 1
       if (recipe_name.empty())
         raise << "empty recipe name\n";
       if (Recipe_number.find(recipe_name) == Recipe_number.end()) {
@@ -60,6 +62,7 @@ recipe slurp_recipe(istream& in) {
   instruction curr;
   while (next_instruction(in, &curr)) {
     // End Rewrite Instruction(curr)
+//?     cerr << "instruction: " << curr.to_string() << '\n'; //? 2
     result.steps.push_back(curr);
   }
   return result;
@@ -102,6 +105,7 @@ bool next_instruction(istream& in, instruction* curr) {
     for (; *p != "<-"; ++p) {
       if (*p == ",") continue;
       curr->products.push_back(reagent(*p));
+//?       cerr << "product: " << curr->products.back().to_string() << '\n'; //? 1
     }
     ++p;  // skip <-
   }
@@ -119,6 +123,7 @@ bool next_instruction(istream& in, instruction* curr) {
   for (; p != words.end(); ++p) {
     if (*p == ",") continue;
     curr->ingredients.push_back(reagent(*p));
+//?     cerr << "ingredient: " << curr->ingredients.back().to_string() << '\n'; //? 1
   }
 
   trace("parse") << "instruction: " << curr->name;
@@ -138,6 +143,7 @@ string next_word(istream& in) {
   slurp_word(in, out);
   skip_whitespace(in);
   skip_comment(in);
+//?   cerr << '^' << out.str() << "$\n"; //? 1
   return out.str();
 }
 
diff --git a/013literal_string.cc b/013literal_string.cc
index 92db8f87..f1416384 100644
--- a/013literal_string.cc
+++ b/013literal_string.cc
@@ -26,15 +26,44 @@ Type_number["literal-string"] = 0;
     string result = slurp_quoted(in);
     skip_whitespace(in);
     skip_comment(in);
+//?     cerr << '^' << result << "$\n"; //? 1
     return result;
   }
 
 :(code)
 string slurp_quoted(istream& in) {
-  assert(!in.eof());
-  assert(in.peek() == '[');
   ostringstream out;
-  int brace_depth = 0;
+  assert(!in.eof());  assert(in.peek() == '[');  out << static_cast<char>(in.get());  // slurp the '['
+  if (code_string(in, out))
+    slurp_quoted_comment_aware(in, out);
+  else
+    slurp_quoted_comment_oblivious(in, out);
+  return out.str();
+}
+
+// A string is a code string if it contains a newline before any non-whitespace
+// todo: support comments before the newline. But that gets messy.
+bool code_string(istream& in, ostringstream& out) {
+  while (!in.eof()) {
+    char c = in.get();
+    if (!isspace(c)) {
+      in.putback(c);
+//?       cerr << "code_string: " << out.str() << '\n'; //? 1
+      return false;
+    }
+    out << c;
+    if (c == '\n') {
+//?       cerr << "code_string: " << out.str() << '\n'; //? 1
+      return true;
+    }
+  }
+  return false;
+}
+
+// Read a regular string. Regular strings can only contain other regular
+// strings.
+void slurp_quoted_comment_oblivious(istream& in, ostream& out) {
+  int brace_depth = 1;
   while (!in.eof()) {
     char c = in.get();
 //?     cout << (int)c << ": " << brace_depth << '\n'; //? 2
@@ -50,9 +79,28 @@ string slurp_quoted(istream& in) {
   }
   if (in.eof() && brace_depth > 0) {
     raise << "unbalanced '['\n";
-    return "";
+    out.clear();
+  }
+}
+
+// Read a code string. Code strings can contain either code or regular strings.
+void slurp_quoted_comment_aware(istream& in, ostream& out) {
+  char c;
+  while (in >> c) {
+    if (c == '#') {
+      out << c;
+      while (!in.eof() && in.peek() != '\n') out << static_cast<char>(in.get());
+      continue;
+    }
+    if (c == '[') {
+      in.putback(c);
+      // recurse
+      out << slurp_quoted(in);
+      continue;
+    }
+    out << c;
+    if (c == ']') break;
   }
-  return out.str();
 }
 
 :(after "reagent::reagent(string s)")
@@ -122,3 +170,18 @@ recipe main [
 def]
 ]
 +parse:   ingredient: {name: "abc\ndef", properties: [_: "literal-string"]}
+
+:(scenario string_literal_can_skip_past_comments)
+recipe main [
+  copy [
+    # ']' inside comment
+    bar
+  ]
+]
++parse:   ingredient: {name: "\n    # ']' inside comment\n    bar\n  ", properties: [_: "literal-string"]}
+
+:(scenario string_literal_empty)
+recipe main [
+  copy []
+]
++parse:   ingredient: {name: "", properties: [_: "literal-string"]}
diff --git a/050scenario.cc b/050scenario.cc
index bb828636..0f463cfc 100644
--- a/050scenario.cc
+++ b/050scenario.cc
@@ -74,6 +74,7 @@ scenario parse_scenario(istream& in) {
 //?   cerr << "parse scenario\n"; //? 1
   scenario result;
   result.name = next_word(in);
+//?   cerr << "scenario: " << result.name << '\n'; //? 1
   skip_whitespace_and_comments(in);
   assert(in.peek() == '[');
   // scenarios are take special 'code' strings so we need to ignore brackets
@@ -130,7 +131,7 @@ void run_mu_scenario(const scenario& s) {
     Trace_stream = new trace_stream;
     setup();
   }
-//?   cerr << '^' << s.to_run << "$\n"; //? 1
+//?   cerr << '^' << s.to_run << "$\n"; //? 2
   run("recipe "+s.name+" [ " + s.to_run + " ]");
   if (not_already_inside_test && Trace_stream) {
     teardown();
@@ -539,7 +540,7 @@ string slurp_quoted_ignoring_comments(istream& in) {
       // can't yet handle scenarios inside strings inside scenarios..
       in.putback(c);
       out << slurp_quoted(in);
-//?       cerr << "snapshot: ^" << out.str() << "$\n"; //? 1
+//?       cerr << "snapshot: ^" << out.str() << "$\n"; //? 2
       continue;
     }
     if (c == ']') {
diff --git a/072scenario_screen.cc b/072scenario_screen.cc
index b65f1dee..fe91a823 100644
--- a/072scenario_screen.cc
+++ b/072scenario_screen.cc
@@ -134,6 +134,7 @@ Name[tmp_recipe.at(0)]["screen"] = SCREEN;
 //? cout << "before: " << curr.to_string() << '\n'; //? 1
 if (curr.name == "assume-screen") {
   curr.operation = Recipe_number["init-fake-screen"];
+  assert(curr.operation);
   assert(curr.products.empty());
   curr.products.push_back(reagent("screen:address"));
   curr.products.at(0).set_value(SCREEN);