diff options
-rw-r--r-- | 011load.cc | 6 | ||||
-rw-r--r-- | 013literal_string.cc | 73 | ||||
-rw-r--r-- | 050scenario.cc | 5 | ||||
-rw-r--r-- | 072scenario_screen.cc | 1 |
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); |