class AbbreviationLabel {

    static boolean parse(String label, List<String> tokens) {

        int i = 0;
        int len = label.length();

        while (i < len) {

            int st = i;
            int last;

            char c = label.charAt(i);

            // BRACKETS we treat as separate
            if (c == '(' || c == ')') {
                tokens.add(Character.toString(c));
                i++;

                // digits following closing brackets
                if (c == ')') {
                    st = i;
                    while (i < len && isDigit(c = label.charAt(i))) {
                        i++;
                    }
                    if (i > st)
                        tokens.add(label.substring(st, i));
                }

                continue;
            }

            // separators
            if (c == '/' || c == '·' || c == '.' || c == '•' || c == '=') {
                tokens.add(Character.toString(c));
                i++;

                int beg = i;
                while (i < label.length() && isDigit(label.charAt(i))) {
                    i++;
                }
                if (i > beg)
                    tokens.add(label.substring(beg, i));
                continue;
            }

            // SYMBOL Tokens
            // optional prefix o- m- p- etc.
            if ((last = findPrefix(PREFIX_TRIE, label, i, -1)) > 0) {
                i += (last - i);
            }
            final int symSt = i;

            // a valid symbol token
            if ((last = findPrefix(SYMBOL_TRIE, label, i, -1)) > 0) {
                i += (last - i);
                // an optional number suffix e.g. O2 F3 Ph3 etc.
                while (i < len && isDigit(label.charAt(i))) {
                    i++;
                }
            }
            // a charge token, only if it's after some other parts
            else if (i == st && st > 0) {
                c = norm(label.charAt(i));
                if (c == '-' || c == '+') {
                    i++;
                    while (i < len && isDigit(label.charAt(i))) {
                        i++;
                    }
                    // we expect charge at the end of the string.. if there is
                    // still more it's not good input
                    if (i < len) {
                        return failParse(label, tokens);
                    }
                }
            }

            if (i == st || i == symSt) {
                return failParse(label, tokens);
            }

            tokens.add(label.substring(st, i));
        }

        return true;
    }

}