class CxSmilesParser {

    static int processCx(final String str, final CxSmilesState state) {

        final CharIter iter = new CharIter(str);

        if (!iter.nextIf('|'))
            return -1;

        while (iter.hasNext()) {
            switch (iter.next()) {
                case '$': // atom labels and values
                    // dest is atom labels by default
                    Map<Integer, String> dest;

                    // check for atom values
                    if (iter.nextIf("_AV:"))
                        dest = state.atomValues = new TreeMap<>();
                    else
                        dest = state.atomLabels = new TreeMap<>();

                    if (!processAtomLabels(iter, dest))
                        return -1;
                    break;
                case '(': // coordinates
                    if (!processCoords(iter, state))
                        return -1;
                    break;
                case 'c': // cis/trans/unspec ignored
                case 't':
                    // c/t:
                    if (iter.nextIf(':')) {
                        if (!skipIntList(iter, COMMA_SEPARATOR))
                            return -1;
                    }
                    // ctu:
                    else if (iter.nextIf("tu:")) {
                        if (!skipIntList(iter, COMMA_SEPARATOR))
                            return -1;
                    }
                    break;
                case 'r': // relative stereochemistry ignored
                    if (iter.nextIf(':')) {
                        if (!skipIntList(iter, COMMA_SEPARATOR))
                            return -1;
                    } else {
                        if (!iter.nextIf(',') && iter.curr() != '|')
                            return -1;
                    }
                    break;
                case 'l': // lone pairs ignored
                    if (!iter.nextIf("p:"))
                        return -1;
                    if (!skipIntMap(iter))
                        return -1;
                    break;
                case 'f': // fragment grouping
                    if (!iter.nextIf(':'))
                        return -1;
                    if (!processFragmentGrouping(iter, state))
                        return -1;
                    break;
                case 'S': // Sgroup polymers
                    if (iter.nextIf("g:")) {
                        if (!processPolymerSgroups(iter, state))
                            return -1;
                    }
                    else if (iter.nextIf("gD:")) {
                        if (!processDataSgroups(iter, state))
                            return -1;
                        if (iter.nextIf(','))
                            break;
                    }
                    else if (iter.nextIf("gH:")) {
                        if (!processSgroupsHierarchy(iter, state))
                            return -1;
                    }
                    else {
                        return -1;
                    }
                    break;
                case 'm': // positional variation
                    if (!iter.nextIf(':'))
                        return -1;
                    if (!processPositionalVariation(iter, state))
                        return -1;
                    break;
                case '^': // Radicals
                    if (!processRadicals(iter, state))
                        return -1;
                    break;
                case 'C':
                case 'H': // coordination and hydrogen bonding ignored
                    if (!iter.nextIf(':'))
                        return -1;
                    while (iter.hasNext() && isDigit(iter.curr())) {
                        if (!skipIntList(iter, DOT_SEPARATOR))
                            return -1;
                        iter.nextIf(',');
                    }
                    break;
                case '|': // end of CX
                    // consume optional separators
                    if (!iter.nextIf(' ')) iter.nextIf('\t');
                    return iter.pos;
                case 'L':
                    // LO, Ligand Ordering
                    if (iter.nextIf('O')) {
                        if (!iter.nextIf(':'))
                            return -1;
                        if (!processLigandOrdering(iter, state))
                            return -1;
                    }
                    else {
                        // LP, bond connected lone pair?
                        return -1;
                    }
                    break;
                default:
                    return -1;
            }
        }

        return -1;
    }

    private  CxSmilesParser();

}