|
| 1 | +defmodule NimbleParsecTest.QuotedTraversal do |
| 2 | + def error(_rest, _acc, _context, _line, _offset), do: {:error, "quoted traversal error"} |
| 3 | +end |
| 4 | + |
1 | 5 | defmodule NimbleParsecTest do |
2 | 6 | use ExUnit.Case, async: true |
3 | 7 |
|
@@ -1252,9 +1256,44 @@ defmodule NimbleParsecTest do |
1252 | 1256 | end |
1253 | 1257 |
|
1254 | 1258 | describe "choice/2 combinator" do |
| 1259 | + three_ascii_chars = times(ascii_char([?a..?z, ?\n]), 3) |
| 1260 | + |
1255 | 1261 | defparsecp :simple_choice, |
1256 | 1262 | choice([ascii_char([?a..?z]), ascii_char([?A..?Z]), ascii_char([?0..?9])]) |
1257 | 1263 |
|
| 1264 | + defparsecp :choice_post_traverse, |
| 1265 | + choice([ |
| 1266 | + post_traverse(three_ascii_chars, {__MODULE__, :error_when_last_is_z, []}), |
| 1267 | + replace(three_ascii_chars, nil) |
| 1268 | + ]) |
| 1269 | + |
| 1270 | + defparsecp :choice_pre_traverse, |
| 1271 | + choice([ |
| 1272 | + pre_traverse(three_ascii_chars, {__MODULE__, :error_when_last_is_z, []}), |
| 1273 | + replace(three_ascii_chars, nil) |
| 1274 | + ]) |
| 1275 | + |
| 1276 | + defparsecp :choice_quoted_post_traverse, |
| 1277 | + choice([ |
| 1278 | + quoted_post_traverse( |
| 1279 | + three_ascii_chars, |
| 1280 | + {NimbleParsecTest.QuotedTraversal, :error, []} |
| 1281 | + ), |
| 1282 | + replace(three_ascii_chars, nil) |
| 1283 | + ]) |
| 1284 | + |
| 1285 | + defparsecp :standalone_quoted_post_traverse, |
| 1286 | + quoted_post_traverse( |
| 1287 | + three_ascii_chars, |
| 1288 | + {NimbleParsecTest.QuotedTraversal, :error, []} |
| 1289 | + ) |
| 1290 | + |
| 1291 | + defparsecp :choice_post_traverse_without_matching_fallback, |
| 1292 | + choice([ |
| 1293 | + post_traverse(three_ascii_chars, {__MODULE__, :error_when_last_is_z, []}), |
| 1294 | + string("xyz") |
| 1295 | + ]) |
| 1296 | + |
1258 | 1297 | defparsecp :choice_label, |
1259 | 1298 | choice([ascii_char([?a..?z]), ascii_char([?A..?Z]), ascii_char([?0..?9])]) |
1260 | 1299 | |> label("something") |
@@ -1304,6 +1343,31 @@ defmodule NimbleParsecTest do |
1304 | 1343 | assert simple_choice("+=") == {:error, @error, "+=", %{}, {1, 0}, 0} |
1305 | 1344 | end |
1306 | 1345 |
|
| 1346 | + test "falls back after a post-traversal error" do |
| 1347 | + assert choice_post_traverse("a\nc!") == {:ok, ~c"a\nc", "!", %{}, {2, 2}, 3} |
| 1348 | + |
| 1349 | + assert choice_post_traverse("a\nz!", context: %{source: :initial}) == |
| 1350 | + {:ok, [nil], "!", %{source: :initial}, {2, 2}, 3} |
| 1351 | + end |
| 1352 | + |
| 1353 | + test "falls back after a pre-traversal error" do |
| 1354 | + assert choice_pre_traverse("a\nz!") == {:ok, [nil], "!", %{}, {2, 2}, 3} |
| 1355 | + end |
| 1356 | + |
| 1357 | + test "falls back after a quoted traversal error" do |
| 1358 | + assert choice_quoted_post_traverse("a\nc!") == {:ok, [nil], "!", %{}, {2, 2}, 3} |
| 1359 | + |
| 1360 | + assert standalone_quoted_post_traverse("a\nc!") == |
| 1361 | + {:error, "quoted traversal error", "!", %{}, {2, 2}, 3} |
| 1362 | + end |
| 1363 | + |
| 1364 | + test "returns a parser error when no branch succeeds after a traversal error" do |
| 1365 | + assert {:error, reason, "a\nz!", %{}, {1, 0}, 0} = |
| 1366 | + choice_post_traverse_without_matching_fallback("a\nz!") |
| 1367 | + |
| 1368 | + assert is_binary(reason) |
| 1369 | + end |
| 1370 | + |
1307 | 1371 | @error "expected something" |
1308 | 1372 |
|
1309 | 1373 | test "returns ok/error with wrapping label" do |
|
0 commit comments