Module
СсылкаCode predicates classify an integer. Indexed predicates classify one Unicode scalar in a string. Span scans return the first position after consecutive matches. Every position uses the same scalar unit as string indexing.
Why
СсылкаExplicit ASCII classes give parsers stable boundaries without locale rules. Scalar positions compose with existing string indexing and slicing.
Availability
СсылкаImport std.parser in language mode 5.21. The current compiler selects std/parser.tpz for this language mode. Availability in other released editions and inclusion in each installed distribution are Pending.
Public API
Ссылкаstd.parser.isAsciiWhitespaceCode →
std.parser.isAsciiWhitespace →
std.parser.takeWhileAsciiDigit →
std.parser.takeWhileAsciiAlpha →
Pending contracts
СсылкаClassify integer ASCII codes
СсылкаClassify integer ASCII codes
is returns true for integers from 48 through 57, inclusive. These are the ASCII digits from 0 through 9.
is returns true for integers from 65 through 90 or from 97 through 122, inclusive. These are ASCII uppercase and lowercase letters.
is returns true when the digit predicate or the letter predicate returns true.
is returns true for 9, 10, 11, 12, 13, and 32. These represent tab, line feed, vertical tab, form feed, carriage return, and space.
Every other int returns false. Negative values, surrogate code values, non ASCII characters, and integers above the Unicode range do not cause a diagnostic.
Each call evaluates its input once. Classification has no side effects and does not consult a locale, normalize text, or fold case.
Причина
Exact integer sets make ASCII parsing independent of host text rules. A false result handles a value outside the class without introducing an error channel.
Include each ASCII endpoint and exclude its neighbors
Ссылкаimport std.parserimport std.iofor cp in ([47, 48, 57, 58, 64, 65, 90, 91, 96, 97, 122, 123, 8, 9, 10, 11, 12, 13, 14, 31, 32, 33]) {let digit = parser.isAsciiDigitCode(cp)let alpha = parser.isAsciiAlphaCode(cp)let alnum = parser.isAsciiAlnumCode(cp)let space = parser.isAsciiWhitespaceCode(cp)io.writeLine("{digit}/{alpha}/{alnum}/{space}")}
false/false/false/false
true/false/true/false
true/false/true/false
false/false/false/false
false/false/false/false
false/true/true/false
false/true/true/false
false/false/false/false
false/false/false/false
false/true/true/false
false/true/true/false
false/false/false/false
false/false/false/false
false/false/false/true
false/false/false/true
false/false/false/true
false/false/false/true
false/false/false/true
false/false/false/false
false/false/false/false
false/false/false/true
false/false/false/false
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
false/false/false/falsetrue/false/true/falsetrue/false/true/falsefalse/false/false/falsefalse/false/false/falsefalse/true/true/falsefalse/true/true/falsefalse/false/false/falsefalse/false/false/falsefalse/true/true/falsefalse/true/true/falsefalse/false/false/falsefalse/false/false/falsefalse/false/false/truefalse/false/false/truefalse/false/false/truefalse/false/false/truefalse/false/false/truefalse/false/false/falsefalse/false/false/falsefalse/false/false/truefalse/false/false/false
Return false for invalid code points and non ASCII values
Ссылкаimport std.parserimport std.iofor cp in ([-1, 128, 233, 55296, 1114112, 9223372036854775807]) {let digit = parser.isAsciiDigitCode(cp)let alpha = parser.isAsciiAlphaCode(cp)let alnum = parser.isAsciiAlnumCode(cp)let space = parser.isAsciiWhitespaceCode(cp)io.writeLine("{digit}/{alpha}/{alnum}/{space}")}
false/false/false/false
false/false/false/false
false/false/false/false
false/false/false/false
false/false/false/false
false/false/false/false
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
false/false/false/falsefalse/false/false/falsefalse/false/false/falsefalse/false/false/falsefalse/false/false/falsefalse/false/false/false
Classify a scalar position
СсылкаClassify a scalar position
The index counts Unicode scalars from zero. A multibyte scalar occupies one position. A combining scalar occupies its own position.
A present scalar is classified by the corresponding code predicate. Non ASCII scalars return false, including a nonbreaking space and letters outside the ASCII ranges.
A negative index or an index at or beyond the scalar length returns false. Index zero in an empty string also returns false. These cases do not produce a diagnostic.
The result agrees with applying the corresponding code predicate to text. when it returns Some(code). A None() result means false.
The text expression is evaluated before the index expression, once each. Classification leaves the string unchanged and performs no I/O.
Причина
A shared scalar coordinate system lets parser positions pass directly to string operations. An absent position is a failed predicate, so end of input needs no exceptional control flow.
Keep scalar positions through multibyte and combining text
Ссылкаimport std.parserimport std.iolet text = "é5éZ "for index in ([0, 1, 2, 3, 4, 5, 6]) {let digit = parser.isAsciiDigit(text, index)let alpha = parser.isAsciiAlpha(text, index)let alnum = parser.isAsciiAlnum(text, index)let space = parser.isAsciiWhitespace(text, index)io.writeLine("{digit}/{alpha}/{alnum}/{space}")}
false/false/false/false
true/false/true/false
false/true/true/false
false/false/false/false
false/true/true/false
false/false/false/false
false/false/false/true
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
false/false/false/falsetrue/false/true/falsefalse/true/true/falsefalse/false/false/falsefalse/true/true/falsefalse/false/false/falsefalse/false/false/true
Treat negative positions and end of input as false
Ссылкаimport std.parserimport std.iolet text = "7"for index in ([-1, 1, 2, 9223372036854775807]) {let digit = parser.isAsciiDigit(text, index)let alpha = parser.isAsciiAlpha(text, index)let alnum = parser.isAsciiAlnum(text, index)let space = parser.isAsciiWhitespace(text, index)io.writeLine("{digit}/{alpha}/{alnum}/{space}")}let empty = ""let digit = parser.isAsciiDigit(empty, 0)let alpha = parser.isAsciiAlpha(empty, 0)let alnum = parser.isAsciiAlnum(empty, 0)let space = parser.isAsciiWhitespace(empty, 0)io.writeLine("{digit}/{alpha}/{alnum}/{space}")
false/false/false/false
false/false/false/false
false/false/false/false
false/false/false/false
false/false/false/false
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
false/false/false/falsefalse/false/false/falsefalse/false/false/falsefalse/false/false/falsefalse/false/false/false
Scan a maximal ASCII span
СсылкаScan a maximal ASCII span
Each scan uses the class named by its corresponding ASCII predicate. The starting position and result follow the zero based scalar positions.
Clamp a negative start to zero. Clamp a start greater than the scalar length to that length. The first position examined is the clamped start.
Inspect consecutive positions from left to right. Stop at the first nonmatching scalar or at the scalar length. Return that exclusive end position.
If the first scalar does not match, return the clamped start. Starting at end of input returns that end. Every scan of an empty string returns zero.
A non ASCII scalar ends the span. Scanning does not skip it, normalize it, or advance across it to find a later match.
The text expression is evaluated before the start expression, once each. Scans do not modify the text or perform I/O. An out of range start produces a bounded result without a diagnostic.
For a clamped start begin and returned end, text. is the matched text. The scan reports a position rather than a character count.
Причина
Maximal spans let callers resume at the first unconsumed scalar. Clamping uses the same bounds as string slicing and gives empty input a useful result.
Find the exclusive end for every ASCII class
Ссылкаimport std.parserimport std.iolet digit = parser.takeWhileAsciiDigit("123x", 0)let alpha = parser.takeWhileAsciiAlpha("abZ9", 0)let alnum = parser.takeWhileAsciiAlnum("a9Z_", 0)let space = parser.takeWhileAsciiWhitespace("\t\n\r x", 0)io.writeLine("{digit}/{alpha}/{alnum}/{space}")
3/3/3/4
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
3/3/3/4
Stop at non ASCII scalars without changing position units
Ссылкаimport std.parserimport std.iolet digit = parser.takeWhileAsciiDigit("é12x", 1)let combining = parser.takeWhileAsciiAlpha("éA", 0)let suffix = parser.takeWhileAsciiAlpha("éA", 2)let nonbreaking = parser.takeWhileAsciiWhitespace(" ", 0)let alnum = parser.takeWhileAsciiAlnum("Aé", 0)io.writeLine("{digit}/{combining}/{suffix}/{nonbreaking}/{alnum}")
3/1/3/0/1
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
3/1/3/0/1
Clamp starts and keep the first failing position
Ссылкаimport std.parserimport std.iolet text = "12"for start in ([-3, 0, 1, 2, 99]) {let digit = parser.takeWhileAsciiDigit(text, start)let alpha = parser.takeWhileAsciiAlpha(text, start)let alnum = parser.takeWhileAsciiAlnum(text, start)let space = parser.takeWhileAsciiWhitespace(text, start)io.writeLine("{digit}/{alpha}/{alnum}/{space}")}let empty = ""let digit = parser.takeWhileAsciiDigit(empty, 99)let alpha = parser.takeWhileAsciiAlpha(empty, -1)let alnum = parser.takeWhileAsciiAlnum(empty, 0)let space = parser.takeWhileAsciiWhitespace(empty, 1)io.writeLine("{digit}/{alpha}/{alnum}/{space}")
2/0/2/0
2/0/2/0
2/1/2/1
2/2/2/2
2/2/2/2
0/0/0/0
Ожидаемый результат
Ожидаемый результат
Выполнение завершается. Код завершения 0.
2/0/2/02/0/2/02/1/2/12/2/2/22/2/2/20/0/0/0