v1.0.0
1/11/2021 에 게시됨 – 텍스트 버전

TOML v1.0.0

Tom's Obvious, Minimal Language.

By Tom Preston-Werner, Pradyun Gedam, et al.

목표

TOML은 명확한 의미를 가져 읽기 쉬운 최소한의 구성 파일 포맷을 목표로 합니다. TOML은 해시 테이블에 분명하게 대응되도록 설계되었습니다. TOML은 여러 언어에서 데이터 구조로 변환하기에 용이할 것입니다.

명세

  • TOML은 대소문자를 구별합니다.
  • TOML 파일은 UTF-8으로 인코딩된 유효한 유니코드 문서여야 합니다.
  • 공백은 탭(0x09)과 스페이스(0x20)를 의미합니다.
  • 개행은 LF(0x0A)와 CRLF(0x0D 0x0A)를 의미합니다.

주석

해시 기호는 문자열의 일부일 때를 제외하면 줄의 뒷부분을 주석으로 표시합니다.

# 이 줄은 전부 주석입니다
key = "value"  # 이건 줄 끝에 붙은 주석입니다
another = "# 이건 주석이 아닙니다"

탭이 아닌 제어 문자(U+0000에서 U+0008까지, U+000A에서 U+001F까지, U+007F)는 주석의 일부가 될 수 없습니다.

키/값 쌍

TOML 문서를 구성하는 주요 요소는 키/값 쌍입니다.

키는 등호의 왼쪽에, 값은 오른쪽에 위치합니다. 키 이름과 값을 둘러싼 공백은 무시됩니다. 키, 등호, 값은 같은 줄에 있어야 합니다만, 일부 값은 여러 줄에 걸쳐 위치할 수 있습니다.

key = "value"

값은 다음 중 하나의 타입을 가져야 합니다.

지정되지 않은 값은 유효하지 않습니다.

key = # 유효하지 않음

키/값 쌍 다음에는 개행(또는 EOF)이 와야 합니다. (예외로, 인라인 테이블을 보세요.)

first = "Tom" last = "Preston-Werner" # 유효하지 않음

키에는 기본 키, 따옴표를 씌운 키, 점을 찍은 키가 있습니다.

기본 키(Bare keys)는 ASCII 문자, ASCII 숫자, 언더스코어, 그리고 대시로만 구성됩니다(A-Za-z0-9_-). ASCII 숫자로만 구성된 기본 키(예를 들어, 1234)도 유효하지만, 항상 문자열로 해석됨에 주의해야 합니다.

key = "value"
bare_key = "value"
bare-key = "value"
1234 = "value"

따옴표를 씌운 키(Quoted keys)는 기본 문자열이나 리터럴 문자열과 정확히 같은 규칙을 따르며, 더 다양한 키 이름을 사용할 수 있게 해줍니다. 정말 필요할 때를 제외하면 기본 키를 사용하는 것이 권장됩니다.

"127.0.0.1" = "value"
"character encoding" = "value"
"ʎǝʞ" = "value"
'key2' = "value"
'quoted "value"' = "value"

기본 키는 비어 있을 수 없지만, 따옴표를 씌운 키는 비어 있을 수 있습니다(권장되지는 않습니다).

= "no key name"  # 유효하지 않음
"" = "blank"     # 유효함, 권장되지 않음
'' = 'blank'     # 유효함, 권장되지 않음

점을 찍은 키(Dotted keys)는 점으로 연결된 기본 또는 따옴표를 씌운 키의 나열입니다. 점을 찍은 키를 이용하면 비슷한 속성들을 서로 묶을 수 있습니다.

name = "Orange"
physical.color = "orange"
physical.shape = "round"
site."google.com" = true

이는 다음 JSON과 대응됩니다.

{
  "name": "Orange",
  "physical": {
    "color": "orange",
    "shape": "round"
  },
  "site": {
    "google.com": true
  }
}

