1.10. 구두점과 연산자 토큰
이 문서는 연산자와 구두점 글자열의 토큰화 규칙을 다루며, 어휘 형태에 한정해 설명합니다. 각 토큰의 의미, 즉 우선순위와 결합성, 어떤 트레잇으로 디스패치되는지 등은 3. 표현식 에서 정의합니다.
1.10.1. 토큰화 원칙
연산자와 구두점의 토큰화는 두 단계로 이루어집니다. 첫째로 고정 토큰표가 있어서, 본 문서에 명시된 글자열은 항상 정해진 토큰으로 분리됩니다. 둘째로 확장 토큰표가 있어서, 표준 라이브러리가 메타 시스템을 통해 추가 등록한 글자열도 토큰이 됩니다. 등록 메커니즘은 #[infix] / #[prefix] / #[postfix] 매직 에서 정의합니다.
두 표 사이에 충돌이 생기는 경우에는 등록 시점에 거부되며, 고정 토큰은 덮어쓸 수 없습니다.
1.10.2. 최장 일치
중요
여러 토큰 후보가 가능한 입력에서는 가장 긴 일치가 선택됩니다.
| 입력 | 토큰화 |
|---|---|
== | 한 토큰 |
= | 한 토큰 |
= = | 두 토큰 (공백이 분리) |
..= | 한 토큰 (..= 가 .. 보다 깁니다) |
.. | 한 토큰 |
<<= | 한 토큰 (<<= 가 << 보다 깁니다) |
1.10.3. 고정 토큰표
다음은 언어가 예약하는 ASCII 영역의 연산자와 구두점 글자열의 전체 목록입니다. 표준 라이브러리는 이 토큰들에 의미를 부여, 즉 트레잇 메서드 매핑을 부여할 뿐이며, 토큰 형태 자체는 본 표가 결정합니다.
산술 / 비교 / 논리
+ - * / % %%
== != < > <= >=
&& || !
& | ^ ~ << >>
% 는 산술 나머지 (Rem - 부호는 피제수 따름) 이며, %% 는 floored modulo (결과의 부호가 제수를 따름 - 양수 제수에 대해 늘 [0, divisor) 범위, Python 의 %) 입니다. 두 토큰은 별개의 트레잇으로 매핑되며 의미가 다릅니다.
각 토큰이 어떤 트레잇 메서드를 호출하는지에 대한 매핑은 표준 라이브러리의 연산자 사양에서 정의됩니다. 본 문서에서는 어휘 토큰화만 보장한다는 점을 밝혀 둡니다.
브로드캐스트 (. 접두)
원소별 (broadcast) 연산을 위한 점-접두 형태입니다. 위 산술, 비교, 논리, 비트, shift 연산자에 점을 한 글자 앞에 붙인 형태가 별개의 토큰으로 분리됩니다.
.+ .- .* ./ .% .%%
.== .!= .< .> .<= .>=
.&& .||
.& .| .^ .<< .>>
이 형태는 각각 점이 없는 형태와 다른 트레잇 메서드로 매핑됩니다. 예를 들어 + 는 Add::add 로, .+ 는 DotAdd::dot_add 로 매핑되며, 이러한 매핑은 표준 라이브러리에서 정의합니다. 한편 점-접두 논리 연산자 (.&&, .||) 는 점 없는 형태와 달리 short-circuit 평가를 하지 않으며 - broadcast 가 fused loop 으로 lower 되는 특성상 양쪽 인자가 모두 평가됩니다 (자세한 내용은 2.6 broadcast 참고).
부동소수 리터럴과의 구분
부동소수 리터럴인 1. 이나 1.5 가 점을 포함하므로, 다음 두 입력의 토큰화는 위치에 따라 달라집니다.
| 입력 | 토큰화 | 이유 |
|---|---|---|
1.+2 | 1., +, 2 | . 가 숫자 직후이므로 부동소수의 일부로 흡수 |
a.+b | a, .+, b | . 가 숫자 직후가 아니므로 브로드캐스트 토큰 시작 |
규칙을 정리하면, 숫자 리터럴 도중의 . 은 항상 부동소수의 일부이며, 그 외 위치의 . 은 다른 토큰 형태를 우선합니다 (숫자 리터럴 의 . 처리 규칙을 참조합니다).
Unicode 수학 연산자
다음 Unicode 연산자도 고정 토큰입니다. 우선순위는 3.2.3 표가 정하고, 연결되는 트레잇은 표준 라이브러리 2.3 ops 가 정합니다.
× ⋅ ÷ ∘ √
≡ ≠ ≤ ≥
∈ ∉ ⊂ ⊆ ∪ ∩
| 토큰 | 코드포인트 | 의미 (ASCII 이름 메서드) |
|---|---|---|
× | U+00D7 | 외적 (cross) |
⋅ | U+22C5 | 내적 (dot) |
÷ | U+00F7 | 나눗셈 (div, / 의 동의어) |
∘ | U+2218 | 함수 합성 (compose) |
√ | U+221A | 제곱근, 전위 (sqrt) |
≡ ≠ ≤ ≥ | U+2261, U+2260, U+2264, U+2265 | == != <= >= 의 동의어 |
∈ ∉ | U+2208, U+2209 | 원소 포함 (contains) |
⊂ ⊆ | U+2282, U+2286 | 부분집합 (is_proper_subset, is_subset) |
∪ ∩ | U+222A, U+2229 | 합집합, 교집합 (union, intersection) |
연산자 글자는 모두 Unicode Pattern_Syntax 속성을 가진 코드포인트에서 고릅니다. ∑ ∏ ∫ 는 Pattern_Syntax 이지만 식별자 글자로 정했으므로 (1.4.1) 연산자가 아닙니다.
대입 / 복합 대입
= += -= *= /= %= %%=
&= |= ^= <<= >>=
복합 대입의 의미, 즉 좌변 평가 횟수와 트레잇 매핑 등은 표현식 사양에서 정의합니다. %%= 는 %% (floored modulo) 의 복합 대입 형태이며, 최장 일치 규칙에 따라 %%= 가 %= 또는 % 보다 먼저 매칭됩니다.
범위 / 슬라이스
.. ..= : ::
여기에서 .. 와 ..= 는 범위 표기에 사용됩니다. : 는 슬라이스의 자리 구분자, 형식 지정자 도입자, 그 외 여러 문맥에서 사용됩니다. :: 는 경로 구분자로서 모듈이나 타입의 정적 항목 접근에 사용됩니다.
점 / 물음표
. ?. ?? ?
. 은 멤버 또는 메서드 접근에 사용됩니다. ?. 은 합 타입을 통과시키는 점 접근입니다. ?? 는 빈 자리 (none) 를 대체값으로 메우는 이항 연산입니다. 마지막으로 ? 는 단독 물음표로서 T | none 값이 none 이면 둘러싼 함수에서 none 을 조기 반환하는 후위 단항 연산자입니다. 자세한 의미와 desugar 규칙은 에러 제어 흐름 의 ? 연산자 절에서 정의합니다.
try? 와 try! 는 하나의 토큰이 아닙니다. 어휘 분석은 키워드 try 와 구두점 ? 또는 ! 를 각각의 토큰으로 만들고, 구문 분석이 try 바로 뒤에 공백 없이 붙은 ? / ! 를 try? / try! 접두 연산자로 해석합니다. 공백이 있으면 try !ready() 처럼 try 와 논리 부정 ! 로 해석합니다.
작은따옴표 토큰: 문자 리터럴 vs 라벨
' 토큰은 두 형태로 분기합니다. 첫 번째는 'X' 또는 '\X' 형태로, 단일 문자 (또는 escape) 다음에 닫는 ' 가 오는 형태이며 문자 리터럴 에 해당합니다. 두 번째는 'identifier 형태로, 닫는 ' 가 없는 식별자 형태이며 라벨 토큰에 해당합니다 (라벨 과 라벨 블록 을 참조합니다).
어휘 분석은 ' 다음 두 바이트를 보고 결정합니다. 식별자 시작 다음에 닫는 ' 가 오면 문자이고, 식별자 시작 다음에 식별자나 콜론, 공백처럼 닫는 ' 가 아닌 토큰이 오면 라벨이며, escape ('\...) 는 항상 문자 리터럴입니다.
람다 / 화살표
| || -> =>
| 는 비트 OR, 합 타입 구분자, 람다 인자 구분자로 문맥에 따라 사용됩니다. || 는 논리 OR 또는 인자 없는 람다 시작에 사용됩니다. -> 는 함수 반환 타입 화살표이고, => 는 match 가지 화살표입니다.
구두점
( ) [ ] { }
, ; @
각 구두점의 쓰임은 다음과 같습니다. ( ) 는 그룹화, 튜플, 호출에 사용됩니다. [ ] 는 인덱싱, 슬라이스, 캡처 리스트, 배열 리터럴에 사용됩니다. { } 는 블록, 복합 리터럴, 구조체 리터럴에 사용됩니다. , 는 인자나 항목 구분자로 쓰이고, ; 는 문장 종결자입니다 (문장 종결자 를 참고합니다). 마지막으로 @ 는 메타 시스템의 토큰이며, 정확한 의미는 6장에서 다룹니다.
속성 도입자
#[ #![
여기에서 #[ 는 다음 항목에 부착되는 속성, 즉 외부 속성을 도입합니다. #![ 는 둘러싸는 항목 또는 모듈에 부착되는 속성, 즉 내부 속성을 도입합니다.
이 두 도입자는 각각 하나의 고정 토큰으로 분리됩니다. # 과 [ 사이에 공백을 둘 수 없으며, 별개 토큰 # 다음 [ 는 정의되지 않습니다.
외부와 내부의 한 쌍은 어휘 구조 의 문서 주석 /// 와 //! 와 같은 패턴입니다. 부착 방향만 다를 뿐 의미는 동일하게 묶입니다.
1.10.4. 확장 토큰
위 고정 표 외에, 표준 라이브러리나 사용자가 등록할 수 있는 글자열은 다음 조건을 만족해야 합니다. 모든 글자가 Pattern_Syntax 코드포인트여야 하고, 식별자 글자 (1.4.1) 가 전혀 포함되지 않아야 하며, 공백과 줄 종결자도 포함되지 않아야 합니다. 또한 고정 토큰과 같으면 안 됩니다.
예를 들면 ⊕, ⊗, ⋆, ° 같은 글자열을 들 수 있습니다. 확장 토큰의 우선순위는 등록할 때 like 로 지정한 기존 토큰을 따릅니다 (6.7.2).
이러한 글자열을 등록하면 렉서가 그 글자열을 한 토큰으로 잘라냅니다. 등록 시점과 구문, 의미는 #[infix] / #[prefix] / #[postfix] 매직 에서 정의합니다.
1.10.5. 토큰화 대상이 아닌 것
다음 요소들은 토큰이 아니라 더 큰 단위의 일부분에 해당합니다. f"..." 의 f 는 문자열 리터럴 의 형식 문자열 접두입니다. r"..." 의 r 와 r#"..."# 의 r# 는 원시 문자열 접두입니다. c'...' 의 c 는 문자 리터럴 의 C 호환 문자 접두입니다. 그리고 숫자 리터럴 뒤에 붙는 타입 접미사도 여기에 속하며, 자세한 내용은 숫자 리터럴 을 참고합니다.
이들은 본 문서의 토큰표에 등장하지 않으며, 그 자리에서 식별자나 일반 토큰으로 토큰화되지도 않습니다.