Objective
Mimic Haskell's reads :: ReadS ().
Or in other words, parse nested parentheses. Since the target type is () (the type with one possible value), "parsing" means discarding a leading nested parentheses.
Valid Input
"Nested parentheses" means (), (()), ((())), and so on. That is, leading nonzero (s and trailing )s of the same number.
But there's a twist. The parser must munch also leading or intercalated whitespaces. So for example, the following strings are valid to be munched:
( )()( () )
Note that trailing whitespaces are not to be munched.
Whitespaces
The following ASCII characters are always considered a whitespace:
\tU+0009; Horizontal Tab\nU+000A; Line Feed\vU+000B; Vertical Tab\fU+000C; Form Feed\rU+000D; Carriage ReturnU+0020; Space
For each of the following Unicode characters, it is implementation-defined to consider it a whitespace:
- U+0085; Next Line
- U+00A0; No-Break Space
- U+1680; Ogham Space Mark
- U+2000; En Quad
- U+2001; Em Quad
- U+2002; En Space
- U+2003; Em Space
- U+2004; Three-Per-Em Space
- U+2005; Four-Per-Em Space
- U+2006; Six-Per-Em Space
- U+2007; Figure Space
- U+2008; Punctuation Space
- U+2009; Thin Space
- U+200A; Hair Space
- U+2028; Line Separator
- U+2029; Paragraph Separator
- U+202F; Narrow No-Break Space
- U+205F; Medium Mathematical Space
- U+3000; Ideographic Space
All other characters are never considered a whitespace.
Error
If the string doesn't start with a nested parentheses, the parser shall fall in an erroneous state. Ways that indicates an error include:
- Monadic failing
- Returning an erroneous value
- Raising/Throwing an error
Output
When the parser successfully munched a nested parentheses, the parser shall output the unmunched part of string.
Examples
Valid example
- When given
(), the output is an empty string. - When given
( ) Hello, the output isHello. Note the leading whitespace of the output. - when given
((())))), the output is)).
Erroneous example
- Empty string
((()(()())(H)Hello, world!
Ungolfed solution
C
Returns a null pointer for an error.
#include <stdbool.h>
#include <stdlib.h>
char *readMaybeUnit(char *str) {
bool p = false;
unsigned c = 0;
while (*str != '\0') {
switch (*str) {
case '(':
p = true;
++c;
// FALLTHRU
case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
break;
default:
goto parseRightParentheses;
}
++str;
}
parseRightParentheses: while (*str != '\0') {
switch (*str) {
case ')':
if (1 >= c) {
if (1 == c)
++str;
c = 0;
goto returnReadMaybeUnit;
}
--c;
// FALLTHRU
case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
break;
default:
goto returnReadMaybeUnit;
}
++str;
}
returnReadMaybeUnit: return p && 0 == c ? str : NULL;
}
Hello, world!doesn't just give itself (do we need nonzero parens?) or what's going on with(()()). \$\endgroup\$