점을 찍은 키가 정의하는 테이블에 대한 자세한 사항은 아래의 테이블 섹션을 참조하세요.

점으로 구분된 각 부분을 둘러싼 공백은 무시됩니다만, 공백을 쓰지 않는 것이 권장됩니다.

fruit.name = "banana"     # 권장됨
fruit. color = "yellow"    # fruit.color와 같음
fruit . flavor = "banana"   # fruit.flavor와 같음

들여쓰기는 공백으로 처리되며, 무시됩니다.

같은 키를 여러 번 정의하는 것은 유효하지 않습니다.

# 이렇게 하지 마세요
name = "Tom"
name = "Pradyun"

기본 키와 따옴표를 씌운 키는 동등합니다.

# 이래도 안됩니다
spelling = "favorite"
"spelling" = "favourite"

키가 직접 정의되지 않은 한, 그 키나 키 안의 이름에 값을 쓰는 것이 가능합니다.

# 이러면 키 "fruit"에 테이블이 대응됩니다.
fruit.apple.smooth = true

# 그러므로 테이블 "fruit"에 다음과 같이 값을 추가할 수 있습니다.
fruit.orange = 2
# 다음은 유효하지 않습니다

# 여기서는 fruit.apple의 값을 정수로 정의합니다.
fruit.apple = 1

# 하지만 여기선 fruit.apple이 테이블인 것처럼 다룹니다.
# 정수를 테이블로 바꿀 수는 없습니다.
fruit.apple.smooth = true

점을 찍은 키를 어긋난 순서로 정의하는 것은 권장되지 않습니다.

# 유효하지만 권장되지 않음

apple.type = "fruit"
orange.type = "fruit"

apple.skin = "thin"
orange.skin = "thick"

apple.color = "red"
orange.color = "orange"
# 권장됨

apple.type = "fruit"
apple.skin = "thin"
apple.color = "red"

orange.type = "fruit"
orange.skin = "thick"
orange.color = "orange"

ASCII 숫자만으로도 기본 키를 구성할 수 있으므로, 부동소수점 같아 보이는 점을 찍은 키를 정의하는 것이 가능합니다. 그럴만한 이유가 있는게 아니라면, 그러지 마세요(아마 없을 겁니다).

3.14159 = "pi"

위 TOML은 다음 JSON에 대응됩니다.

{ "3": { "14159": "pi" } }

문자열

문자열을 나타내는 방법은 총 네 가지, 즉 기본, 여러 줄 기본, 리터럴, 그리고 여러 줄 리터럴이 있습니다. 문자열에는 유효한 UTF-8 문자만이 포함되어야 합니다.

