//: Phase 1 of running mu code: load it from a textual representation. :(scenarios load) // use 'load' instead of 'run' in all scenarios in this layer :(scenario first_recipe) recipe main [ 1:number <- copy 23 ] +parse: instruction: copy +parse: ingredient: {"23": "literal"} +parse: product: {"1": "number"} :(code) vector load(string form) { istringstream in(form); in >> std::noskipws; return load(in); } vector load(istream& in) { in >> std::noskipws; vector result; while (!in.eof()) { skip_whitespace_and_comments(in); if (in.eof()) break; string command = next_word(in); // Command Handlers if (command == "recipe") { result.push_back(slurp_recipe(in)); } else if (command == "recipe!") { Disable_redefine_warnings = true; result.push_back(slurp_recipe(in)); Disable_redefine_warnings = false; } // End Command Handlers else { raise_error << "unknown top-level command: " << command << '\n' << end(); } } return result; } long long int slurp_recipe(istream& in) { recipe result; result.name = next_word(in); // End recipe Refinements if (result.name.empty()) raise_error << "empty result.name\n" << end(); trace(9991, "parse") << "--- defining " << result.name << end(); if (Recipe_ordinal.find(result.name) == Recipe_ordinal.end()) { Recipe_ordinal[result.name] = Next_recipe_ordinal++; } if (Recipe.find(Recipe_ordinal[result.name]) != Recipe.end()) { trace(9991, "parse") << "already exists" << end(); if (warn_on_redefine(result.name)) raise << "redefining recipe " << result.name << "\n" << end(); Recipe.erase(Recipe_ordinal[result.name]); } slurp_body(in, result); // End recipe Body(result) Recipe[Recipe_ordinal[result.name]] = result; // track added recipes because we may need to undo them in tests; see below recently_added_recipes.push_back(Recipe_ordinal[result.name]); return Recipe_ordinal[result.name]; } void slurp_body(istream& in, recipe& result) { in >> std::noskipws; skip_whitespace(in); if (in.get() != '[') raise_error << "recipe body must begin with '['\n" << end(); skip_whitespace_and_comments(in); instruction curr; while (next_instruction(in, &curr)) { // End Rewrite Instruction(curr, recipe result) trace(9992, "load") << "after rewriting: " << curr.to_string() << end(); if (!curr.is_clear()) result.steps.push_back(curr); } } bool next_instruction(istream& in, instruction* curr) { curr->clear(); if (in.eof()) { raise_error << "0: unbalanced '[' for recipe\n" << end(); return false; } skip_whitespace(in); if (in.eof()) { raise_error << "1: unbalanced '[' for recipe\n" << end(); return false; } skip_whitespace_and_comments(in); if (in.eof()) { raise_error << "2: unbalanced '[' for recipe\n" << end(); return false; } vector words; while (in.peek() != '\n' && !in.eof()) { skip_whitespace(in); if (in.eof()) { raise_error << "3: unbalanced '[' for recipe\n" << end(); return false; } string word = next_word(in); words.push_back(word); skip_whitespace(in); } skip_whitespace_and_comments(in); if (SIZE(words) == 1 && words.at(0) == "]") { return false; // end of recipe } if (SIZE(words) == 1 && !isalnum(words.at(0).at(0)) && words.at(0).at(0) != '$') { curr->is_label = true; curr->label = words.at(0); trace(9993, "parse") << "label: " << curr->label << end(); if (in.eof()) { raise_error << "7: unbalanced '[' for recipe\n" << end(); return false; } return true; } vector::iterator p = words.begin(); if (find(
- improve mouse based resizals with quadrant approach (then I think we have feature completeness already)
product: {"2": <"address" : <"number" : <>>>} :(scenario parse_properties) recipe main [ 1:number:address/lookup <- copy 23 ] +parse: product: {"1": <"number" : <"address" : <>>>, "lookup": <>} //: this test we can't represent with a scenario :(code) void test_parse_comment_terminated_by_eof() { Trace_file = "parse_comment_terminated_by_eof"; load("recipe main [\n" " a:number <- copy 34\n" "]\n" "# abc"); // no newline after comment cerr << "."; // termination = success } :(scenario warn_on_redefine) % Hide_warnings = true; recipe main [ 1:number <- copy 23 ] recipe main [ 1:number <- copy 24 ] +warn: redefining recipe main :(scenario redefine_without_warning) % Hide_warnings = true; recipe main [ 1:number <- copy 23 ] recipe! main [ 1:number <- copy 24 ] -warn: redefining recipe main $warn: 0