리스펙스 구문: 생각의 원자들

복잡한 규칙은 없습니다. 리스펙스의 모든 논리를 구축하는 가장 작은 단위인 토큰, 리터럴, 그리고 S-표현식의 순수한 세계를 탐험하세요.

리스펙스 구문 참조입니다. 이 문서는 입력 전용 S-표현식 문법Core AST로의 결정적 정규화 규칙을 정의합니다. 실행 의미와 표준 라이브러리 동작은 범위 밖입니다.

범위: 입력 문법 + 정규화. 사용자 매크로/리더 확장은 허용되지 않습니다. R5RS-compat 토글이 일부 규칙을 조정합니다(정확한 목록은 전체 사양 참조).

0) 파일 헤더(선택)

;! lispex 1.1
;! compat: r5rs   ; R5RS-compat 모드 활성화

1) 인코딩 / 공백 / 주석

  • 인코딩: UTF‑8
  • 공백: space, tab, CR, LF
  • 주석: 한 줄 ; ..., 블록 #| ... |#(중첩 가능)

2) 토큰 & 리터럴

심벌(identifier)

대소문자 구분, 유니코드 허용. 개념적 정규식: [^()\[\]{}\s"';,]+`. 예약어는 바인딩 금지(아래 참조).

불리언

#t   #f

숫자(입력형)

  • 정수(10진): 0 | -?[1-9][0-9]*
  • 유리수: p/q (분모 0 금지)
  • 실수: -?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?

문자 / 문자열

  • 문자: #\a, #\space, #\x03B1
  • 문자열: "..." — 이스케이프 \" \\ \n \t \r \xHH;

리스트 / 점리스트 / 벡터 / 바이트벡터

  • 리스트: (a b c); 점리스트: (a b . c)
  • 벡터: #(a b c)
  • 바이트벡터: #u8(0 255 ...)

인용 계열(리더 축약)

'x      ⇒ (quote x)
`x      ⇒ (quasiquote x)
,x      ⇒ (unquote x)
,@xs    ⇒ (unquote-splicing xs)

3) 모듈 헤더(선택)

(module <name>
  (export id ...)
  (import <name> ...)
  body ...)

<name>은 심벌 또는 점-경로(util.string)입니다. 이 표면 헤더에는 rename/only/except가 없습니다. 모듈 없는 파일도 허용됩니다.

참고: 이 헤더는 선택 사항이며 가이드에서는 사용하지 않습니다. 리스펙스는 변환기 기반이므로, 예제는 최소한의 최상위 폼만 사용합니다. 일부 도구는 변환 과정에서 이 헤더를 평탄화하거나 무시할 수 있습니다.

4) 예약어(키워드) — 바인딩 금지

quote quasiquote unquote unquote-splicing
lambda if begin set! define let let* letrec
cond case and or when unless do
values call-with-values
call/cc dynamic-wind
module export import

다음 사용자 매크로/리더 확장 사용 시 즉시 오류: define-syntax syntax-rules syntax-case let-syntax letrec-syntax #lang #;.

5) Core 폼 — 정규화 후 남는 형태

(lambda (formals) body+)
(if test then else)
(begin e1 ... en)
(set! id expr)
(define id expr)
(define (f params) body+)      ; 정규화 시 define+lambda로 환원
(let ((id expr) ...) body+)
(letrec ((id expr) ...) body+)
(quote datum)
(quasiquote template)          ; §10 전개 규칙 후 Core로 수렴
(values expr*)
(call-with-values producer consumer)
(call/cc proc)
(dynamic-wind before thunk after)

6) 파생 폼 — 결정적 정규화

함수 정의 설탕

(define (f a b) body...) ⇒ (define f (lambda (a b) body...))

let*

(let* ((x e1) (y e2) ...) body)
⇒ (let ((x e1)) (let* ((y e2) ...) body))

cond

(cond (t1 b1...) ... (else e...))
⇒ (if t1 (begin b1...)
      (if t2 (begin b2...)
          ...
          (begin e...)))

(=> 변형은 v1 미지원)

case (equal?로 서술)

(case key
  ((k11 k12 ...) b1...)
  ...
  (else e...))
⇒ (let ((t key))
     (if (equal? t k11) (begin b1...)
         (if (equal? t k12) (begin b1...)
             ...
             (begin e...))))

and / or

(and)              ⇒ #t
(and e1)           ⇒ e1
(and e1 e2 ... en) ⇒ (if e1 (and e2 ... en) #f)

(or)               ⇒ #f
(or e1)            ⇒ e1
(or e1 e2 ... en)  ⇒ (let ((t e1)) (if t t (or e2 ... en)))

R5RS-compat 노트: ;! compat: r5rs 활성 시, 바이트벡터 표기와 일부 판별자/포트 세부 규칙이 R5RS 변형을 따릅니다.