기본 문자열(Basic strings)은 큰 따옴표(")로 둘러싸여집니다. 이스케이프될 필요 없는 문자는 모두 사용될 수 있습니다. 이스케이프되어야 하는 문자로는 따옴표, 백슬래시, 탭이 아닌 제어 문자(U+0000에서 U+0008, U=000A에서 U+001F, U+007F)가 있습니다.

str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."

편의를 위해, 자주 사용되는 문자들에 대한 짧은 이스케이프 문자열이 제공됩니다.

\b         - 백스페이스  (U+0008)
\t         - 탭          (U+0009)
\n         - 라인 피드   (U+000A)
\f         - 폼 피드     (U+000C)
\r         - 캐리지 리턴 (U+000D)
\"         - 큰따옴표    (U+0022)
\\         - 백슬래시    (U+005C)
\uXXXX     - 유니코드    (U+XXXX)
\UXXXXXXXX - 유니코드    (U+XXXXXXXX)

\uXXXX 또는 \UXXXXXXX 형태를 이용해 어느 유니코드 문자든 이스케이프할 수 있습니다. 이스케이프 코드는 유효한 유니코드 스칼라 값 이어야 합니다.

다른 모든 이스케이프 문자열은 예약되어 있습니다. 사용된 경우, TOML 구현은 에러를 발생시켜야 합니다.

경우에 따라, 긴 문단을 나타내거나 (예를 들어, 번역 파일) 매우 긴 문자열을 여러 줄에 걸쳐 나타내고 싶을 때가 있습니다. TOML에서는 이를 쉽게 할 수 있습니다.

여러 줄 기본 문자열(Multi-line basic strings)은 양 쪽에 3개의 큰따옴표로 둘러싸이며, 안에 개행을 포함할 수 있습니다. 여는 큰따옴표 바로 다음에 오는 개행은 제거됩니다. 모든 다른 공백과 개행은 유지됩니다.

str1 = """
Roses are red
Violets are blue"""

TOML 파서는 개행을 플랫폼에 따라 적절한 문자열로 변환해도 됩니다.

# 유닉스 시스템에서는, 위 여러 줄 문자열은 아마 다음과 같을 것입니다.
str2 = "Roses are red\nViolets are blue"

# 윈도우 시스템에서는, 아마 다음과 같을 것입니다.
str3 = "Roses are red\r\nViolets are blue"

공백을 추가하지 않고 긴 문자열을 쓰려고 한다면, "줄 끝 백슬래시(line ending backslash)"를 사용하십시오. 줄에서 공백이 아닌 마지막 글자가 이스케이프되지 않은 \일 경우, 이 백슬래시는 다음 공백이 아닌 문자 또는 닫는 따옴표가 나올 때까지의 모든 공백(개행 포함)과 함께 제거됩니다. 기본 문자열에서 유효한 모든 이스케이프 문자열은 여러 줄 기본 문자열에서도 유효합니다.

# 다음 문자열들은 바이트 단위로 동일합니다.
str1 = "The quick brown fox jumps over the lazy dog."

str2 = """
The quick brown \


  fox jumps over \
    the lazy dog."""

str3 = """\
       The quick brown \
       fox jumps over \
       the lazy dog.\
       """

이스케이프할 필요가 없는 유니코드 문자는 모두 사용할 수 있습니다. 이스케이프되어야 하는 문자로는 백슬래시와, 탭이나 라인 피드나 캐리지 리턴이 아닌 제어 문자들이 있습니다 (U+0000에서 U+0008, U+000B, U+000C, U+000E에서 U+001F, U+007F).

여러 줄 기본 문자열 안에는 큰따옴표나 2개의 인접한 큰따옴표가 어디에나 나타나도 됩니다. 열거나 닫는 큰따옴표와 인접하게도 나타날 수 있습니다.

str4 = """Here are two quotation marks: "". Simple enough."""
# str5 = """Here are three quotation marks: """."""  # 유효하지 않음
str5 = """Here are three quotation marks: ""\"."""
str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""

# "This," she said, "is just a pointless statement."
str7 = """"This," she said, "is just a pointless statement.""""

Windows 경로나 정규표현식을 자주 사용한다면, 백슬래시를 항상 이스케이프하는 것은 매우 귀찮고 틀리기 쉬운 일입니다. 이러한 상황을 위해, TOML은 이스케이프를 아예 처리하지 않는 리터럴 문자열을 포함합니다.

리터럴 문자열(Literal strings)은 작은따옴표로 둘러싸입니다. 기본 문자열과 같이, 리터럴 문자열은 한 줄로 표현되어야 합니다.

# What you see is what you get.
winpath  = 'C:\Users\nodejs\templates'
winpath2 = '\\ServerX\admin$\system32\'
quoted   = 'Tom "Dubs" Preston-Werner'
regex    = '<\i\c*\s*>'

이스케이프가 없으므로, 작은따옴표로 둘러싸인 리터럴 문자열은 작은따옴표를 포함할 수 없습니다. 다행히도, TOML은 이 문제를 해결하는 여러 줄 리터럴 문자열을 지원합니다.

여러 줄 리터럴 문자열(Multi-line literal strings)는 양 쪽에 세 개의 작은따옴표로 둘러 싸이며, 개행을 포함할 수 있습니다. 리터럴 문자열과 같이, 이스케이프는 지원하지 않습니다. 여는 작은따옴표 바로 다음에 오는 개행은 제거됩니다. 작은따옴표 사이의 다른 모든 내용은 있는 그대로 해석됩니다.

regex2 = '''I [dw]on't need \d{2} apples'''
lines  = '''
The first newline is
trimmed in raw strings.
   All other whitespace
   is preserved.
'''

여러 줄 리터럴 문자열 안 어디에든 1개나 2개의 연속된 작은따옴표가 포함될 수 있지만, 3개 이상의 연속된 작은따옴표는 허용되지 않습니다.

quot15 = '''Here are fifteen quotation marks: """""""""""""""'''

# apos15 = '''Here are fifteen apostrophes: ''''''''''''''''''  # 유효하지 않음
apos15 = "Here are fifteen apostrophes: '''''''''''''''"

# 'That,' she said, 'is still pointless.'
str = ''''That,' she said, 'is still pointless.''''

리터럴 문자열에 탭이 아닌 제어 문자는 허용되지 않습니다. 그러므로, 이진 데이터를 표현하려 한다면, Base64나 다른 적절한 ASCII 또는 UTF-8 인코딩을 이용할 것이 권장됩니다. 해당 인코딩을 다루는 방식은 응용 프로그램이 정의합니다.

정수

양수 앞에는 플러스 기호가 올 수 있으며, 음수 앞에는 마이너스 기호가 옵니다.

int1 = +99
int2 = 42
int3 = 0
int4 = -17

큰 수를 쓸 때는, 가독성을 위해 숫자 사이에 언더스코어를 쓸 수 있습니다. 각 언더스코어의 양 쪽에는 적어도 하나의 숫자가 와야 합니다.

int5 = 1_000
int6 = 5_349_221
int7 = 53_49_221  # 인도식 표기법
int8 = 1_2_3_4_5  # 유효하지만 권장되지 않음

0이 아닌 수의 맨 앞에 0이 오는 것은 허용되지 않습니다. 정수 값 +0-0은 유효하며, 접두사 없는 0과 동일합니다.

음이 아닌 정수는 16진수, 8진수, 또는 2진수로도 나타낼 수 있습니다. 이 경우, 앞에 +가 오는 것은 허용되지 않으며, 접두사 다음에 0이 오는 것은 허용됩니다. 16진수 값은 대소문자를 구분하지 않습니다. 숫자 사이에 언더스코어가 오는 것이 허용되지만, 접두사와 값 사이에 오는 것은 허용되지 않습니다.

# 16진수의 접두사는 `0x`
hex1 = 0xDEADBEEF
hex2 = 0xdeadbeef
hex3 = 0xdead_beef

# 8진수의 접두사는 `0o`
oct1 = 0o01234567
oct2 = 0o755 # 유닉스 파일 권한을 표기할 때 유용함

# 2진수의 접두사는 `0b`
bin1 = 0b11010110

임의의 64비트 부호 있는 정수(−2^63에서 2^63−1까지) 값은 오차 없이 나타낼 수 있어야 합니다. 오차 발생 없이 정수를 표현할 수 없다면, 에러가 발생해야 합니다.

부동소수점

부동소수점은 IEEE binary64 값으로 구현되어야 합니다.

부동소수점은 정수 부분(10진 정수와 같은 규칙을 따릅니다), 그리고 그 뒤의 소수 부분 및 지수 부분으로 표현됩니다. 소수 부분과 지수 부분이 모두 있다면, 소수 부분이 앞에 와야 합니다.

# 소수
flt1 = +1.0
flt2 = 3.1415
flt3 = -0.01

# 지수
flt4 = 5e+22
flt5 = 1e06
flt6 = -2E-2

# 둘 다
flt7 = 6.626e-34

소수 부분은 점, 그리고 그 뒤의 하나 혹은 그 이상의 숫자들입니다.

지수 부분은 E 또는 e, 그리고 그 뒤의 정수 부분(10진 정수 값과 같은 규칙을 따르지만, 앞에 0이 오는 것이 허용됩니다)입니다.

점이 사용된다면, 점 양 쪽에 적어도 하나의 숫자가 와야 합니다.

# 유효하지 않은 부동소수점 값들
invalid_float_1 = .7
invalid_float_2 = 7.
invalid_float_3 = 3.e+20

정수와 비슷하게, 언더스코어를 이용해 가독성을 높일 수 있습니다. 각 언더스코어의 양 쪽에는 적어도 하나의 숫자가 와야 합니다.

flt8 = 224_617.445_991_228

부동소수점 값 -0.0+0.0은 유효하며, IEEE 754에 따르는 값을 가집니다.

특수한 부동소수점 값 또한 표현할 수 있습니다. 항상 소문자입니다.

# 무한대
sf1 = inf  # 양의 무한대
sf2 = +inf # 양의 무한대
sf3 = -inf # 음의 무한대

# not a number
sf4 = nan  # sNaN/qNaN 인코딩은 구현에 맡김
sf5 = +nan # `nan` 과 같음
sf6 = -nan # 유효, 실제 인코딩은 구현에 맡김

불리언

불리언은 익숙한 토큰들입니다. 항상 소문자입니다.

bool1 = true
bool2 = false

오프셋 된 날짜-시간

특정 순간을 명확하게 표현하기 위해, RFC 3339 형식 오프셋 된 날짜-시간을 사용할 수 있습니다.

odt1 = 1979-05-27T07:32:00Z
odt2 = 1979-05-27T00:32:00-07:00
odt3 = 1979-05-27T00:32:00.999999-07:00

가독성을 위해, 날짜와 시간 사이의 T 구분자를 스페이스 문자로 대체할 수 있습니다 (RFC 3339 5.6 섹션에 의해 허용됩니다).

odt4 = 1979-05-27 07:32:00Z

밀리초 정밀도는 필수적으로 지원되어야 합니다. 그 이상의 정밀도는 구현에 따라 지원될 수도 있습니다. 값의 정밀도가 구현이 지원하는 것 이상인 경우, 지원되지 않는 정밀도 부분은 반올림하지 말고 버려야 합니다.

로컬 날짜-시간

RFC 3339 형식 날짜-시간에서 오프셋을 생략하면, 타임존이나 오프셋과 무관하게 해당 날짜-시간을 나타내는 값이 됩니다. 추가 정보 없이는 특정한 순간으로 변환될 수 없습니다. 필요한 경우, 특정 순간으로 변환은 구현에 따라 다를 수 있습니다.

ldt1 = 1979-05-27T07:32:00
ldt2 = 1979-05-27T00:32:00.999999

밀리초 정밀도는 필수적으로 지원되어야 합니다. 그 이상의 정밀도는 구현에 따라 지원될 수도 있습니다. 값이 구현이 지원하는 것 이상의 정밀도를 포함할 경우, 지원되지 않는 정밀도 부분은 반올림하지 말고 버려야 합니다.

로컬 날짜

RFC 3339 형식 날짜-시간에서 날짜 부분만을 쓸 경우, 타임 존이나 오프셋과 무관하게 그날 전체를 나타내는 값이 됩니다.

ld1 = 1979-05-27

로컬 시간

RFC 3339 형식 날짜-시간에서 시간 부분만을 쓸 경우, 타임 존, 오프셋과 날짜와 무관하게 그 시각을 나타내는 값이 됩니다.

lt1 = 07:32:00
lt2 = 00:32:00.999999

밀리초 정밀도는 필수적으로 지원되어야 합니다. 그 이상의 정밀도는 구현에 따라 지원될 수도 있습니다. 값이 구현이 지원하는 것 이상의 정밀도를 포함할 경우, 지원되지 않는 정밀도 부분은 반올림하지 말고 버려야 합니다.

배열

배열은 대괄호와 그 안에 든 값들입니다. 공백은 무시됩니다. 배열의 값들은 쉼표로 구분됩니다. 배열은 키/값 쌍에 포함될 수 있는 모든 타입의 값을 가질 수 있습니다. 서로 다른 타입의 값들을 섞을 수 있습니다.

integers = [ 1, 2, 3 ]
colors = [ "red", "yellow", "green" ]
nested_arrays_of_ints = [ [ 1, 2 ], [3, 4, 5] ]
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
string_array = [ "all", 'strings', """are the same""", '''type''' ]

# 서로 다른 타입을 섞을 수 있습니다
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
contributors = [
  "Foo Bar <foo@example.com>",
  { name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
]

배열은 여러 줄에 걸쳐 나타날 수 있습니다. 배열의 마지막 값 뒤에 쉼표가 오는 것이 허용됩니다 (terminating comma 또는 trailing comma). 값, 쉼표, 그리고 닫는 대괄호 앞에 개행과 주석이 몇 개든 올 수 있습니다. 배열의 값들과 쉼표들 사이의 들여쓰기는 공백으로 처리되며, 무시됩니다.

integers2 = [
  1, 2, 3
]

integers3 = [
  1,
  2, # 이래도 됩니다
]

테이블

테이블(해시 테이블 또는 딕셔너리라고도 함)은 키/값 쌍의 모음입니다. 테이블의 헤더는 줄에 홀로 있는 대괄호로 둘러싸인 값을 말하며, 테이블은 헤더에 의해 정의됩니다. 배열은 항상 값으로만 나타나므로, 헤더와 구분할 수 있습니다.

[table]

그 아래로부터 다음 헤더나 EOF까지는 그 테이블의 키/값 쌍이 나타납니다. 테이블의 키/값 쌍은 특정한 순서로 나타난다고 보장할 수 없습니다.

[table-1]
key1 = "some string"
key2 = 123

[table-2]
key1 = "another string"
key2 = 456

테이블의 이름을 정하는 규칙은 키의 이름을 정하는 규칙과 같습니다(위에서 의 정의를 볼 수 있습니다).

[dog."tater.man"]
type.name = "pug"

이는 다음 JSON과 대응됩니다.

{ "dog": { "tater.man": { "type": { "name": "pug" } } } }

키 주변의 공백은 무시됩니다. 공백을 쓰지 않는 것이 권장됩니다.

[a.b.c]            # 권장됨
[ d.e.f ]          # [d.e.f]와 같음
[ g .  h  . i ]    # [g.h.i]와 같음
[ j . "ʞ" . 'l' ]  # [j."ʞ".'l']와 같음

들여쓰기는 공백으로 취급되며 무시됩니다.

상위 테이블을 모두 정의할 필요는 없습니다. TOML이 알아서 해줍니다.

# [x] 이거
# [x.y] 필요
# [x.y.z] 없음
[x.y.z.w] # 이것만 있어도 됨

[x] # 상위 테이블을 나중에 정의해도 괜찮음

빈 테이블은 허용되며, 안에 키/값 쌍을 포함하지 않습니다.

키와 비슷하게, 같은 테이블을 한 번 이상 정의할 수 없습니다. 그렇게 하는 것은 유효하지 않습니다.

# 하지 마세요

[fruit]
apple = "red"

[fruit]
orange = "orange"
# 이것도 하지 마세요

[fruit]
apple = "red"

[fruit.apple]
texture = "smooth"

테이블을 어긋난 순서로 정의하는 것은 권장되지 않습니다.

# 유효하지만 권장되지 않음
[fruit.apple]
[animal]
[fruit.orange]
# 권장됨
[fruit.apple]
[fruit.orange]
[animal]

최상위 테이블(또는 루트 테이블)은 문서가 시작되는 지점에서 시작되어 첫 테이블 헤더 (또는 EOF) 바로 전에 끝납니다. 다른 테이블들과는 달리, 최상위 테이블에는 이름이 없으며 다시 지정될 수 없습니다.

# 최상위 테이블 시작
name = "Fido"
breed = "pug"

# 최상위 테이블 끝
[owner]
name = "Regina Dogman"
member_since = 1999-08-04

점이 찍힌 키는 마지막을 제외한 정의되지 않은 각 부분에 대해 새 테이블을 정의합니다.

fruit.apple.color = "red"
# fruit이라는 테이블을 정의함
# fruit.apple이라는 테이블을 정의함

fruit.apple.taste.sweet = true
# fruit.apple.taste라는 테이블을 정의함
# fruit과 fruit.apple은 이미 정의되어 있음

테이블을 한 번 이상 정의하는 것은 금지되므로, 이러한 테이블을 [테이블] 헤더를 사용해 재정의하는 것은 허용되지 않습니다. 비슷하게, [테이블] 형식으로 정의된 테이블을 점이 찍힌 키를 사용해 재정의하는 것도 허용되지 않습니다. 하지만, 점이 찍힌 키를 사용해 정의된 테이블 안의 하위 테이블을 [테이블] 형태를 이용해 정의하는 것은 허용됩니다.

[fruit]
apple.color = "red"
apple.taste.sweet = true

# [fruit.apple]  # 유효하지 않음
# [fruit.apple.taste]  # 유효하지 않음

[fruit.apple.texture]  # 하위 테이블을 추가할 수 있음
smooth = true

인라인 테이블

인라인 테이블은 테이블을 표현하는 데에 쓸 수 있는 더 단순한 구문을 제공합니다. 그냥 쓰기엔 너무 장황한 테이블 데이터를 작성하는데에 특히 유용합니다. 인라인 테이블은 중괄호 {} 사이에 정의됩니다. 중괄호 사이에는 0 또는 그보다 많은 키/값 쌍이 쉼표로 구분되어 나타날 수 있습니다. 키/값 쌍은 일반 테이블의 키/값 쌍과 같은 형태를 가집니다. 값들은 인라인 테이블을 포함한 모든 타입을 가질 수 있습니다.

인라인 테이블은 한 줄에 나타나도록 의도되었습니다. 인라인 테이블의 마지막 키/값 쌍 뒤에 쉼표가 올 수 없습니다. 값의 일부로 유효하게 나타나는 것이 아닌 한, 중괄호 사이에는 개행이 올 수 없으며, 개행이 유효한 경우에도 인라인 테이블을 여러 줄에 걸쳐 작성하는 것은 권장되지 않습니다. 만일 인라인 테이블을 여러 줄에 쓰고 싶다면, 일반 테이블을 써야한다는 뜻입니다.

name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
animal = { type.name = "pug" }

위 인라인 테이블 정의는 아래의 테이블 정의와 동일합니다.

[name]
first = "Tom"
last = "Preston-Werner"

[point]
x = 1
y = 2

[animal]
type.name = "pug"

인라인 테이블은 그 자체로 완전하며, 모든 키와 하위 테이블을 안에 정의해야 합니다. 중괄호 밖에서 키나 하위 테이블을 추가할 수는 없습니다.

[product]
type = { name = "Nail" }
# type.edible = false  # 유효하지 않음

비슷하게, 인라인 테이블을 이용해 이미 정의된 테이블에 키나 하위 테이블을 추가할 수 없습니다.

[product]
type.name = "Nail"
# type = { edible = false }  # 유효하지 않음

테이블의 배열

마지막 구문을 이용해 테이블의 배열을 정의할 수 있습니다. 이는 이름이 대괄호 2개로 둘러싸인 헤더를 이용해 표현할 수 있습니다. 첫 헤더는 배열과 그 배열의 첫 테이블 값을 정의하고, 뒤에 따라오는 헤더는 같은 배열의 새 값을 정의합니다. 테이블은 나타나는 순서대로 배열에 삽입됩니다.

[[products]]
name = "Hammer"
sku = 738594937

[[products]]  # 배열 안의 빈 테이블

[[products]]
name = "Nail"
sku = 284758393

color = "gray"

이는 다음 JSON과 같은 구조입니다.

{
  "products": [
    { "name": "Hammer", "sku": 738594937 },
    { },
    { "name": "Nail", "sku": 284758393, "color": "gray" }
  ]
}

테이블의 배열의 이름을 사용해 그 배열의 가장 최근에 정의된 값을 참조할 수 있습니다. 이를 이용해 가장 최근에 정의된 테이블 안에 하위 테이블, 또는 테이블의 하위 배열을 정의할 수 있습니다.

[[fruits]]
name = "apple"

[fruits.physical]  # 하위 테이블
color = "red"
shape = "round"

[[fruits.varieties]]  # 중첩된 테이블의 배열
name = "red delicious"

[[fruits.varieties]]
name = "granny smith"


[[fruits]]
name = "banana"

[[fruits.varieties]]
name = "plantain"

위 TOML은 다음 JSON과 같습니다.

{
  "fruits": [
    {
      "name": "apple",
      "physical": {
        "color": "red",
        "shape": "round"
      },
      "varieties": [
        { "name": "red delicious" },
        { "name": "granny smith" }
      ]
    },
    {
      "name": "banana",
      "varieties": [
        { "name": "plantain" }
      ]
    }
  ]
}

테이블이나 테이블의 배열의 상위 요소가 배열이라면, 그 배열은 하위 요소가 정의되기 전에 먼저 정의되어 있어야 합니다. 이 순서를 거꾸로 하려고 하는 경우, 파싱 시 에러가 발생해야 합니다.

# 유효하지 않은 TOML 문서
[fruit.physical]  # 서브 테이블, 하지만 상위 요소는?
color = "red"
shape = "round"

[[fruit]]  # 파서는 "fruit"이 테이블이 아닌 배열이라는 것을 확인한 시점에
           # 에러를 발생시켜야 함
name = "apple"

정적으로 정의된 배열에 값을 추가하려고 하는 것이 발견되면, 파싱 시에 에러가 발생해야 합니다.

# 유효하지 않은 TOML 문서
fruits = []

[[fruits]] # 허용되지 않음

이미 정의된 배열과 같은 이름의 테이블을 정의하려고 하는 경우 파싱 시에 에러가 발생해야 합니다. 동일하게, 테이블을 배열로 재정의하고자 하는 경우에도 파싱 시 에러가 발생해야 합니다.

# 유효하지 않은 TOML 문서
[[fruits]]
name = "apple"

[[fruits.varieties]]
name = "red delicious"

# 유효하지 않음: 이 테이블은 직전의 테이블의 배열과 충돌함
[fruits.varieties]
name = "granny smith"

[fruits.physical]
color = "red"
shape = "round"

# 유효하지 않음: 이 테이블의 배열은 직전의 테이블과 충돌함
[[fruits.physical]]
color = "green"

인라인 테이블을 적절히 사용할 수도 있습니다.

points = [ { x = 1, y = 2, z = 3 },
           { x = 7, y = 8, z = 9 },
           { x = 2, y = 4, z = 8 } ]

파일 확장자

TOML 파일의 확장자는 .toml이어야 합니다.

MIME 타입

TOML 파일을 인터넷을 통해 전송하는 경우, 적절한 MIME 타입은 application/toml입니다.

ABNF 문법

TOML의 구문에 대한 엄밀한 정의는 다른 ABNF 파일에 나타나 있습니다.