让我们正式地处理这个问题,以增加我们在没有大量调试的情况下提出可行的解决方案的可能性。
什么是平衡弦?这是一个简单的语法:
BalancedString: Sequence end-of-string;
Sequence:
Fragment Sequence |
(* empty *);
Fragment:
'(' Sequence ')' |
'[' Sequence ']' |
'{' Sequence '}' |
any-character-not-in-'()[]{}';
请注意,此语法生成的字符串(hello)[[good]{bye}]
具有多个“顶级”组。
现在让我们把它变成一个递归下降解析器。每个非终结符(BalancedString
、Sequence
和Fragment
)都成为一个函数。我们将从解析“BalancedString”非终端的函数开始:
private static bool parseBalancedString(String input, int offset) {
offset = parseSequence(input, offset);
return offset == input.length();
}
请注意,此函数期望parseSequence
返回它停止解析的偏移量。接下来写吧parseSequence
。我们将使用循环而不是直接递归。
private static int parseSequence(String input, int offset) {
bool parseSucceeded = true;
while (parseSucceeded) {
int newOffset = parseFragment(input, offset);
parseSucceeded = newOffset > offset;
newOffset = offset;
}
return offset;
}
请注意,parseSequence
期望parseFragment
返回它停止解析的偏移量,如果失败,它应该返回它传递的偏移量。现在我们将编写parseFragment
. 我们将从三个相似的产生式中提取公共代码到一个辅助函数中。
private static int parseFragment(String input, int offset) {
if (offset >= input.length()) {
return offset;
}
switch (input.charAt(offset)) {
case '(': return helpParseFragment(input, offset, ')');
case '[': return helpParseFragment(input, offset, ']');
case '{': return helpParseFragment(input, offset, '}');
default: return offset + 1;
}
}
辅助函数期望接收开启者的偏移量,以便在失败时返回该偏移量。如果成功,它将返回刚刚过去的偏移量。
private static int helpParseFragment(String input, int offset, char closer) {
int newOffset = parseSequence(input, offset + 1);
if (newOffset > offset && newOffset < input.length() && input.charAt(newOffset) == closer) {
return newOffset + 1;
} else {
return offset;
}
}