// not including <> as they are ambiguous (< is also a comparison operator) static S testBracketHygiene_op = "([{"; static S testBracketHygiene_close = ")]}"; static bool testBracketHygiene(S s) { ret testBracketHygiene(s, testBracketHygiene_op, testBracketHygiene_close, null); } static bool testBracketHygiene(S s, Var msg) { ret testBracketHygiene(s, testBracketHygiene_op, testBracketHygiene_close, msg); } static bool testBracketHygiene(S s, S op, S close, Var msg) { S t = getUnclosedStringLiteral(s); if (t != null) { if (msg != null) msg.set("Unclosed string literal: " + quote(t)); false; } L tok = javaTok(s); new Map map; L stack = getBracketMap2(tok, map, op, close); if (nempty(stack)) { if (msg != null) msg.set("Bad hygiene - " + n(l(stack), "bracket") + " not closed"); false; } if (map.containsKey(0)) { if (msg != null) msg.set("Bad hygiene - bracket not opened (" + quote(tok.get(map.get(0))) + ")"); false; } for (int i : keys(map)) { int j = map.get(i); S a = tok.get(i), b = tok.get(j); int ai = op.indexOf(a), bi = close.indexOf(b); if (ai != bi) { if (msg != null) msg.set("Bad hygiene - brackets don't match (" + quote(a) + " vs " + quote(b) + ")"); false; } } if (msg != null) msg.set("Hygiene OK!"); true; }