From 201458e3bd2f1d79a0ea0b853552e9df267e92b1 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Mon, 26 Dec 2016 20:44:10 -0800 Subject: 3713 - cross-link calls with definitions in html --- html/011load.cc.html | 208 +++++++++++++++++++++++++-------------------------- 1 file changed, 104 insertions(+), 104 deletions(-) (limited to 'html/011load.cc.html') diff --git a/html/011load.cc.html b/html/011load.cc.html index e1f6bc62..5a715d13 100644 --- a/html/011load.cc.html +++ b/html/011load.cc.html @@ -65,10 +65,10 @@ if ('onhashchange' in window) { 5 6 :(scenarios load) // use 'load' instead of 'run' in all scenarios in this layer 7 :(scenario first_recipe) - 8 def main [ + 8 def main [ 9 1:number <- copy 23 10 ] - 11 +parse: instruction: copy + 11 +parse: instruction: copy 12 +parse: ingredient: {23: "literal"} 13 +parse: product: {1: "number"} 14 @@ -82,165 +82,165 @@ if ('onhashchange' in window) { 22 vector<recipe_ordinal> load(istream& in) { 23 in >> std::noskipws; 24 vector<recipe_ordinal> result; - 25 while (has_data(in)) { - 26 skip_whitespace_and_comments(in); + 25 while (has_data(in)) { + 26 skip_whitespace_and_comments(in); 27 if (!has_data(in)) break; - 28 string command = next_word(in); + 28 string command = next_word(in); 29 if (command.empty()) { 30 assert(!has_data(in)); 31 break; 32 } 33 // Command Handlers 34 if (command == "recipe" || command == "def") { - 35 recipe_ordinal r = slurp_recipe(in); + 35 recipe_ordinal r = slurp_recipe(in); 36 if (r > 0) result.push_back(r); 37 } 38 else if (command == "recipe!" || command == "def!") { 39 Disable_redefine_checks = true; - 40 recipe_ordinal r = slurp_recipe(in); + 40 recipe_ordinal r = slurp_recipe(in); 41 if (r > 0) result.push_back(r); 42 Disable_redefine_checks = false; 43 } 44 // End Command Handlers 45 else { - 46 raise << "unknown top-level command: " << command << '\n' << end(); + 46 raise << "unknown top-level command: " << command << '\n' << end(); 47 } 48 } 49 return result; 50 } 51 52 // return the recipe ordinal slurped, or -1 if it failed - 53 int slurp_recipe(istream& in) { - 54 recipe result; - 55 result.name = next_word(in); + 53 int slurp_recipe(istream& in) { + 54 recipe result; + 55 result.name = next_word(in); 56 if (result.name.empty()) { 57 assert(!has_data(in)); - 58 raise << "file ended with 'recipe'\n" << end(); + 58 raise << "file ended with 'recipe'\n" << end(); 59 return -1; 60 } 61 // End Load Recipe Name 62 skip_whitespace_but_not_newline(in); 63 // End Recipe Refinements 64 if (result.name.empty()) - 65 raise << "empty result.name\n" << end(); - 66 trace(9991, "parse") << "--- defining " << result.name << end(); + 65 raise << "empty result.name\n" << end(); + 66 trace(9991, "parse") << "--- defining " << result.name << end(); 67 if (!contains_key(Recipe_ordinal, result.name)) - 68 put(Recipe_ordinal, result.name, Next_recipe_ordinal++); - 69 if (Recipe.find(get(Recipe_ordinal, result.name)) != Recipe.end()) { - 70 trace(9991, "parse") << "already exists" << end(); - 71 if (should_check_for_redefine(result.name)) - 72 raise << "redefining recipe " << result.name << "\n" << end(); + 68 put(Recipe_ordinal, result.name, Next_recipe_ordinal++); + 69 if (Recipe.find(get(Recipe_ordinal, result.name)) != Recipe.end()) { + 70 trace(9991, "parse") << "already exists" << end(); + 71 if (should_check_for_redefine(result.name)) + 72 raise << "redefining recipe " << result.name << "\n" << end(); 73 Recipe.erase(get(Recipe_ordinal, result.name)); 74 } - 75 slurp_body(in, result); + 75 slurp_body(in, result); 76 // End Recipe Body(result) - 77 put(Recipe, get(Recipe_ordinal, result.name), result); + 77 put(Recipe, get(Recipe_ordinal, result.name), result); 78 return get(Recipe_ordinal, result.name); 79 } 80 - 81 void slurp_body(istream& in, recipe& result) { + 81 void slurp_body(istream& in, recipe& result) { 82 in >> std::noskipws; 83 skip_whitespace_but_not_newline(in); 84 if (in.get() != '[') - 85 raise << result.name << ": recipe body must begin with '['\n" << end(); - 86 skip_whitespace_and_comments(in); // permit trailing comment after '[' - 87 instruction curr; - 88 while (next_instruction(in, &curr)) { + 85 raise << result.name << ": recipe body must begin with '['\n" << end(); + 86 skip_whitespace_and_comments(in); // permit trailing comment after '[' + 87 instruction curr; + 88 while (next_instruction(in, &curr)) { 89 curr.original_string = to_original_string(curr); 90 // End Rewrite Instruction(curr, recipe result) - 91 trace(9992, "load") << "after rewriting: " << to_string(curr) << end(); + 91 trace(9992, "load") << "after rewriting: " << to_string(curr) << end(); 92 if (!curr.is_empty()) result.steps.push_back(curr); 93 } 94 } 95 - 96 bool next_instruction(istream& in, instruction* curr) { - 97 curr->clear(); - 98 skip_whitespace_and_comments(in); + 96 bool next_instruction(istream& in, instruction* curr) { + 97 curr->clear(); + 98 skip_whitespace_and_comments(in); 99 if (!has_data(in)) { -100 raise << "incomplete recipe at end of file (0)\n" << end(); +100 raise << "incomplete recipe at end of file (0)\n" << end(); 101 return false; 102 } 103 104 vector<string> words; -105 while (has_data(in) && in.peek() != '\n') { +105 while (has_data(in) && in.peek() != '\n') { 106 skip_whitespace_but_not_newline(in); 107 if (!has_data(in)) { -108 raise << "incomplete recipe at end of file (1)\n" << end(); +108 raise << "incomplete recipe at end of file (1)\n" << end(); 109 return false; 110 } -111 string word = next_word(in); +111 string word = next_word(in); 112 if (word.empty()) { 113 assert(!has_data(in)); -114 raise << "incomplete recipe at end of file (2)\n" << end(); +114 raise << "incomplete recipe at end of file (2)\n" << end(); 115 return false; 116 } 117 words.push_back(word); 118 skip_whitespace_but_not_newline(in); 119 } -120 skip_whitespace_and_comments(in); -121 if (SIZE(words) == 1 && words.at(0) == "]") +120 skip_whitespace_and_comments(in); +121 if (SIZE(words) == 1 && words.at(0) == "]") 122 return false; // end of recipe 123 -124 if (SIZE(words) == 1 && is_label_word(words.at(0))) { +124 if (SIZE(words) == 1 && is_label_word(words.at(0))) { 125 curr->is_label = true; 126 curr->label = words.at(0); -127 trace(9993, "parse") << "label: " << curr->label << end(); +127 trace(9993, "parse") << "label: " << curr->label << end(); 128 if (!has_data(in)) { -129 raise << "incomplete recipe at end of file (3)\n" << end(); +129 raise << "incomplete recipe at end of file (3)\n" << end(); 130 return false; 131 } 132 return true; 133 } 134 135 vector<string>::iterator p = words.begin(); -136 if (find(words.begin(), words.end(), "<-") != words.end()) { +136 if (find(words.begin(), words.end(), "<-") != words.end()) { 137 for (; *p != "<-"; ++p) 138 curr->products.push_back(reagent(*p)); 139 ++p; // skip <- 140 } 141 -142 if (p == words.end()) { -143 raise << "instruction prematurely ended with '<-'\n" << end(); +142 if (p == words.end()) { +143 raise << "instruction prematurely ended with '<-'\n" << end(); 144 return false; 145 } 146 curr->old_name = curr->name = *p; ++p; 147 // curr->operation will be set at transform time 148 -149 for (; p != words.end(); ++p) +149 for (; p != words.end(); ++p) 150 curr->ingredients.push_back(reagent(*p)); 151 -152 trace(9993, "parse") << "instruction: " << curr->name << end(); -153 trace(9993, "parse") << " number of ingredients: " << SIZE(curr->ingredients) << end(); -154 for (vector<reagent>::iterator p = curr->ingredients.begin(); p != curr->ingredients.end(); ++p) -155 trace(9993, "parse") << " ingredient: " << to_string(*p) << end(); -156 for (vector<reagent>::iterator p = curr->products.begin(); p != curr->products.end(); ++p) -157 trace(9993, "parse") << " product: " << to_string(*p) << end(); +152 trace(9993, "parse") << "instruction: " << curr->name << end(); +153 trace(9993, "parse") << " number of ingredients: " << SIZE(curr->ingredients) << end(); +154 for (vector<reagent>::iterator p = curr->ingredients.begin(); p != curr->ingredients.end(); ++p) +155 trace(9993, "parse") << " ingredient: " << to_string(*p) << end(); +156 for (vector<reagent>::iterator p = curr->products.begin(); p != curr->products.end(); ++p) +157 trace(9993, "parse") << " product: " << to_string(*p) << end(); 158 if (!has_data(in)) { -159 raise << "9: unbalanced '[' for recipe\n" << end(); +159 raise << "9: unbalanced '[' for recipe\n" << end(); 160 return false; 161 } 162 return true; 163 } 164 165 // can return empty string -- only if `in` has no more data -166 string next_word(istream& in) { +166 string next_word(istream& in) { 167 skip_whitespace_but_not_newline(in); 168 // End next_word Special-cases 169 ostringstream out; -170 slurp_word(in, out); -171 skip_whitespace_and_comments_but_not_newline(in); +170 slurp_word(in, out); +171 skip_whitespace_and_comments_but_not_newline(in); 172 string result = out.str(); -173 if (result != "[" && ends_with(result, '[')) -174 raise << "insert a space before '[' in '" << result << "'\n" << end(); +173 if (result != "[" && ends_with(result, '[')) +174 raise << "insert a space before '[' in '" << result << "'\n" << end(); 175 return result; 176 } 177 -178 bool is_label_word(const string& word) { +178 bool is_label_word(const string& word) { 179 if (word.empty()) return false; // error raised elsewhere 180 return !isalnum(word.at(0)) && string("$_*@&,=-[]()").find(word.at(0)) == string::npos; 181 } 182 -183 bool ends_with(const string& s, const char c) { +183 bool ends_with(const string& s, const char c) { 184 if (s.empty()) return false; 185 return *s.rbegin() == c; 186 } @@ -249,9 +249,9 @@ if ('onhashchange' in window) { 189 // word boundaries 190 extern const string Terminators("(){}"); 191 :(code) -192 void slurp_word(istream& in, ostream& out) { +192 void slurp_word(istream& in, ostream& out) { 193 char c; -194 if (has_data(in) && Terminators.find(in.peek()) != string::npos) { +194 if (has_data(in) && Terminators.find(in.peek()) != string::npos) { 195 in >> c; 196 out << c; 197 return; @@ -265,40 +265,40 @@ if ('onhashchange' in window) { 205 } 206 } 207 -208 void skip_whitespace_and_comments(istream& in) { +208 void skip_whitespace_and_comments(istream& in) { 209 while (true) { 210 if (!has_data(in)) break; 211 if (isspace(in.peek())) in.get(); 212 else if (Ignore.find(in.peek()) != string::npos) in.get(); -213 else if (in.peek() == '#') skip_comment(in); +213 else if (in.peek() == '#') skip_comment(in); 214 else break; 215 } 216 } 217 218 // confusing; move to the next line only to skip a comment, but never otherwise -219 void skip_whitespace_and_comments_but_not_newline(istream& in) { +219 void skip_whitespace_and_comments_but_not_newline(istream& in) { 220 while (true) { 221 if (!has_data(in)) break; 222 if (in.peek() == '\n') break; 223 if (isspace(in.peek())) in.get(); 224 else if (Ignore.find(in.peek()) != string::npos) in.get(); -225 else if (in.peek() == '#') skip_comment(in); +225 else if (in.peek() == '#') skip_comment(in); 226 else break; 227 } 228 } 229 -230 void skip_comment(istream& in) { -231 if (has_data(in) && in.peek() == '#') { +230 void skip_comment(istream& in) { +231 if (has_data(in) && in.peek() == '#') { 232 in.get(); -233 while (has_data(in) && in.peek() != '\n') in.get(); +233 while (has_data(in) && in.peek() != '\n') in.get(); 234 } 235 } 236 237 :(scenario recipe_instead_of_def) -238 recipe main [ +238 recipe main [ 239 1:number <- copy 23 240 ] -241 +parse: instruction: copy +241 +parse: instruction: copy 242 +parse: ingredient: {23: "literal"} 243 +parse: product: {1: "number"} 244 @@ -307,112 +307,112 @@ if ('onhashchange' in window) { 247 def f1 [ 248 ] 249 # this comment will go through to 'load' -250 def main [ +250 def main [ 251 1:number <- copy 23 252 ] -253 +parse: instruction: copy +253 +parse: instruction: copy 254 +parse: ingredient: {23: "literal"} 255 +parse: product: {1: "number"} 256 257 :(scenario parse_comment_amongst_instruction) -258 def main [ +258 def main [ 259 # comment 260 1:number <- copy 23 261 ] -262 +parse: instruction: copy +262 +parse: instruction: copy 263 +parse: ingredient: {23: "literal"} 264 +parse: product: {1: "number"} 265 266 :(scenario parse_comment_amongst_instruction_2) -267 def main [ +267 def main [ 268 # comment 269 1:number <- copy 23 270 # comment 271 ] -272 +parse: instruction: copy +272 +parse: instruction: copy 273 +parse: ingredient: {23: "literal"} 274 +parse: product: {1: "number"} 275 276 :(scenario parse_comment_amongst_instruction_3) -277 def main [ +277 def main [ 278 1:number <- copy 23 279 # comment 280 2:number <- copy 23 281 ] -282 +parse: instruction: copy +282 +parse: instruction: copy 283 +parse: ingredient: {23: "literal"} 284 +parse: product: {1: "number"} -285 +parse: instruction: copy +285 +parse: instruction: copy 286 +parse: ingredient: {23: "literal"} 287 +parse: product: {2: "number"} 288 289 :(scenario parse_comment_after_instruction) -290 def main [ +290 def main [ 291 1:number <- copy 23 # comment 292 ] -293 +parse: instruction: copy +293 +parse: instruction: copy 294 +parse: ingredient: {23: "literal"} 295 +parse: product: {1: "number"} 296 297 :(scenario parse_label) -298 def main [ +298 def main [ 299 +foo 300 ] 301 +parse: label: +foo 302 303 :(scenario parse_dollar_as_recipe_name) -304 def main [ +304 def main [ 305 $foo 306 ] -307 +parse: instruction: $foo +307 +parse: instruction: $foo 308 309 :(scenario parse_multiple_properties) -310 def main [ +310 def main [ 311 1:number <- copy 23/foo:bar:baz 312 ] -313 +parse: instruction: copy +313 +parse: instruction: copy 314 +parse: ingredient: {23: "literal", "foo": ("bar" "baz")} 315 +parse: product: {1: "number"} 316 317 :(scenario parse_multiple_products) -318 def main [ +318 def main [ 319 1:number, 2:number <- copy 23 320 ] -321 +parse: instruction: copy +321 +parse: instruction: copy 322 +parse: ingredient: {23: "literal"} 323 +parse: product: {1: "number"} 324 +parse: product: {2: "number"} 325 326 :(scenario parse_multiple_ingredients) -327 def main [ +327 def main [ 328 1:number, 2:number <- copy 23, 4:number 329 ] -330 +parse: instruction: copy +330 +parse: instruction: copy 331 +parse: ingredient: {23: "literal"} 332 +parse: ingredient: {4: "number"} 333 +parse: product: {1: "number"} 334 +parse: product: {2: "number"} 335 336 :(scenario parse_multiple_types) -337 def main [ -338 1:number, 2:address:number <- copy 23, 4:number +337 def main [ +338 1:number, 2:address:number <- copy 23, 4:number 339 ] -340 +parse: instruction: copy +340 +parse: instruction: copy 341 +parse: ingredient: {23: "literal"} 342 +parse: ingredient: {4: "number"} 343 +parse: product: {1: "number"} 344 +parse: product: {2: ("address" "number")} 345 346 :(scenario parse_properties) -347 def main [ -348 1:address:number/lookup <- copy 23 +347 def main [ +348 1:address:number/lookup <- copy 23 349 ] 350 +parse: product: {1: ("address" "number"), "lookup": ()} 351 352 //: this test we can't represent with a scenario 353 :(code) -354 void test_parse_comment_terminated_by_eof() { -355 load("recipe main [\n" +354 void test_parse_comment_terminated_by_eof() { +355 load("recipe main [\n" 356 " a:number <- copy 34\n" 357 "]\n" 358 "# abc"); // no newline after comment @@ -434,34 +434,34 @@ if ('onhashchange' in window) { 374 :(before "End Setup") 375 Disable_redefine_checks = false; 376 :(code) -377 bool should_check_for_redefine(const string& recipe_name) { +377 bool should_check_for_redefine(const string& recipe_name) { 378 if (Disable_redefine_checks) return false; 379 return true; 380 } 381 382 :(scenario forbid_redefining_recipes) 383 % Hide_errors = true; -384 def main [ +384 def main [ 385 1:number <- copy 23 386 ] -387 def main [ +387 def main [ 388 1:number <- copy 24 389 ] -390 +error: redefining recipe main +390 +error: redefining recipe main 391 392 :(scenario permit_forcibly_redefining_recipes) -393 def main [ +393 def main [ 394 1:number <- copy 23 395 ] -396 def! main [ +396 def! main [ 397 1:number <- copy 24 398 ] -399 -error: redefining recipe main +399 -error: redefining recipe main 400 $error: 0 401 402 :(code) 403 // for debugging -404 void show_rest_of_stream(istream& in) { +404 void show_rest_of_stream(istream& in) { 405 cerr << '^'; 406 char c; 407 while (in >> c) -- cgit 1.4.1-2-gfad0