url unblank (url u) { if (is_concat (u) && (u[2]->t == "")) return u[1]; if (is_concat (u)) return u[1] * unblank (u[2]); if (is_or (u)) return unblank (u[1]) | unblank (u[2]); return u; }
tree evaluate_merge (tree t) { int i, n= N(t); if (n == 0) return ""; tree acc= evaluate (t[0]); if (is_concat (acc)) acc= tree_as_string (acc); for (i=1; i<n; i++) { tree add= evaluate (t[i]); if (is_atomic (acc) && (is_atomic (add) || is_concat (add))) acc= acc->label * tree_as_string (add); else if (is_tuple (acc) && is_tuple (add)) acc= acc * add; else if (is_func (acc, MACRO) && is_func (add, MACRO) && (N(acc) == N(add)) && (acc (0, N(acc)-1) == add (0, N(add)-1))) { tree r = copy (acc); tree u1= copy (acc[N(acc)-1]); tree u2= copy (add[N(add)-1]); tree u (CONCAT, u1, u2); if (u1 == "") u= u2; else if (u2 == "") u= u1; else if (is_atomic (u1) && is_atomic (u2)) u= u1->label * u2->label; r[N(r)-1]= u; acc= r; } else return evaluate_error ("bad merge"); } return acc; }
tree upgrade_above_below (tree t) { if (is_atomic (t)) return t; else if (is_concat (t)) { tree r (CONCAT); for (int i=0; i<N(t); i++) { tree x= upgrade_above_below (t[i]); if (is_concat (x)) r << A(x); else r << x; } return r; } else { int i, n= N(t); tree r (t, n); for (i=0; i<n; i++) r[i]= upgrade_above_below (t[i]); if (is_func (r, ABOVE, 2)) { if (is_func (r[0], BIG)) r= tree (CONCAT, r[0], tree (RSUP, r[1])); else if (is_concat_big (r[0])) r= tree (r[0] * tree (CONCAT, tree (RSUP, r[1]))); } if (is_func (r, BELOW, 2)) { if (is_func (r[0], BIG)) r= tree (CONCAT, r[0], tree (RSUB, r[1])); else if (is_concat_big (r[0])) r= tree (r[0] * tree (CONCAT, tree (RSUB, r[1]))); } return r; } }
bool descends (url u, url base) { if (is_or (base)) return descends (u, base[1]) || descends (u, base[2]); if (is_concat (u) && is_atomic (base)) return u[1] == base; if (is_concat (u) && is_concat (base)) return u[1] == base[1] && descends (u[2], base[2]); return false; }
static url factor_sorted (url u) { if (!is_or (u)) return u; url v= factor_sorted (u[2]); if (is_concat (u[1])) { if (is_concat (v) && (u[1][1] == v[1])) return u[1][1] * (u[1][2] | v[2]); if (is_or (v) && is_concat (v[1]) && (u[1][1] == v[1][1])) return (u[1][1] * (u[1][2] | v[1][2])) | v[2]; } return u[1] | v; }
static url expand (url u1, url u2) { if (is_or (u1)) return expand (u1[1], u2) | expand (u1[2], u2); if (is_or (u2)) return expand (u1, u2[1]) | expand (u1, u2[2]); if (is_ancestor (u2)) { if (is_concat (u1)) return u1 | expand (u1[1], u2); if (is_special_root (u1)) return u2; return u1 | u2; } if (is_concat (u2) && is_ancestor (u2[1])) return expand (expand (u1, u2[1]), u2[2]); return u1 * u2; }
static bool operator <= (url u1, url u2) { if (is_atomic (u1) && is_atomic (u2)) return u1->t->label <= u2->t->label; if (is_atomic (u1)) return true; if (is_atomic (u2)) return false; if (is_concat (u1) && is_concat (u2)) { if (u1[1] == u2[1]) return u1[2] <= u2[2]; else return u1[1] <= u2[1]; } if (is_concat (u1)) return true; if (is_concat (u2)) return false; return true; // does not matter for sorting }
url delta_sub (url base, url u) { if (is_atomic (base)) return u; if (is_concat (base) && is_concat (u) && (base[1] == u[1])) { if (is_special_root (base[1]) && is_concat (base[2]) && is_concat (u[2]) && base[2][1] != u[2][1]) return url_none (); return delta_sub (base[2], u[2]); } if (is_concat (base) && !is_semi_root (base)) return url_parent () * delta_sub (head (base), u); return url_none (); }
static bool need_tokenize (tree t, array<tree> sep) { if (!(is_apply (t) && N(t) == 2 && is_concat (t[1]))) return false; for (int i=0; i<N(t[1]); i++) if (contains (t[1][i], sep)) return true; return false; }
static void adjust_right_script (tree t, path& o1) { while (is_concat (t) && o1->item > 0 && o1->next == path (0)) { tree st= t[o1->item]; if (is_func (st, RSUB) || is_func (st, RSUP) || is_func (st, RPRIME)) { tree pt= t[o1->item-1]; if (!is_atomic (pt)) o1= path (o1->item-1, start (pt)); else { string s= pt->label; int pos= N(s); while (pos > 0) { int prev= pos; tm_char_backwards (s, prev); if (pos == N(s)); else if (is_numeric (s (prev, N(s)))); else if (is_iso_alpha (s (prev, N(s)))); else break; pos= prev; } o1= path (o1->item-1, pos); } } else break; } }
bool is_rooted_blank (url u) { return is_root_blank (u) || (is_concat (u) && is_rooted_blank (u[1])) || (is_or (u) && is_rooted_blank (u[1]) && is_rooted_blank (u[2])); }
bool is_rooted (url u, string protocol) { return is_root (u, protocol) || (is_concat (u) && is_rooted (u[1], protocol)) || (is_or (u) && is_rooted (u[1], protocol) && is_rooted (u[2], protocol)); }
tree evaluate_change_case (tree t, tree nc, bool evaluate_flag, bool first) { if (is_atomic (t)) { string s= t->label; tree r= copy (s); int i, n= N(s); bool all= true; bool up = false; bool lo = false; if (nc == "Upcase") { all= false; up= true; } else if (nc == "UPCASE") { up= true; } else if (nc == "locase") { lo= true; } for (i=0; i<n; tm_char_forwards (s, i)) if (is_iso_alpha (s[i]) && (all || (first && (i==0)))) { if (up && is_locase (s[i])) r->label[i]= upcase (s[i]); if (lo && is_upcase (s[i])) r->label[i]= locase (s[i]); } r->obs= list_observer (ip_observer (obtain_ip (t)), r->obs); return r; } else if (is_concat (t)) { int i, n= N(t); tree r (t, n); for (i=0; i<n; i++) r[i]= evaluate_change_case (t[i], nc, evaluate_flag, first && (i==0)); r->obs= list_observer (ip_observer (obtain_ip (t)), r->obs); return r; } else { if (evaluate_flag) return t; else return evaluate_change_case (evaluate (t), nc, true, first); } }
void edit_interface_rep::append_left_footer (tree& l, string env_var) { if (!is_concat (l)) l= concat (l); string i= get_init_string (env_var); string c= get_env_string (env_var); if (c != i) l << (" " * c); }
tree downgrade_brackets (tree t, bool delete_missing, bool big_dot) { if (is_atomic (t)) return t; int i, n= N(t); tree r (t, n); for (i=0; i<n; i++) r[i]= downgrade_brackets (t[i], delete_missing, big_dot); if (is_func (r, AROUND, 3)) { if (delete_missing && r[0] == "<nobracket>" && r[2] == "<nobracket>") return concat (r[0], r[1], r[2]); tree lb= downgrade_bracket (r[0], false); tree rb= downgrade_bracket (r[2], false); r= concat (lb, r[1], rb); } if (is_func (r, VAR_AROUND, 3)) { tree lb= tree (LEFT, downgrade_bracket (r[0], true)); tree rb= tree (RIGHT, downgrade_bracket (r[2], true)); if (delete_missing) { if (lb == tree (LEFT, ".") && rb == tree (RIGHT, ".")); else if (lb == tree (LEFT, ".")) lb= ""; else if (rb == tree (RIGHT, ".")) rb= ""; } r= concat (lb, r[1], rb); } if (is_func (r, BIG_AROUND, 2)) { tree op= downgrade_bracket (r[0], true); if (big_dot) r= concat (tree (BIG, op), r[1], tree (BIG, ".")); else r= concat (tree (BIG, op), r[1]); } if (is_concat (r)) r= concat_recompose (concat_decompose (r)); return r; }
url reroot (url u, string protocol) { if (is_concat (u)) return reroot (u[1], protocol) * u[2]; if (is_or (u)) return reroot (u[1], protocol) | reroot (u[2], protocol); if (is_root (u)) return url_root (protocol); return u; }
url unroot (url u) { if (is_concat (u)) return unroot (u[1]) * u[2]; if (is_or (u)) return unroot (u[1]) | unroot (u[2]); if (is_root (u)) return url_here (); return u; }
static void adjust_left_script (tree t, path& o2) { while (is_concat (t) && o2->item + 1 < N(t) && o2->next == path (1)) { tree st= t[o2->item]; if (is_func (st, LSUB) || is_func (st, LSUP) || is_func (st, LPRIME)) { tree nt= t[o2->item+1]; if (!is_atomic (nt)) o2= path (o2->item+1, end (nt)); else { string s= nt->label; int pos= 0; while (pos < N(s)) { int next= pos; tm_char_forwards (s, next); if (pos == 0); else if (is_numeric (s (0, next))); else if (is_iso_alpha (s (0, next))); else break; pos= next; } o2= path (o2->item+1, pos); } } else break; } }
static bool is_concat_big (tree t) { if (!is_concat (t) || N(t) == 0 || !is_func (t[0], BIG)) return false; for (int i=1; i<N(t); i++) if (!is_func (t[i], RSUB, 1) && !is_func (t[i], RSUP, 1)) return false; return true; }
static void make_entry (tree& D, tree t) { // cout << "Make entry " << t << "\n"; int i, j, n= N(t); for (i=0; i<n; i++) if (is_func (t[i], TUPLE, 1)) { bool flag= true; for (j=0; j<n; j++) if (is_func (t[j], TUPLE, 2) && (t[i][0] == t[j][0])) flag= false; if (flag) D << t[i][0]; } for (i=0; i<n; i++) if (is_func (t[i], TUPLE, 2) && is_tuple (t[i][1], "range", 2)) { bool flag= true; for (j=i+1; j<n; j++) if (is_func (t[j], TUPLE, 2) && is_tuple (t[j][1], "range", 2)) if ((t[i][0] == t[j][0]) && (t[i][1][1] == t[j][1][1])) { t[i][1]= tree (CONCAT, t[i][1][2], "--", t[j][1][2]); t[j]= ""; flag= false; break; } if (flag) t[i][1]= tree (CONCAT, t[i][1][2], "--?"); } hashmap<tree,tree> h (""); for (i=0; i<n; i++) if (is_func (t[i], TUPLE, 2)) { tree l= t[i][0], r= t[i][1]; if (!h->contains (l)) h (l)= r; else { tree rr= h[l]; if (rr == "") rr= r; else if (r != "") { if (!is_concat (rr)) rr= tree (CONCAT, rr); rr << ", " << r; } h (l)= rr; } } for (i=0; i<n; i++) if (is_func (t[i], TUPLE, 2)) { tree l= t[i][0]; if (h->contains (l)) { int k= N(l); tree e= compound ("index-" * as_string (k), copy (l[k-1]), h[l]); if (h[l] == "") e= compound ("index-" * as_string (k) * "*", copy (l[k-1])); D << e; h->reset (l); } } }
url glue (url u, string s) { if (is_atomic (u)) return as_url (tree (u->t->label * s)); if (is_concat (u)) return u[1] * glue (u[2], s); if (is_or (u)) return glue (u[1], s) | glue (u[2], s); failed_error << "u= " << u << "\n"; failed_error << "s= " << s << "\n"; FAILED ("can't glue string to url"); return u; }
url tail (url u) { if (is_concat (u)) { if (is_root_web (u[1]) && is_atomic (u[2])) return url_here (); return tail (u[2]); } if (is_or (u)) return tail (u[1]) | tail (u[2]); if (is_root (u)) return url_here (); return u; }
static tree remove_all_indent (tree t) { if (is_atomic (t) || is_compound (t, "coqdoc-verbatim") || is_compound (t, "coq-comment")) return t; if (is_compound (t, "coq-indent")) return ""; int i, n= N(t); tree r (L(t)); for (i=0; i<n; i++) if (!is_compound (t[i], "coq-indent", 1)) r << t[i]; if (N(r) == 0 && (is_document (r) || is_concat (r))) r= ""; else if (N(r) == 1 && (is_document (r) || is_concat (r))) r= r[0]; return r; }
void edit_select_rep::select_enlarge_text () { path p= common (start_p, end_p); if (start_p == end_p) p= path_up (p); tree st= subtree (et, p); ASSERT (is_atomic (st), "non textual tree"); string s= st->label; string mode= get_env_string (MODE); int i1= last_item (start_p), j1= i1; int i2= last_item (end_p), j2= i2; path q= path_up (p); if (mode == "text" || mode == "src") { int i, f= 4; if (i1 > 0) { i= i1; tm_char_backwards (s, i); f= min (f, breaking_force (s[i])); } if (i2 < N(s)) f= min (f, breaking_force (s[i2])); while (i1 > 0) { i= i1; tm_char_backwards (s, i); if (breaking_force (s[i]) > f) break; i1= i; } while (i2 < N(s)) { if (breaking_force (s[i2]) > f) break; tm_char_forwards (s, i2); } if (i1 < i2 && (i1 != j1 || i2 != j2)) { if (is_concat (subtree (et, q)) && i1 == 0 && i2 == N(s)) select (q * 0, q * 1); else select (p * i1, p * i2); return; } } if (is_concat (subtree (et, q)) || (i1 == 0 && i2 == N(s))) select (q * 0, q * 1); else select (p * 0, p * N(s)); }
static string serialize (tree t) { if (is_atomic (t)) return t->label; else if (is_concat (t)) { string s; for (int i=0; i<N(t); i++) { tree u= t[i]; while (is_concat (u) && N(u) > 0) u= u[0]; if (i > 0 && is_compound (u, "render-key")) if (!is_atomic (t[i-1]) || !ends (t[i-1]->label, " ")) { if (use_macos_fonts () || gui_is_qt ()) s << " "; else s << " "; } s << serialize (t[i]); } return s; } else if (is_compound (t, "render-key", 1)) return serialize (t[0]); else if (is_func (t, WITH)) return serialize (t[N(t)-1]); else if (is_compound (t, "math", 1)) return serialize (t[0]); else if (is_compound (t, "op", 1)) { t= t[0]; if (gui_is_qt ()) { if (t == "<leftarrow>") return "Left"; if (t == "<rightarrow>") return "Right"; if (t == "<uparrow>") return "Up"; if (t == "<downarrow>") return "Down"; } else { if (t == "<leftarrow>") return "left"; if (t == "<rightarrow>") return "right"; if (t == "<uparrow>") return "up"; if (t == "<downarrow>") return "down"; } return serialize (t); } else return ""; }
static void restricted_exec (edit_env env, tree t, int end) { if (is_func (t, ASSIGN, 2) && end == 2) env->exec (t); else if (is_document (t) || is_concat (t)) for (int i=0; i < min (end, 10); i++) restricted_exec (env, t[i], arity (t[i])); else if (is_compound (t, "hide-preamble", 1) || is_compound (t, "show-preamble", 1)) env->exec (t[0]); }
url unglue (url u, int nr) { if (is_atomic (u)) return as_url (tree (u->t->label (0, max (N(u->t->label) - nr, 0)))); if (is_concat (u)) return u[1] * unglue (u[2], nr); if (is_or (u)) return unglue (u[1], nr) | unglue (u[2], nr); failed_error << "u = " << u << "\n"; failed_error << "nr= " << nr << "\n"; FAILED ("can't unglue from url"); return u; }
string get_root (url u) { if (is_concat (u)) return get_root (u[1]); if (is_or (u)) { string s1= get_root (u[1]); string s2= get_root (u[2]); if (s1 == s2) return s1; else return ""; } if (is_root (u)) return u[1]->t->label; return ""; }
void edit_select_rep::cut (path p1, path p2) { path p = common (p1, p2); tree st= subtree (et, p); raw_cut (p1, p2); if (!is_func (st, TFORMAT) && !is_func (st, TABLE) && !is_func (st, ROW) && !is_document (subtree (et, p)) && is_concat (subtree (et, path_up (p)))) correct_concat (path_up (p)); }
static void append_commands (tree &t, tree u) { if (t == "") t= u; else if (is_atomic (t)) t= concat (trim_spaces_right (t), u); else if (is_document (u)) { if (N(u) > 0) { append_commands (t, u[0]); u[0]= t; t= u; } } else if (is_document (t)) { int last= N(t)-1; append_commands (t[last], u); } else if (is_concat (t) && is_concat (u)) t << A(u); else if (is_concat (t)) t << u; }