parseString static method

Danger<List<String>, ChainException> parseString(
  1. String source
)

基本的に space で区切る.
aaa bbb ccc -> 'aaa', 'bbb', 'ccc'

space を要素の中に含めたい場合 variety or double quotation でその要素を囲む.
aaa 'b b' "c c" -> 'aaa', 'b b', 'c c'

variety or double quotation を要素の中に含めたい場合 \ で escape できる.
aaa 'b\'b' "c\"c" -> 'aaa', 'b'b', 'c"c'

要素の中に含まれる quotation の種類が異なる場合 escape する必要が無い.
aaa 'b"b' "c'c" -> 'aaa', 'b"b', 'c'c'

Implementation

static Danger<List<String>, ChainException> parseString(String source) {

    final log = Log(classLocation: Chain, functionLocation: 'parseString');

    const varietyQuotation = "'";
    const doubleQuotation = '"';
    const space = ' ';
    const escapeSequence = '\\';

    final _source = source.trim().split('');

    final scanner = StringScanner<String>(_source);

    String string = '';

    while (true) {

        final lookResult = scanner.look();
        log.add(lookResult);
        if (lookResult is! Success<String, ScannerExceptionA>) {
            if (string.isNotEmpty) scanner.scan(string);
            break;
        }
        final look = lookResult.wrapped;

        switch (look) {
        case varietyQuotation:
        case doubleQuotation:

            // abc'xyz' のような space を挟まずに variety quotation が来た時は abc を1つの塊と見なす.
            if (string.isNotEmpty) {
                final result = scanner.scan(string);
                log.add(result);
                string = ''; // string をリセット.
            }

            // variety quotation で挟まれた文字列を 1つの塊として見なす.
            final lookWhileResult = scanner.lookWhileUntils([look], escapeSequence);
            log.add(lookWhileResult);
            if (lookWhileResult is! Survive<List<String>, StringScannerExceptionA, StringScannerErrorA>) {
                switch (look) {
                case varietyQuotation: return Failure(ChainExceptionB(), log);
                case doubleQuotation: return Failure(ChainExceptionC(), log);
                case _: Result.panic(ChainErrorB(), log.monitor({
                    'look': look,
                }));
                }
            }

            final result = scanner.scan(lookWhileResult.wrapped.join());
            log.add(result);

        case space:

            // space は区切りの開始となる.
            final lookWhileResult = scanner.lookWhileCharacters([' ']);
            log.add(lookWhileResult);

            if (string.isNotEmpty) {
                final result = scanner.scan(string);
                log.add(result);
                string = ''; // string をリセット.
            }

        case _:

            string = string + look;

        }

    }

    return Success(scanner.outcome, log);

}