Restricted S-expression parsing
ParenWick supports project conversations about small, deliberately restricted parsers on Windows. Ask a compatible model to inspect list nesting and atom rules, then review the proposed S-expression code without confusing parsing with execution.
import re
def read_sexpression(text):
if type(text) is not str or len(text) > 4096:
raise ValueError("sexpr.input")
stack, result, count = [], None, 0
for match in re.finditer(r"\(|\)|[^\s()]+", text):
token = match[0]
if token == "(":
if len(stack) == 16 or (not stack and result is not None):
raise ValueError("sexpr.depth")
item = []
if stack:
stack[-1].append(item)
stack.append(item)
count += 1
elif token == ")":
if not stack:
raise ValueError("sexpr.close")
item = stack.pop()
if not stack:
result = item
else:
if not stack or re.fullmatch(r"[A-Za-z_][A-Za-z0-9_-]*|[+-]?[0-9]+", token) is None:
raise ValueError("sexpr.atom")
stack[-1].append(token)
count += 1
if count > 1024:
raise ValueError("sexpr.nodes")
if stack or result is None:
raise ValueError("sexpr.unclosed")
return result
Connection
Base URL, credentials and a reachable server.
Project
Test empty lists, depth 16 and 1024 nodes, rejecting extra forms, unclosed lists and unsupported quote syntax without evaluating anything.
Review before applying
Compare actual behavior with the expected result. If a check fails, investigate it before applying more changes.
import re
def read_sexpression(text):
if type(text) is not str or len(text) > 4096:
raise ValueError("sexpr.input")
stack, result, count = [], None, 0
for match in re.finditer(r"\(|\)|[^\s()]+", text):
token = match[0]
if token == "(":
if len(stack) == 16 or (not stack and result is not None):
raise ValueError("sexpr.depth")
item = []
if stack:
stack[-1].append(item)
stack.append(item)
count += 1
elif token == ")":
if not stack:
raise ValueError("sexpr.close")
item = stack.pop()
if not stack:
result = item
else:
if not stack or re.fullmatch(r"[A-Za-z_][A-Za-z0-9_-]*|[+-]?[0-9]+", token) is None:
raise ValueError("sexpr.atom")
stack[-1].append(token)
count += 1
if count > 1024:
raise ValueError("sexpr.nodes")
if stack or result is None:
raise ValueError("sexpr.unclosed")
return result
Keep a small language small as its parser changes
ParenWick is a Windows AI coding workspace for developing parsers whose accepted input is deliberately constrained. Open the project and describe the language the application should recognize, including where it must stop. Ask the connected assistant to inspect the current parser and its consumer before suggesting a patch, so an implementation convenience does not quietly expand the language.
A bounded S-expression reader offers a concrete example. Discuss a single parenthesized form, the permitted atom syntax and how nested lists are represented. Include the depth and node limits in the request, along with what happens when extra forms follow the first. The parser returns a representation of input; interpreting that representation would be a separate part of your application.
Review the proposal using accepted and rejected fixtures together, then run the project's checks at the exact limits and beyond them. Inspect error handling as carefully as successful output so callers can distinguish malformed input from a valid empty list. ParenWick accepts supported OpenAI-compatible or Anthropic connections, with credentials when required. Choose an unrestricted model where offered, and check the server's context and tool support. The resulting patch should be explainable against your grammar, rather than merely plausible on one sample expression.
Parser changes and their boundaries
What should I give the assistant besides valid examples?
Provide rejected examples, the allowed atom syntax and explicit size, depth and node limits. State how errors reach the caller. This makes it possible to review whether the proposed patch preserves the intended language boundary.
Does reading an expression execute its contents?
The illustrated task parses input into lists and atom strings. It does not evaluate that representation. Keep execution or interpretation as a separately specified behavior, and inspect downstream code before connecting parsed input to any action.
How should a second top-level form behave?
The existing contract accepts one parenthesized form and rejects extras. Include a fixture with two forms and check the full input is considered, so a parser change does not silently accept a valid prefix while ignoring trailing material.
Why test exactly at the nesting limit?
It distinguishes the largest accepted structure from the first rejected one and can expose off-by-one changes. Do the same for node and input-length limits, then verify that rejection produces the response expected by the calling application.
ParenWick · Updated 2026-10-25