kakasoo

2. slove, and, or, join 본문

프로그래밍/regexp-manager

2. slove, and, or, join

카카수(kakasoo) 2023. 1. 17. 21:45
반응형

오늘 만든 메서드들은 현재 Builder instance 내부에 스택으로 저장되지 않고, 즉시 실행되는 형태를 가진다.

이렇게 만들어진 까닭은, 이 메서드들이 from 메서드 내부에 종속될 거라고 예상되기 때문이다.

대부분의 경우, from의 값을 꾸미는 데 사용될 것이기 때문에 이런 패턴을 강제했다.

 

slove

/**
 * A function that unravels a subBuilder and converts it all intro a string.
 */
private slove(target: string | ((subBulder: RegExpBuilder) => string | RegExpBuilder)) {
    if (typeof target === 'string') {
        return target;
    } else {
        const result = target(new RegExpBuilder());
        if (typeof result === 'string') {
            return result;
        } else {
            return result.getRawOne();
        }
    }
}

내가 정의한 메서드들은 string과 function 타입을 받고, function 타입은 RegExpBuilder나 string을 반환한다.

이는 단순히 문자열일 때보다 사용자들이 더 쉽게 정규표현식을 작성할 수 있게 돕고, 휴먼 에러를 방지한다.

다만 이로 인해, 매번 문자인지, 함수라면 실행해서 정규식 빌더가 나오는지 문자열이 나오는지 체크해야 한다.

이 문제를 해결하려고 일단 slove method를 만들었다.

 

and

and(subBuilder: (regExpBuilder: RegExpBuilder) => RegExpBuilder, options?: AndOptions): this;
and(subBuilder: (regExpBuilder: RegExpBuilder) => string, options?: AndOptions): this;
and(partial: string, options?: AndOptions): this;

/**
 * and method set initial value to `${partial}${from.value}` OR `${from.value}${partial}`
 * @param partial  string (=pattern) or sub-expression / words or phrases you want to add
 * @returns
 */
and(
    partial: string | ((subBuilder: RegExpBuilder) => string | RegExpBuilder),
    options: AndOptions = { isForehead: true },
): this {
    const from = this.step.find((el) => el.name === 'from');
    const value: string = this.slove(partial);

    if (options?.isForehead === true) {
        from.value = `${value}${from.value}`;
    } else {
        from.value = `${from.value}${value}`;
    }

    return this;
}

초기 값의 앞과 뒤, 둘 중 하나를 선택해서 단어를 붙일 수 있게 만들었다.

 

or

or(subBuilder: (regExpBuilder: RegExpBuilder) => RegExpBuilder): this;
or(subBuilder: (regExpBuilder: RegExpBuilder) => string): this;
or(partial: string): this;

/**
 * or method set initial value to `${from.value}|${partial}`;
 * @param partial string (=pattern) or sub-expression
 * @returns
 */
or(partial: string | ((subBuilder: RegExpBuilder) => string | RegExpBuilder)): this {
    const from = this.step.find((el) => el.name === 'from');
    const value: string = this.slove(partial);

    from.value = `${from.value}|${value}`;
    return this;
}

or method는 정규식의 문자들을 붙여, 선택적으로 고를 수 있게 도와준다.

그냥 작성해도 되는 것을 굳이 메서드로 분리한 것은, 긴 정규식일수록 가독성이 심각하게 떨어지는 탓이다.

or 과 and method는 가독성을 위한 메서드라고 봐도 무방하다.

이 메서드가 from 내부에서 subBuilder 와 함께 쓰이면 이전 정규식들의 문제를 해결할 수 있을 거로 본다.

 

join

/**
 * The `join` method create and returns a new string ( = pattern ) by concatenating all of the elements,
 * like as array.prototype.join
 * @param partial string (=pattern) or sub-expression
 * @param separator
 */
join(partials: (string | ((subBuilder: RegExpBuilder) => string | RegExpBuilder))[], separator: string = '') {
    return partials.map((partial) => this.slove(partial)).join(separator);
}

여러 개의 문자열 또는 subBuilder로 정의된 경우, 이를 합쳐주는 메서드로 join 메서드를 제공한다.

from 내부에서, 계속 and, and, and…, or, or, or…과 같이 반복된 subBilder를 작성해야 할 경우 사용한다.

이 join 메서드는 내부 배열로 받은 partials를 array.prototype.join으로 합쳐주는 역할을 한다.

반응형