| 109 | } |
| 110 | |
| 111 | fn format_error(error: ErrorTree<&str>, mut depth: u32, input: &str, buffer: &mut String) { |
| 112 | match error { |
| 113 | ErrorTree::Base { location, kind } => { |
| 114 | buffer |
| 115 | .write_fmt(format_args!( |
| 116 | "{}{} at {}\n", |
| 117 | indent(depth), |
| 118 | format_kind(kind), |
| 119 | format_location(input, location) |
| 120 | )) |
| 121 | .unwrap(); |
| 122 | } |
| 123 | ErrorTree::Stack { base, contexts } => { |
| 124 | let mut show_nested = true; |
| 125 | for (location, ctx) in contexts.into_iter().rev() { |
| 126 | let ctx_str = match ctx { |
| 127 | StackContext::Kind(kind) => format!("{kind:?}"), |
| 128 | StackContext::Context(ctx) => { |
| 129 | if TERMINAL_CONTEXTS.contains(&ctx) { |
| 130 | show_nested = false; |
| 131 | } |
| 132 | |
| 133 | ctx.to_string() |
| 134 | } |
| 135 | }; |
| 136 | buffer |
| 137 | .write_fmt(format_args!( |
| 138 | "{}expected {} at {}", |
| 139 | indent(depth), |
| 140 | ctx_str, |
| 141 | format_location(input, location) |
| 142 | )) |
| 143 | .unwrap(); |
| 144 | buffer.push('\n'); |
| 145 | } |
| 146 | if show_nested { |
| 147 | format_error(*base, depth + 1, input, buffer); |
| 148 | } |
| 149 | } |
| 150 | ErrorTree::Alt(mut choices) => { |
| 151 | // If an external error (`map_res`) has happened, it should have higher priority |
| 152 | // than other alternatives. |
| 153 | let external_error_index = choices.iter().position(|c| { |
| 154 | matches!( |
| 155 | c, |
| 156 | ErrorTree::Base { |
| 157 | kind: BaseErrorKind::External(_), |
| 158 | .. |
| 159 | } |
| 160 | ) |
| 161 | }); |
| 162 | |
| 163 | match external_error_index { |
| 164 | Some(index) => format_error(choices.swap_remove(index), depth, input, buffer), |
| 165 | None => { |
| 166 | let length = choices.len(); |
| 167 | buffer |
| 168 | .write_fmt(format_args!( |