Skip to content

feat(parser): Add #{...} set literal syntax support (Phase 1 of #164)#166

Merged
andreasronge merged 2 commits intomainfrom
claude/issue-165-20251209-212843
Dec 9, 2025
Merged

feat(parser): Add #{...} set literal syntax support (Phase 1 of #164)#166
andreasronge merged 2 commits intomainfrom
claude/issue-165-20251209-212843

Conversation

@andreasronge
Copy link
Copy Markdown
Owner

Summary

This implements Phase 1 (Parser) of the Set Literal epic (#164). LLMs commonly emit Clojure-style #{...} set literal syntax, but PTC-Lisp previously failed to parse it. This PR adds parser support to eliminate a common source of LLM-generated parse errors.

Key Changes:

  • Add :set combinator to match #{ followed by zero or more expressions followed by }
  • Update :expr choice list to include :set BEFORE :map_literal for correct precedence
  • Add build_set/1 helper in ParserHelpers
  • Add comprehensive parser tests covering success and error cases

Tests Added:

  • Empty set: #{}
  • Sets with elements: #{1 2 3}
  • Sets with keywords: #{:a :b}
  • Nested sets: #{#{1 2}}
  • Sets containing vectors: #{[1 2]}
  • Whitespace and comma handling: #{ 1 , 2 , 3 }
  • Error case: unclosed sets
  • Error case: space between # and {

All 979 tests passing including 6 new set parser tests.

Closes #165

🤖 Generated with Claude Code

Implement Phase 1 of set literal support (issue #164) by adding parser support
for Clojure-style `#{...}` set literal syntax.

Changes:
- Add :set combinator to parser that matches `#{` followed by expressions
- Update :expr choice list to include :set before :map_literal (critical for
  correct precedence - must try `#{` before `{`)
- Add build_set/1 helper function to ParserHelpers
- Add comprehensive parser tests for empty sets, sets with various element types,
  whitespace/comma handling, nested sets, and error cases

Tests now validate:
- Empty set: `#{}`
- Sets with numbers, keywords, vectors: `#{1 :a [1 2]}`
- Nested sets: `#{#{1 2}}`
- Whitespace and commas: `#{ 1 , 2 , 3 }`
- Error cases: unclosed sets, space between `#` and `{`

All 979 tests passing.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Dec 9, 2025

PR Review: feat(parser): Add #{...} set literal syntax support (Phase 1 of #164)

Summary

This PR implements Phase 1 (Parser) of the Set Literal epic (#164), adding support for Clojure-style #{...} set literal syntax to PTC-Lisp. The implementation is clean, follows existing patterns, and matches the specification in docs/ptc-lisp-set-literal-plan.md.

What's Good

  1. Follows existing patterns exactly - The build_set/1 helper mirrors build_vector/1, and the :set combinator follows the same structure as :vector and :map_literal

  2. Correct combinator ordering - Critical requirement met: parsec(:set) appears BEFORE parsec(:map_literal) in the :expr choice list (lines 169-170), ensuring #{ is matched before {

  3. Clever string escaping - Using string("#" <> "{") instead of string("#{") avoids Elixir string interpolation issues during compilation

  4. Comprehensive test coverage - 8 test cases covering:

    • Empty set, set with elements, set with keywords
    • Nested sets, sets containing vectors
    • Whitespace and comma handling
    • Error cases: unclosed set, space between # and {
  5. Tests placed in appropriate describe block - Set tests are grouped with other collection tests in the "collections" describe block, which is logical

Issues (Must Fix)

None - the implementation is complete and correct for Phase 1 scope.

Suggestions (Optional)

  1. Test for set containing map - Nice-to-have

    • Suggestion: Consider adding a test for #{:a {:b 1}} (set containing a map)
    • Benefit: Ensures complex nesting works in both directions
    • Complexity: Trivial (add one test case)
    • Recommendation: Could be added now or deferred to later phases
  2. Test for mixed types - Nice-to-have

    • Suggestion: The spec (Section 6.1) mentions #{:a "b" 3} as a test case, which was not included
    • Benefit: Verifies mixed-type sets parse correctly
    • Complexity: Trivial
    • Recommendation: Could be deferred since #{:a :b} (keywords) and #{1 2 3} (integers) already cover primitive parsing

Security

No concerns - parser changes only, no external input handling changes.

Documentation

No updates needed for Phase 1. The spec document (docs/ptc-lisp-set-literal-plan.md) correctly notes that documentation updates are planned for Phase 8.

Verdict

Approve - The implementation is correct, complete for its stated scope (Phase 1: Parser), follows the specification, and all 979 tests pass. The PR is well-scoped as the first phase of a multi-phase feature.

@github-actions github-actions bot added the auto-triage-pending Auto-triage in progress label Dec 9, 2025
@andreasronge
Copy link
Copy Markdown
Owner Author

@claude please fix these issues from PR review:

Issue 1: Add test for set containing map

Location: test/ptc_runner/lisp/parser_test.exs:133 (after line 132)
Problem: Missing test coverage for sets containing maps (only have vector→set, not map→set nesting)
Fix: Add test case after the "set containing vector" test:

test "set containing map" do
  set_map = "#" <> "{:a {:b 1}}"
  assert {:ok, {:set, [{:keyword, :a}, {:map, [{{:keyword, :b}, 1}]}]}} = Parser.parse(set_map)
end

Issue 2: Add test for mixed types from spec

Location: test/ptc_runner/lisp/parser_test.exs:133 (after Issue 1's test)
Problem: The spec (docs/ptc-lisp-set-literal-plan.md line 582-583, Section 6.1) explicitly lists #{:a "b" 3} as a test case, but it was not included
Fix: Add test case:

test "set with mixed types" do
  set_mixed = "#" <> "{:a \"b\" 3}"
  assert {:ok, {:set, [{:keyword, :a}, {:string, "b"}, 3]}} = Parser.parse(set_mixed)
end

Please fix ALL issues above in a SINGLE commit. Make minimal changes to resolve each issue.

@andreasronge
Copy link
Copy Markdown
Owner Author

Auto-Triage Summary

Decisions Made

# Issue Decision Action
1 Add test for set containing map (#{:a {:b 1}}) FIX_NOW Included in fix request above
2 Add test for mixed types from spec (#{:a \"b\" 3}) FIX_NOW Included in fix request above

Rationale

Both suggestions are FIX_NOW because:

  1. Trivial complexity - Each adds a single test case following existing patterns
  2. In-scope - The PR implements parser support per the spec; these tests complete the coverage:
    • Issue 1 mirrors the existing "set containing vector" test pattern
    • Issue 2 is explicitly listed in the spec document (Section 6.1, line 582-583)
  3. Mechanical - No design decisions needed, just apply the existing test pattern

Status

  • FIX_NOW items: 2 (batched in single fix comment above)
  • Issues created: 0
  • Items ignored: 0

The review verdict was Approve, and these are low-risk additions that complete the parser test coverage as specified in the implementation plan.

@github-actions github-actions bot added auto-triage-cycle-1 Auto-triage cycle 1 auto-triage-complete Auto-triage completed and removed auto-triage-pending Auto-triage in progress labels Dec 9, 2025
- Add test for set containing map (#{:a {:b 1}})
- Add test for set with mixed types (#{:a "b" 3}) from spec

Addresses PR review suggestions to complete test coverage for parser Phase 1.

🤖 Generated with Claude Code

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@andreasronge
Copy link
Copy Markdown
Owner Author

Fixed Issues

All issues from the PR review have been resolved:

Issue 1: Set containing map ✅

  • Added test for to ensure sets can contain maps
  • Placed after the "set containing vector" test to maintain test organization

Issue 2: Set with mixed types ✅

  • Added test for to verify mixed-type sets parse correctly
  • Covers the test case explicitly listed in spec (Section 6.1)

Verification

  • All 981 tests pass (5 doctests, 39 properties, 981 tests)
  • Precommit checks passed: formatting, compilation, credo, tests
  • Single minimal commit with only the required test additions

Commit: b60ed36

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Dec 9, 2025

PR Review: feat(parser): Add #{...} set literal syntax support (Phase 1 of #164)

Summary

This PR implements Phase 1 (Parser) of the Set Literal epic (#164), adding support for Clojure-style #{...} set literal syntax to PTC-Lisp. The implementation is clean, complete, and matches the specification in docs/ptc-lisp-set-literal-plan.md.

What's Good

  1. Follows existing patterns exactly - The :set combinator structure (lines 133-141) mirrors :vector and :map_literal, and build_set/1 in parser_helpers.ex mirrors build_vector/1

  2. Critical combinator ordering is correct - parsec(:set) appears at line 169, BEFORE parsec(:map_literal) at line 170, ensuring #{ is matched before { attempts to match

  3. Clever string escaping - Using string("#" <> "{") instead of string("#{") avoids Elixir string interpolation issues during compilation

  4. Comprehensive test coverage - 10 test cases covering:

    • Empty set, sets with elements, keywords
    • Nested sets, sets containing vectors and maps
    • Whitespace and comma handling
    • Mixed types (:a "b" 3)
    • Error cases: unclosed set, space between # and {
  5. Implementation matches spec - The parser changes exactly match the specification in docs/ptc-lisp-set-literal-plan.md Section 5.1:

    • Combinator definition matches lines 260-268 of spec
    • build_set/1 matches lines 298-300 of spec
    • Combinator ordering matches spec requirement (line 271)
  6. Previous review issues addressed - The follow-up comments added tests for "set containing map" and "set with mixed types" as requested

Issues (Must Fix)

None - the implementation is complete and correct for Phase 1 scope.

Suggestions (Optional)

None - the implementation covers all test cases from the spec (Section 6.1) and follows the existing codebase patterns precisely.

Security

No concerns - parser changes only, no external input handling changes or new attack vectors.

Documentation

No updates needed for Phase 1. The spec document (docs/ptc-lisp-set-literal-plan.md) correctly notes that documentation updates are planned for Phase 8.

Verification

  • Implementation matches specification (Section 5.1)
  • Combinator ordering is correct (set before map_literal)
  • All test cases from spec Section 6.1 are covered
  • Previous review issues have been fixed
  • No code duplication issues

Verdict

Approve - The implementation is correct, complete for its stated scope (Phase 1: Parser), and matches the specification exactly. All 981 tests pass. The PR is well-scoped as the first phase of a multi-phase feature and establishes clean patterns for subsequent phases (analyzer, evaluator, runtime functions, formatter, env bindings, documentation).

@github-actions github-actions bot added the auto-triage-pending Auto-triage in progress label Dec 9, 2025
@andreasronge andreasronge added the ready-to-merge PR is ready to be merged label Dec 9, 2025
@andreasronge
Copy link
Copy Markdown
Owner Author

Auto-Triage Summary (Cycle 1 of 3)

Review Status

The PR has already completed a full review and fix cycle:

  • Initial review: 2 optional suggestions identified
  • Fix cycle: Both suggestions were addressed in commit b60ed36
  • Second review: Approve verdict with no remaining issues

Decisions Made

No new issues to triage. The latest review (comment #5) shows:

  • ✅ Implementation matches specification
  • ✅ All test cases from spec covered
  • ✅ Previous review issues fixed
  • ✅ All 981 tests passing

Action Taken

Added ready-to-merge label to signal that the PR is ready for auto-merge once all checks pass.

Status

  • FIX_NOW items: 0
  • Issues created: 0
  • Items ignored: 0

The PR is complete and ready to merge.

@github-actions github-actions bot added auto-triage-cycle-2 Auto-triage cycle 2 and removed auto-triage-cycle-1 Auto-triage cycle 1 auto-triage-pending Auto-triage in progress labels Dec 9, 2025
@andreasronge andreasronge enabled auto-merge (squash) December 9, 2025 21:39
@andreasronge andreasronge merged commit db9dbb1 into main Dec 9, 2025
4 checks passed
@andreasronge andreasronge deleted the claude/issue-165-20251209-212843 branch December 9, 2025 21:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-triage-complete Auto-triage completed auto-triage-cycle-2 Auto-triage cycle 2 ready-to-merge PR is ready to be merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add \#{...} set literal parsing to PTC-Lisp parser

1 participant