about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2015-12-02 17:11:58 -0800
committerKartik K. Agaram <vc@akkartik.com>2015-12-02 17:11:58 -0800
commit1f7e3c056ce0ea71e1337579b24e8fd1ad26abac (patch)
treecebdec305552bdf180f3f0db5518a69c2a086857
parentf8997ec06c0cdda1a16c5d99f96c447ce6809185 (diff)
downloadmu-1f7e3c056ce0ea71e1337579b24e8fd1ad26abac.tar.gz
2614 - still fixing bugs with missing '['
When skipping past some text (usually whitespace, but also commas and
comments) I need to always be aware of whether it's ok to switch to the
next line or not.
-rw-r--r--010vm.cc15
-rw-r--r--011load.cc36
-rw-r--r--014literal_string.cc3
-rw-r--r--030container.cc2
-rw-r--r--054dilated_reagent.cc2
-rw-r--r--055parse_tree.cc5
-rw-r--r--056recipe_header.cc27
7 files changed, 49 insertions, 41 deletions
diff --git a/010vm.cc b/010vm.cc
index 53e40b0a..59229ad6 100644
--- a/010vm.cc
+++ b/010vm.cc
@@ -261,7 +261,7 @@ reagent::reagent(string s) :original_string(s), value(0), initialized(false), ty
 }
 
 string_tree* parse_property_list(istream& in) {
-  skip_whitespace(in);
+  skip_whitespace_but_not_newline(in);
   if (!has_data(in)) return NULL;
   string_tree* result = new string_tree(slurp_until(in, ':'));
   result->right = parse_property_list(in);
@@ -523,9 +523,16 @@ void dump(const string_tree* x, ostream& out) {
   out << ')';
 }
 
-void skip_whitespace(istream& in) {
-  while (in && isspace(in.peek()) && in.peek() != '\n') {
-    in.get();
+:(before "End Globals")
+const string Ignore(",");  // commas are ignored in mu except within [] strings
+:(code)
+void skip_whitespace_but_not_newline(istream& in) {
+  while (true) {
+    if (!has_data(in)) break;
+    else if (in.peek() == '\n') break;
+    else if (isspace(in.peek())) in.get();
+    else if (Ignore.find(in.peek()) != string::npos) in.get();
+    else break;
   }
 }
 
diff --git a/011load.cc b/011load.cc
index 578e2b46..14811e38 100644
--- a/011load.cc
+++ b/011load.cc
@@ -43,7 +43,7 @@ vector<recipe_ordinal> load(istream& in) {
 long long int slurp_recipe(istream& in) {
   recipe result;
   result.name = next_word(in);
-  skip_whitespace_and_comments(in);
+  skip_whitespace_and_comments_but_not_newline(in);
   // End recipe Refinements
   if (result.name.empty())
     raise_error << "empty result.name\n" << end();
@@ -82,31 +82,22 @@ void slurp_body(istream& in, recipe& result) {
 
 bool next_instruction(istream& in, instruction* curr) {
   curr->clear();
-  if (!has_data(in)) {
-    raise_error << "0: unbalanced '[' for recipe\n" << end();
-    return false;
-  }
-  skip_whitespace(in);
-  if (!has_data(in)) {
-    raise_error << "1: unbalanced '[' for recipe\n" << end();
-    return false;
-  }
   skip_whitespace_and_comments(in);
   if (!has_data(in)) {
-    raise_error << "2: unbalanced '[' for recipe\n" << end();
+    raise_error << "0: unbalanced '[' for recipe\n" << end();
     return false;
   }
 
   vector<string> words;
   while (has_data(in) && in.peek() != '\n') {
-    skip_whitespace(in);
+    skip_whitespace_but_not_newline(in);
     if (!has_data(in)) {
-      raise_error << "3: unbalanced '[' for recipe\n" << end();
+      raise_error << "1: unbalanced '[' for recipe\n" << end();
       return false;
     }
     string word = next_word(in);
     words.push_back(word);
-    skip_whitespace(in);
+    skip_whitespace_but_not_newline(in);
   }
   skip_whitespace_and_comments(in);
   if (SIZE(words) == 1 && words.at(0) == "]") {
@@ -159,20 +150,17 @@ bool next_instruction(istream& in, instruction* curr) {
 }
 
 string next_word(istream& in) {
-  skip_whitespace(in);
-  skip_ignored_characters(in);
+  skip_whitespace_and_comments_but_not_newline(in);
   // End next_word Special-cases
   ostringstream out;
   slurp_word(in, out);
-  skip_whitespace(in);
-  skip_comment(in);
+  skip_whitespace_and_comments_but_not_newline(in);
   return out.str();
 }
 
 :(before "End Globals")
 // word boundaries
-string Terminators("(){}");
-string Ignore(",");  // meaningless except within [] strings
+const string Terminators("(){}");
 :(code)
 void slurp_word(istream& in, ostream& out) {
   char c;
@@ -190,17 +178,11 @@ void slurp_word(istream& in, ostream& out) {
   }
 }
 
-void skip_ignored_characters(istream& in) {
-  while (isspace(in.peek()) || Ignore.find(in.peek()) != string::npos) {
-    in.get();
-  }
-}
-
 void skip_whitespace_and_comments(istream& in) {
   while (true) {
     if (!has_data(in)) break;
     if (isspace(in.peek())) in.get();
-    else if (in.peek() == ',') in.get();
+    else if (Ignore.find(in.peek()) != string::npos) in.get();
     else if (in.peek() == '#') skip_comment(in);
     else break;
   }
diff --git a/014literal_string.cc b/014literal_string.cc
index 34655aa9..209a6428 100644
--- a/014literal_string.cc
+++ b/014literal_string.cc
@@ -24,8 +24,7 @@ put(Type_ordinal, "literal-string", 0);
 :(before "End next_word Special-cases")
 if (in.peek() == '[') {
   string result = slurp_quoted(in);
-  skip_whitespace(in);
-  skip_comment(in);
+  skip_whitespace_and_comments_but_not_newline(in);
   return result;
 }
 
diff --git a/030container.cc b/030container.cc
index 04be418c..afe08952 100644
--- a/030container.cc
+++ b/030container.cc
@@ -404,7 +404,7 @@ else if (command == "container") {
 
 :(code)
 void insert_container(const string& command, kind_of_type kind, istream& in) {
-  skip_whitespace(in);
+  skip_whitespace_but_not_newline(in);
   string name = next_word(in);
   // End container Name Refinements
   trace(9991, "parse") << "--- defining " << command << ' ' << name << end();
diff --git a/054dilated_reagent.cc b/054dilated_reagent.cc
index ac40f049..6788becc 100644
--- a/054dilated_reagent.cc
+++ b/054dilated_reagent.cc
@@ -32,7 +32,7 @@ bool start_of_dilated_reagent(istream& in) {
   if (in.peek() != '{') return false;
   long long int pos = in.tellg();
   in.get();  // slurp '{'
-  skip_whitespace(in);
+  skip_whitespace_but_not_newline(in);
   char next = in.peek();
   in.seekg(pos);
   return next != '\n';
diff --git a/055parse_tree.cc b/055parse_tree.cc
index ef9cf4e1..33537344 100644
--- a/055parse_tree.cc
+++ b/055parse_tree.cc
@@ -28,7 +28,7 @@ string_tree* parse_string_tree(const string& s) {
 }
 
 string_tree* parse_string_tree(istream& in) {
-  skip_whitespace(in);
+  skip_whitespace_but_not_newline(in);
   if (!has_data(in)) return NULL;
   if (in.peek() == ')') {
     in.get();
@@ -44,8 +44,7 @@ string_tree* parse_string_tree(istream& in) {
   while (in.peek() != ')') {
     assert(has_data(in));
     *curr = new string_tree("");
-    skip_whitespace(in);
-    skip_ignored_characters(in);
+    skip_whitespace_but_not_newline(in);
     if (in.peek() == '(')
       (*curr)->left = parse_string_tree(in);
     else
diff --git a/056recipe_header.cc b/056recipe_header.cc
index f0d448b2..2ca02af7 100644
--- a/056recipe_header.cc
+++ b/056recipe_header.cc
@@ -23,7 +23,6 @@ vector<reagent> products;
 has_header = false;
 
 :(before "End recipe Refinements")
-skip_whitespace(in);
 if (in.peek() != '[') {
   trace(9999, "parse") << "recipe has a header; parsing" << end();
   load_recipe_header(in, result);
@@ -37,17 +36,28 @@ void load_recipe_header(istream& in, recipe& result) {
     if (s == "->") break;
     result.ingredients.push_back(reagent(s));
     trace(9999, "parse") << "header ingredient: " << result.ingredients.back().original_string << end();
-    skip_whitespace_and_comments(in);
+    skip_whitespace_and_comments_but_not_newline(in);
   }
   while (has_data(in) && in.peek() != '[' && in.peek() != '\n') {
     string s = next_word(in);
     result.products.push_back(reagent(s));
     trace(9999, "parse") << "header product: " << result.products.back().original_string << end();
-    skip_whitespace_and_comments(in);
+    skip_whitespace_and_comments_but_not_newline(in);
   }
   // End Load Recipe Header(result)
 }
 
+void skip_whitespace_and_comments_but_not_newline(istream& in) {
+  while (true) {
+    if (!has_data(in)) break;
+    if (in.peek() == '\n') break;
+    if (isspace(in.peek())) in.get();
+    else if (Ignore.find(in.peek()) != string::npos) in.get();
+    else if (in.peek() == '#') skip_comment(in);
+    else break;
+  }
+}
+
 :(scenario recipe_handles_stray_comma)
 recipe main [
   1:number/raw <- add2 3, 5
@@ -78,6 +88,17 @@ recipe main
 ]
 +error: recipe body must begin with '['
 
+:(scenario recipe_handles_missing_bracket_2)
+% Hide_errors = true;
+recipe main
+  local-scope
+  {
+  }
+]
+# doesn't overflow line when reading header
+-parse: header ingredient: local-scope
++error: recipe body must begin with '['
+
 :(after "Begin debug_string(recipe x)")
 out << "ingredients:\n";
 for (long long int i = 0; i < SIZE(x.ingredients); ++i)