"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const CharacterStream_1 = require("./CharacterStream");
const utils_1 = require("../../utils");
class GenericTokenParser {
    constructor(open, close, skipStr) {
        this.open = open;
        this.close = close;
        this.skipStr = skipStr;
    }
    async parse(source, handler) {
        const stream = new CharacterStream_1.default(source);
        const builder = new utils_1.StringBuilder();
        while (stream.hasMore()) {
            builder.append(await this.parseStream(stream, null, handler));
        }
        return builder.toString().trim();
    }
    async parseStream(stream, expect, handler) {
        const builder = new utils_1.StringBuilder();
        while (stream.hasMore()) {
            if (expect != null && stream.match(expect, true)) {
                return builder.toString().trim();
            }
            if (stream.match(this.open, true)) {
                const value = await handler(await this.parseStream(stream, this.close, handler));
                if (value != null) {
                    builder.append(value);
                }
            }
            else {
                const ch = stream.consume();
                builder.append(ch);
                if (this.skipStr && ch == "'") {
                    builder.append(this.consumeUntil(stream, "'"));
                }
                else if (this.skipStr && ch == '"') {
                    builder.append(this.consumeUntil(stream, '"'));
                }
                else if (ch == '{') {
                    builder
                        .append(await this.parseStream(stream, '}', handler))
                        .append('}');
                }
            }
        }
        return builder.toString().trim();
    }
    consumeUntil(stream, str) {
        const start = stream.getPosition();
        while (stream.hasMore()) {
            if (stream.match('\\', true)) {
                stream.consume();
            }
            if (stream.match(str, true)) {
                break;
            }
            stream.consume();
        }
        return stream.substring(start, stream.getPosition());
    }
}
exports.default = GenericTokenParser;
