From 0a2026a6bdb43568422f368846130685b46a8074 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Wed, 19 Aug 2015 22:13:15 -0700 Subject: 2039 - warn on unbalanced '[' --- 011load.cc | 48 ++++++++++++++++++++++++---------- 038scheduler.cc | 4 +-- 060string.mu | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 081run_interactive.cc | 3 ++- edit.mu | 29 +++++++++++++++++++++ 5 files changed, 139 insertions(+), 17 deletions(-) diff --git a/011load.cc b/011load.cc index 301dfdf2..8afe076f 100644 --- a/011load.cc +++ b/011load.cc @@ -63,7 +63,7 @@ recipe slurp_recipe(istream& in) { instruction curr; while (next_instruction(in, &curr)) { // End Rewrite Instruction(curr) -//? cerr << "instruction: " << curr.to_string() << '\n'; //? 2 +//? cerr << "instruction: " << curr.to_string() << '\n'; //? 3 result.steps.push_back(curr); } return result; @@ -72,27 +72,39 @@ recipe slurp_recipe(istream& in) { bool next_instruction(istream& in, instruction* curr) { in >> std::noskipws; curr->clear(); - if (in.eof()) return false; + if (in.eof()) { + raise << "0: unbalanced '[' for recipe\n" << end(); + return false; + } //? show_rest_of_stream(in); //? 1 - skip_whitespace(in); if (in.eof()) return false; + skip_whitespace(in); + if (in.eof()) { + raise << "1: unbalanced '[' for recipe\n" << end(); + return false; + } //? show_rest_of_stream(in); //? 1 - skip_whitespace_and_comments(in); if (in.eof()) return false; + skip_whitespace_and_comments(in); + if (in.eof()) { + raise << "2: unbalanced '[' for recipe\n" << end(); + return false; + } vector words; //? show_rest_of_stream(in); //? 1 - while (in.peek() != '\n') { - skip_whitespace(in); if (in.eof()) return false; + while (in.peek() != '\n' && !in.eof()) { + skip_whitespace(in); + if (in.eof()) { + raise << "3: unbalanced '[' for recipe\n" << end(); + return false; + } //? show_rest_of_stream(in); //? 1 - string word = next_word(in); if (in.eof()) return false; -//? cerr << "AAA: " << word << '\n'; //? 1 + string word = next_word(in); words.push_back(word); - skip_whitespace(in); if (in.eof()) return false; + skip_whitespace(in); } - skip_whitespace_and_comments(in); if (in.eof()) return false; - + skip_whitespace_and_comments(in); //? if (SIZE(words) == 1) cout << words.at(0) << ' ' << SIZE(words.at(0)) << '\n'; //? 1 if (SIZE(words) == 1 && words.at(0) == "]") { -//? cout << "AAA\n"; //? 1 return false; // end of recipe } @@ -100,7 +112,11 @@ bool next_instruction(istream& in, instruction* curr) { curr->is_label = true; curr->label = words.at(0); trace("parse") << "label: " << curr->label << end(); - return !in.eof(); + if (in.eof()) { + raise << "7: unbalanced '[' for recipe\n" << end(); + return false; + } + return true; } vector::iterator p = words.begin(); @@ -141,7 +157,11 @@ bool next_instruction(istream& in, instruction* curr) { for (vector::iterator p = curr->products.begin(); p != curr->products.end(); ++p) { trace("parse") << " product: " << p->to_string() << end(); } - return !in.eof(); + if (in.eof()) { + raise << "9: unbalanced '[' for recipe\n" << end(); + return false; + } + return true; } string next_word(istream& in) { diff --git a/038scheduler.cc b/038scheduler.cc index dc4d56f1..1b68682d 100644 --- a/038scheduler.cc +++ b/038scheduler.cc @@ -212,8 +212,8 @@ recipe f2 [ //: this scenario will require some careful setup in escaped C++ //: (straining our tangle capabilities to near-breaking point) :(scenario scheduler_skips_completed_routines) -% recipe_ordinal f1 = load("recipe f1 [\n1:number <- copy 0\n]").front(); -% recipe_ordinal f2 = load("recipe f2 [\n2:number <- copy 0\n]").front(); +% recipe_ordinal f1 = load("recipe f1 [\n1:number <- copy 0\n]\n").front(); +% recipe_ordinal f2 = load("recipe f2 [\n2:number <- copy 0\n]\n").front(); % Routines.push_back(new routine(f1)); // f1 meant to run % Routines.push_back(new routine(f2)); % Routines.back()->state = COMPLETED; // f2 not meant to run diff --git a/060string.mu b/060string.mu index c7c8bf71..df82ee23 100644 --- a/060string.mu +++ b/060string.mu @@ -404,6 +404,78 @@ scenario string-append-1 [ ] ] +scenario replace-character-in-string [ + run [ + 1:address:array:character/raw <- new [abc] + 1:address:array:character/raw <- string-replace 1:address:array:character/raw, 98/b, 122/z + 2:array:character/raw <- copy *1:address:array:character/raw + ] + memory-should-contain [ + 2:string <- [azc] + ] +] + +recipe string-replace [ + local-scope + s:address:array:character <- next-ingredient + oldc:character <- next-ingredient + newc:character <- next-ingredient + from:number <- next-ingredient + len:number <- length *s + i:number <- find-next s, oldc, from + done?:boolean <- greater-or-equal i, len + reply-if done?, s/same-as-ingredient:0 + dest:address:character <- index-address *s, i + *dest <- copy newc + i <- add i, 1 + s <- string-replace s, oldc, newc, i + reply s/same-as-ingredient:0 +] + +scenario replace-character-at-start [ + run [ + 1:address:array:character/raw <- new [abc] + 1:address:array:character/raw <- string-replace 1:address:array:character/raw, 97/a, 122/z + 2:array:character/raw <- copy *1:address:array:character/raw + ] + memory-should-contain [ + 2:string <- [zbc] + ] +] + +scenario replace-character-at-end [ + run [ + 1:address:array:character/raw <- new [abc] + 1:address:array:character/raw <- string-replace 1:address:array:character/raw, 99/c, 122/z + 2:array:character/raw <- copy *1:address:array:character/raw + ] + memory-should-contain [ + 2:string <- [abz] + ] +] + +scenario replace-character-missing [ + run [ + 1:address:array:character/raw <- new [abc] + 1:address:array:character/raw <- string-replace 1:address:array:character/raw, 100/d, 122/z + 2:array:character/raw <- copy *1:address:array:character/raw + ] + memory-should-contain [ + 2:string <- [abc] + ] +] + +scenario replace-all-characters [ + run [ + 1:address:array:character/raw <- new [banana] + 1:address:array:character/raw <- string-replace 1:address:array:character/raw, 97/a, 122/z + 2:array:character/raw <- copy *1:address:array:character/raw + ] + memory-should-contain [ + 2:string <- [bznznz] + ] +] + # replace underscores in first with remaining args # result:address:array:character <- interpolate template:address:array:character, ... recipe interpolate [ diff --git a/081run_interactive.cc b/081run_interactive.cc index e290024d..e97e2898 100644 --- a/081run_interactive.cc +++ b/081run_interactive.cc @@ -314,7 +314,8 @@ case RELOAD: { } Hide_warnings = true; Disable_redefine_warnings = true; - vector recipes_reloaded = load(read_mu_string(ingredients.at(0).at(0))); + string code = read_mu_string(ingredients.at(0).at(0)); + vector recipes_reloaded = load(code); for (long long int i = 0; i < SIZE(recipes_reloaded); ++i) { Name.erase(recipes_reloaded.at(i)); } diff --git a/edit.mu b/edit.mu index eb4ba61f..4d62e7c6 100644 --- a/edit.mu +++ b/edit.mu @@ -6068,6 +6068,35 @@ recipe foo [ ] ] +scenario run-shows-unbalanced-bracket-warnings [ + $close-trace + assume-screen 100/width, 15/height + # recipe is incomplete (unbalanced '[') + 1:address:array:character <- new [ +recipe foo « + x <- copy 0 +] + string-replace 1:address:array:character, 171/«, 91 # '[' + 2:address:array:character <- new [foo] + 3:address:programming-environment-data <- new-programming-environment screen:address, 1:address:array:character, 2:address:array:character + assume-console [ + press 65532 # F4 + ] + run [ + event-loop screen:address, console:address, 3:address:programming-environment-data + ] + screen-should-contain [ + . errors found run (F4) . + . ┊foo . + .recipe foo \\\[ ┊━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━. + . x <- copy 0 ┊ . + . ┊ . + .9: unbalanced '\\\[' for recipe ┊ . + .┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┊ . + . ┊ . + ] +] + scenario run-shows-get-on-non-container-warnings [ $close-trace assume-screen 100/width, 15/height -- cgit 1.4.1-2-gfad0