671
20
장
스칼라 도메인 특화 언어
➍ 네 가지 가능한 공제를 인식한다.
➎ 네 가지 공제에 대한 구문분석기를 생성하는 도우미 함수를 호출한다.
➏ 네 가지 공제에 대한 도우미 메서드다.
➐
amount
를 계산한다. 배정도 부동소수점수 뒤에
dollars
나
percent
가 온다. 그에 대응하는
Amount
인스턴스를 만들어낸다.
biweekly
를 더 자세히 살펴보자. 다음은 설명을 돕기 위해 그것을 다시 쓴 것이다.
"
biweekly
"
~
>
"{"
~
>
deductions
<
~
"}"
//
➊
^^
{
ds
=
>
Deductions
("
Biweekly
",
26
.
0
,
ds
)
}
//
➋
➊ 세 말단 토큰
terminal
token
인
biweekly
, {,
}을 찾되,
{...}
안의
deductions
에 대한 생성 규
칙
production
을 평가하면서 찾는다. 화살표처럼 생긴 연산자 (실제로는 메서드)인
~
>
와
<
~
는 화살
표의 꼬리인
~
쪽의 토큰을 (확인만 하고 ) 버리라는 뜻이다. 따라서
{
나
}
리터럴은 없어지고
deductions
의 결과만 반환값에 남는다.
➋
^^
연산자는 생성 규칙에 대한 좌변(축약할 토큰)과 우변 (문법 규칙)을 분리한다. 문법 규
칙은 남은 토큰을 인자로 취한다. 토큰을 둘 이상 남겼다면, 예를 들어
{
case
t1
~
t2
~
t2
=
>
... }
와 같은 형태의 부분 함수 리터럴을 사용한다. 이 예제의 경우
ds
는
Deductions
의 인스턴
스를 만들기 위해 사용했던
Deduction
인스턴스의
Vector
다.
여기서는 내부
DSL
에 있던
DeductionBuilder
가 필요 없다.
progscala2
.
dsls
.
payroll
.
parsercomb
.
DSLSpec
테스트를 보라. 그 테스트는 스칼라체크를 활용해서 가능한 모든 경우를
다 검증한다.
20.4
내부
DSL
과 외부
DSL
에 대한 마지막 고찰
사용자가 사용하는 내부
DSL
과 외부
DSL
을 비교해보자. 다음은 내부
DSL
을 다시 쓴 것이다.
672
4
부
고급 주제 및 실전 응용
val biweeklyDeductions
=
biweekly
{
deduct
=
>
deduct federal
_
tax
(
25
.
0 percent
)
deduct state
_
tax
(
5
.
0 percent
)
deduct insurance
_
premiums
(
500
.
0 dollars
)
deduct retirement
_
savings
(
10
.
0 percent
)
}
다음은 외부
DSL
을 다시 쓴 것이다.
val input
=
"""
biweekly
{
federal tax 20
.
0 percent
,
state tax 3
.
0 percent
,
insurance premiums 250
.
0 dollars
,
retirement savings 15
.
0 percent
}"""
외부
DSL
이 더 단순하다. 하지만 사용자는
DSL
을 문자열 안에 넣어야 한다. 따라서 코드 자동
완성, 리팩토링, 문법 하이라이팅, 기타 다른
IDE
기능 등은 사용할 수 없다.
반면 외부
DSL
이 구현하기 더 쉽다 (그리고 더 재미있다). 스칼라 구문분석을 요령껏 사용하는
것에 의존함으로써 생기는 취약점도 더 적다.
여러분의 상황에서 각각의 장단점 중 어떤 것이 가장 중요한지 평가할 수 있어야 한다.
DSL
이 스
칼라와 ‘충분히 가까워서’ 용납할 만한 노력으로 튼튼한 내부 구현이 가능하다면, 사용자 경험도
일반적으로 더 나아질 것이다. 따라서 앞에서 언급한 것과 같은 테스트용 라이브러리에서는 내
부
DSL
이 분명 최고의 선택이다.
DSL
이 스칼라 구문과 너무 동떨어져 있다면 (아마도
SQL
과
같이 이미 잘 알려진 언어라면 그럴 수 있을 것이다) 문자열을 사용하는 외부
DSL
을 사용하는
것이 가장 좋을 것이다.
우리가 원하는 대로 문자열 인터폴레이션을 만들 수 있다는 사실을 기억하라 (
5
.
3
.
1
절 ‘자신만
의 문자열 인터폴레이션 만들기’ 참조). 콤비네이터로 만든 구문분석기를 좀 더 쉬운 문법 뒤
에 숨기고 싶을 때 그런 기능이 유용하다. 예를 들어 여러분이 일종의
SQL
구문분석기를 구현
한다면, 사용자가 좀 전에 본 예제처럼 구문분석기
API
를 명시적으로 호출하도록 하는 대신
sql
"
SELECT
*
FROM
table
WHERE
...;"
라는 형태로 구문분석기를 호출하도록 만들어라.
Get 프로그래밍 스칼라: 실용적인 스칼라 활용법을 익히는 가장 확실한 실전 바이블 (2.11.x 버전 기반) now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.