From 40a648cd194b6e26f4860f14d2d0b7d3658f2173 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Wed, 29 Oct 2025 10:38:57 -0700 Subject: [PATCH] allow ? in identifier name --- src/parser/tests/basics.test.ts | 13 +++++++++++++ src/parser/tokenizer.ts | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/parser/tests/basics.test.ts b/src/parser/tests/basics.test.ts index f92e034..0d870a8 100644 --- a/src/parser/tests/basics.test.ts +++ b/src/parser/tests/basics.test.ts @@ -36,6 +36,19 @@ describe('Identifier', () => { FunctionCallOrIdentifier Identifier 𝜋`) }) + + test('parses identifiers with queries', () => { + expect('even? 20').toMatchTree(` + FunctionCall + Identifier even? + PositionalArg + Number 20`) + + expect('even?').toMatchTree(` + FunctionCallOrIdentifier + Identifier even?`) + }) + }) describe('Unicode Symbol Support', () => { diff --git a/src/parser/tokenizer.ts b/src/parser/tokenizer.ts index 6b2e67a..e4fc895 100644 --- a/src/parser/tokenizer.ts +++ b/src/parser/tokenizer.ts @@ -119,7 +119,7 @@ const consumeWordToken = ( } // Track identifier validity: must be lowercase, digit, dash, or emoji/unicode - if (!isLowercaseLetter(ch) && !isDigit(ch) && ch !== 45 /* - */ && !isEmojiOrUnicode(ch)) { + if (!isLowercaseLetter(ch) && !isDigit(ch) && ch !== 45 /* - */ && ch !== 63 /* ? */ && !isEmojiOrUnicode(ch)) { if (!canBeWord) break isValidIdentifier = false }