Skip to content

Commit f90aecb

Browse files
authored
Fixed a collection reader bug with trailing end tokens separated by comments (#520)
* Fixed a collection reader bug with trailing end tokens separated by comments * Remove the unused _consume_whitespace function
1 parent 89bedcd commit f90aecb

File tree

3 files changed

+105
-12
lines changed

3 files changed

+105
-12
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3232
* Fixed a bug where the `quote` special form allowed more than one argument and raised an unintended exception when no argument was provided (#497)
3333
* Fixed a bug where compiler options specified via command-line argument or environment variable were not honored by the importer (#507)
3434
* Fixed a bug where private Vars from other Namespaces could be referenced if the Namespace was aliased when it was required (#514)
35+
* Fixed a bug where collections with trailing end tokens separated from the collection only by a comment (#520)
3536

3637
## [v0.1.dev12] - 2020-01-26
3738
### Added

src/basilisp/lang/reader.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -572,12 +572,6 @@ def _read_coll(
572572
coll.append(elem)
573573

574574

575-
def _consume_whitespace(reader: StreamReader) -> None:
576-
token = reader.peek()
577-
while whitespace_chars.match(token):
578-
token = reader.advance()
579-
580-
581575
@_with_loc
582576
def _read_list(ctx: ReaderContext) -> llist.List:
583577
"""Read a list element from the input stream."""
@@ -617,14 +611,18 @@ def __read_map_elems(ctx: ReaderContext) -> Iterable[RawReaderForm]:
617611
reader conditionals."""
618612
reader = ctx.reader
619613
while True:
620-
if reader.peek() == "}":
614+
token = reader.peek()
615+
if token == "":
616+
raise ctx.eof_error("Unexpected EOF in map}")
617+
if whitespace_chars.match(token):
618+
reader.advance()
619+
continue
620+
if token == "}":
621621
reader.next_token()
622622
return
623623
v = _read_next(ctx)
624624
if v is COMMENT or isinstance(v, Comment):
625625
continue
626-
elif v is ctx.eof:
627-
raise ctx.eof_error("Unexpected EOF in map")
628626
elif _should_splice_reader_conditional(ctx, v):
629627
assert isinstance(v, ReaderConditional)
630628
selected_feature = v.select_feature(ctx.reader_features)
@@ -1315,7 +1313,7 @@ def _read_comment(ctx: ReaderContext) -> LispReaderForm:
13151313
token = reader.peek()
13161314
if newline_chars.match(token):
13171315
reader.advance()
1318-
return _read_next(ctx)
1316+
return COMMENT
13191317
if token == "":
13201318
return ctx.eof
13211319
reader.advance()
@@ -1333,6 +1331,15 @@ def _read_next_consuming_comment(ctx: ReaderContext) -> RawReaderForm:
13331331
return v
13341332

13351333

1334+
def _read_next_consuming_whitespace(ctx: ReaderContext) -> LispReaderForm:
1335+
"""Read the next full form from the input stream, consuming any whitespace."""
1336+
reader = ctx.reader
1337+
token = reader.peek()
1338+
while whitespace_chars.match(token):
1339+
token = reader.next_token()
1340+
return _read_next(ctx)
1341+
1342+
13361343
def _read_next(ctx: ReaderContext) -> LispReaderForm: # noqa: C901 MC0001
13371344
"""Read the next full form from the input stream."""
13381345
reader = ctx.reader
@@ -1346,8 +1353,7 @@ def _read_next(ctx: ReaderContext) -> LispReaderForm: # noqa: C901 MC0001
13461353
elif begin_num_chars.match(token):
13471354
return _read_num(ctx)
13481355
elif whitespace_chars.match(token):
1349-
reader.next_token()
1350-
return _read_next(ctx)
1356+
return _read_next_consuming_whitespace(ctx)
13511357
elif token == ":":
13521358
return _read_kw(ctx)
13531359
elif token == '"':

tests/basilisp/reader_test.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,27 @@ def test_vector():
376376
1.4, kw.keyword("a"), "string"
377377
)
378378

379+
assert read_str_first("[\n]") == vec.Vector.empty()
380+
assert read_str_first("[ :a\n :b\n]") == vec.v(
381+
kw.keyword("a"), kw.keyword("b")
382+
)
383+
assert read_str_first("[:a :b\n]") == vec.v(kw.keyword("a"), kw.keyword("b"))
384+
assert read_str_first("[:a :b ]") == vec.v(kw.keyword("a"), kw.keyword("b"))
385+
assert read_str_first("[\n;;comment\n]") == vec.Vector.empty()
386+
assert read_str_first("[:a :b\n;;comment\n]") == vec.v(
387+
kw.keyword("a"), kw.keyword("b")
388+
)
389+
assert read_str_first("[:a \n;;comment\n :b]") == vec.v(
390+
kw.keyword("a"), kw.keyword("b")
391+
)
392+
assert read_str_first("[\n#_[:a :b]\n]") == vec.Vector.empty()
393+
assert read_str_first("[:a :b\n#_[:a :b]\n]") == vec.v(
394+
kw.keyword("a"), kw.keyword("b")
395+
)
396+
assert read_str_first("[:a \n#_[:a :b]\n :b]") == vec.v(
397+
kw.keyword("a"), kw.keyword("b")
398+
)
399+
379400

380401
def test_list():
381402
with pytest.raises(reader.SyntaxError):
@@ -393,6 +414,27 @@ def test_list():
393414
)
394415
assert read_str_first("(- -1 2)") == llist.l(sym.symbol("-"), -1, 2)
395416

417+
assert read_str_first("(\n)") == llist.List.empty()
418+
assert read_str_first("( :a\n :b\n)") == llist.l(
419+
kw.keyword("a"), kw.keyword("b")
420+
)
421+
assert read_str_first("(:a :b\n)") == llist.l(kw.keyword("a"), kw.keyword("b"))
422+
assert read_str_first("(:a :b )") == llist.l(kw.keyword("a"), kw.keyword("b"))
423+
assert read_str_first("(\n;;comment\n)") == llist.List.empty()
424+
assert read_str_first("(:a :b\n;;comment\n)") == llist.l(
425+
kw.keyword("a"), kw.keyword("b")
426+
)
427+
assert read_str_first("(:a \n;;comment\n :b)") == llist.l(
428+
kw.keyword("a"), kw.keyword("b")
429+
)
430+
assert read_str_first("(\n#_[:a :b]\n)") == llist.List.empty()
431+
assert read_str_first("(:a :b\n#_[:a :b]\n)") == llist.l(
432+
kw.keyword("a"), kw.keyword("b")
433+
)
434+
assert read_str_first("(:a \n#_[:a :b]\n :b)") == llist.l(
435+
kw.keyword("a"), kw.keyword("b")
436+
)
437+
396438

397439
def test_set():
398440
with pytest.raises(reader.SyntaxError):
@@ -408,6 +450,27 @@ def test_set():
408450
kw.keyword("a"), 1, "some string"
409451
)
410452

453+
assert read_str_first("#{\n}") == lset.Set.empty()
454+
assert read_str_first("#{ :a\n :b\n}") == lset.s(
455+
kw.keyword("a"), kw.keyword("b")
456+
)
457+
assert read_str_first("#{:a :b\n}") == lset.s(kw.keyword("a"), kw.keyword("b"))
458+
assert read_str_first("#{:a :b }") == lset.s(kw.keyword("a"), kw.keyword("b"))
459+
assert read_str_first("#{\n;;comment\n}") == lset.Set.empty()
460+
assert read_str_first("#{:a :b\n;;comment\n}") == lset.s(
461+
kw.keyword("a"), kw.keyword("b")
462+
)
463+
assert read_str_first("#{:a \n;;comment\n :b}") == lset.s(
464+
kw.keyword("a"), kw.keyword("b")
465+
)
466+
assert read_str_first("#{\n#_[:a :b]\n}") == lset.Set.empty()
467+
assert read_str_first("#{:a :b\n#_[:a :b]\n}") == lset.s(
468+
kw.keyword("a"), kw.keyword("b")
469+
)
470+
assert read_str_first("#{:a \n#_[:a :b]\n :b}") == lset.s(
471+
kw.keyword("a"), kw.keyword("b")
472+
)
473+
411474
with pytest.raises(reader.SyntaxError):
412475
read_str_first("#{:a :b :b}")
413476

@@ -422,6 +485,29 @@ def test_map():
422485
{kw.keyword("a"): 1, kw.keyword("b"): "string"}
423486
)
424487

488+
assert read_str_first("{\n}") == lmap.Map.empty()
489+
assert read_str_first("{ :a\n :b\n}") == lmap.map(
490+
{kw.keyword("a"): kw.keyword("b")}
491+
)
492+
assert read_str_first("{:a :b\n}") == lmap.map({kw.keyword("a"): kw.keyword("b")})
493+
assert read_str_first("{:a :b }") == lmap.map(
494+
{kw.keyword("a"): kw.keyword("b")}
495+
)
496+
assert read_str_first("{\n;;comment\n}") == lmap.Map.empty()
497+
assert read_str_first("{:a :b\n;;comment\n}") == lmap.map(
498+
{kw.keyword("a"): kw.keyword("b")}
499+
)
500+
assert read_str_first("{:a \n;;comment\n :b}") == lmap.map(
501+
{kw.keyword("a"): kw.keyword("b")}
502+
)
503+
assert read_str_first("{\n#_[:a :b]\n}") == lmap.Map.empty()
504+
assert read_str_first("{:a :b\n#_[:a :b]\n}") == lmap.map(
505+
{kw.keyword("a"): kw.keyword("b")}
506+
)
507+
assert read_str_first("{:a \n#_[:a :b]\n :b}") == lmap.map(
508+
{kw.keyword("a"): kw.keyword("b")}
509+
)
510+
425511
with pytest.raises(reader.SyntaxError):
426512
read_str_first("{:a 1 :b 2 :a 3}")
427513

0 commit comments

Comments
 (0)