@@ -127,8 +127,6 @@ private def test (input : String) (expected : Ast) : Bool :=
127127#guard parseAst "\\ x" = .error .unexpectedEof
128128#guard parseAst "\\ u" = .error .unexpectedEof
129129#guard parseAst "\\ u12" = .error .unexpectedEof
130- #guard parseAst "\\ u{}" = .error (.unexpectedChar '{' )
131- #guard parseAst "\\ u{xyz}" = .error (.unexpectedChar '{' )
132130#guard parseAst "[]" = .error (.unexpectedChar ']' )
133131#guard parseAst "[^]" = .error (.unexpectedChar ']' )
134132#guard parseAst "a{1" = .error .unexpectedEof
@@ -140,7 +138,61 @@ private def test (input : String) (expected : Ast) : Bool :=
140138#guard parseAst "(?:a" = .error .unexpectedEof
141139#guard parseAst "(?:" = .error .unexpectedEof
142140
143- -- We do not support \u{...} yet.
144- #guard parseAst "\\ u{1234}" = .error (.unexpectedChar '{' )
141+ -- Minimum
142+ #guard parseAst "\\ u{0}" = .ok (.char '\x00 ' )
143+
144+ -- ASCII range
145+ #guard parseAst "\\ u{7F}" = .ok (.char '\x7F ' )
146+ #guard parseAst "\\ u{41}" = .ok (.char 'A' )
147+
148+ -- Latin-1 Supplement
149+ #guard parseAst "\\ u{80}" = .ok (.char (Char.ofNat 0x80 ))
150+ #guard parseAst "\\ u{FF}" = .ok (.char 'ÿ' )
151+
152+ -- BMP (Basic Multilingual Plane)
153+ #guard parseAst "\\ u{1234}" = .ok (.char (Char.ofNat 0x1234 ))
154+ #guard parseAst "\\ u{FFFF}" = .ok (.char (Char.ofNat 0xFFFF ))
155+
156+ -- Supplementary planes (emoji and beyond)
157+ #guard parseAst "\\ u{10000}" = .ok (.char (Char.ofNat 0x10000 ))
158+ #guard parseAst "\\ u{1F600}" = .ok (.char '😀' ) -- GRINNING FACE
159+ #guard parseAst "\\ u{1F4A9}" = .ok (.char '💩' ) -- PILE OF POO
160+ #guard parseAst "\\ u{1F47D}" = .ok (.char '👽' ) -- EXTRATERRESTRIAL ALIEN
161+
162+ -- Maximum valid code point
163+ #guard parseAst "\\ u{10FFFF}" = .ok (.char (Char.ofNat 0x10FFFF ))
164+
165+ -- Lowercase hex digits
166+ #guard parseAst "\\ u{1f600}" = .ok (.char '😀' )
167+ #guard parseAst "\\ u{abcd}" = .ok (.char (Char.ofNat 0xABCD ))
168+
169+ -- Variable length (1-6 digits)
170+ #guard parseAst "\\ u{a}" = .ok (.char (Char.ofNat 0xA ))
171+ #guard parseAst "\\ u{AB}" = .ok (.char (Char.ofNat 0xAB ))
172+ #guard parseAst "\\ u{ABC}" = .ok (.char (Char.ofNat 0xABC ))
173+ #guard parseAst "\\ u{ABCD}" = .ok (.char (Char.ofNat 0xABCD ))
174+ #guard parseAst "\\ u{ABCDE}" = .ok (.char (Char.ofNat 0xABCDE ))
175+
176+ -- Empty braces
177+ #guard parseAst "\\ u{}" = .error (.unexpectedChar '}' )
178+
179+ -- Too large (beyond Unicode)
180+ #guard parseAst "\\ u{110000}" = .error (.invalidCodePoint 0x110000 )
181+ #guard parseAst "\\ u{FFFFFF}" = .error (.invalidCodePoint 0xFFFFFF )
182+
183+ -- Too many digits (>6)
184+ #guard parseAst "\\ u{1234567}" = .error (.tooManyHexDigits 7 )
185+
186+ -- Invalid hex characters
187+ #guard parseAst "\\ u{GHIJ}" = .error (.unexpectedChar 'G' )
188+ #guard parseAst "\\ u{12.34}" = .error (.unexpectedChar '.' )
189+
190+ -- Missing closing brace
191+ #guard parseAst "\\ u{1234" = .error (.unexpectedEof)
192+
193+ -- Surrogate range (optional, depending on Lean's Char behavior)
194+ -- If Lean's Char.ofNat rejects surrogates, these should error:
195+ #guard parseAst "\\ u{D800}" = .error (.invalidCodePoint 0xD800 )
196+ #guard parseAst "\\ u{DFFF}" = .error (.invalidCodePoint 0xDFFF )
145197
146198end Regex.Syntax.Parser.Test
0 commit comments