字句構文は、文字の並びがどのようにして語彙素の並びに分割され、コメントや空白のような重要でない部分がどのように省略されるのかを定める。文字の並びは Unicode 標準 [27] に従ったテキストであると仮定されている。字句構文のうち、識別子や数値オブジェクトの表現、文字列といったものはデータ構文の構文データであり、オブジェクトを表現している。構文の形式的説明を越えて、本節ではどのようなデータ値がこの構文データで表されるかについても述べる。
コメントの説明にもあったように、字句構文には <datum> への前方参照がある。 <datum> はデータ構文の一部として説明されている。ただし、コメントであるため、これら <datum> は構文では重要な役割をしない。
真偽値、数値オブジェクト、Unicode のスカラー値を指定する16進数を除き、大文字小文字は重要である。例えば、 #x1A と #x1a は等価であるが、識別子 Foo は識別子 FOO とは異なる。
<interlexeme space> は任意の語彙素のどちら側にも現れることがあるが、語彙素の中には現れない。
<identifier>、 .、 <number>、 <character>、 <boolean> は <delimiter> か入力の終端で終端されなければならない。
次の 2 文字は将来の言語の拡張のために予約されている: { }
<lexeme> → <identifier> | <boolean> | <number> | <character> | <string> | ( | ) | [ | ] | #( | #vu8( | ’ | ‘ | , | ,@ | . | #’ | #‘ | #, | #,@ <delimiter> → ( | ) | [ | ] | " | ; | # | <whitespace> <whitespace> → <character tabulation> | <linefeed> | <line tabulation> | <form feed> | <carriage return> | <next line> | <any character whose category is Zs, Zl, or Zp> <line ending> → <linefeed> | <carriage return> | <carriage return> <linefeed> | <next line> | <carriage return> <next line> | <line separator> <comment> → ; 〈all subsequent characters up to a <line ending> or <paragraph separator>〉 | <nested comment> | #; <interlexeme space> <datum> | #!r6rs <nested comment> → #| <comment text> <comment cont>* |# <comment text> → 〈character sequence not containing #| or |#〉 <comment cont> → <nested comment> <comment text> <atmosphere> → <whitespace> | <comment> <interlexeme space> → <atmosphere>* <identifier> → <initial> <subsequent>* | <peculiar identifier> <initial> → <constituent> | <special initial> | <inline hex escape> <letter> → a | b | c | ... | z | A | B | C | ... | Z <constituent> → <letter> | 〈any character whose Unicode scalar value is greater than 127, and whose category is Lu, Ll, Lt, Lm, Lo, Mn, Nl, No, Pd, Pc, Po, Sc, Sm, Sk, So, or Co〉 <special initial> → ! | $ | % | & | * | / | : | < | = | > | ? | ^ | _ | ~ <subsequent> → <initial> | <digit> | <any character whose category is Nd, Mc, or Me> | <special subsequent> <digit> → 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 <hex digit> → <digit> | a | A | b | B | c | C | d | D | e | E | f | F <special subsequent> → + | - | . | @ <inline hex escape> → \x<hex scalar value>; <hex scalar value> → <hex digit>+ <peculiar identifier> → + | - | ... | -> <subsequent>* <boolean> → #t | #T | #f | #F <character> → #\<any character> | #\<character name> | #\x<hex scalar value> <character name> → nul | alarm | backspace | tab | linefeed | newline | vtab | page | return | esc | space | delete <string> → " <string element>* " <string element> → <any character other than " or \> | \a | \b | \t | \n | \v | \f | \r | \" | \\ | \<intraline whitespace>*<line ending> <intraline whitespace>* | <inline hex escape> <intraline whitespace> → <character tabulation> | <any character whose category is Zs>
<hex scalar value> は 0 ~ #x10FFFF から [#xD800, #xDFFF] の範囲の Unicode スカラー値を除いたものである。
下の <num R>、 <complex R>、 <real R>、 <ureal 10>、 <uinteger R>、 <prefix R> についての規則は R = 2, 8, 10, 16 について複製される。 <decimal 2>、 <decimal 8>、 <decimal 16> という規則はない。これは小数点や指数部を含む数値表現は 10 を基数としなければならないことを意味する。
<number> → <num 2> | <num 8> | <num 10> | <num 16> <num R> → <prefix R> <complex R> <complex R> → <real R> | <real R> @ <real R> | <real R> + <ureal R> i | <real R> - <ureal R> i | <real R> + <naninf> i | <real R> - <naninf> i | <real R> + i | <real R> - i | + <ureal R> i | - <ureal R> i | + <naninf> i | - <naninf> i | + i | - i <real R> → <sign> <ureal R> | + <naninf> | - <naninf> <naninf> → nan.0 | inf.0 <ureal R> → <uinteger R> | <uinteger R> / <uinteger R> | <decimal R> <mantissa width> <decimal 10> → <uinteger 10> <suffix> | . <digit 10>+ <suffix> | <digit 10>+ . <digit 10>* <suffix> <uinteger R> → <digit R>+ <prefix R> → <radix R> <exactness> | <exactness> <radix R>
<suffix> → <empty> | <exponent marker> <sign> <digit 10>+ <exponent marker> → e | E | s | S | f | F | d | D | l | L <mantissa width> → <empty> | | <digit 10>+ <sign> → <empty> | + | - <exactness> → <empty> | #i| #I | #e| #E <radix 2> → #b| #B <radix 8> → #o| #O <radix 10> → <empty> | #d | #D <radix 16> → #x| #X <digit 2> → 0 | 1 <digit 8> → 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 <digit 10> → <digit> <digit 16> → <hex digit>
Scheme における行末は一行コメント(4.2.3 節参照)と文字列リテラル内で重要な意味をもつ。 Scheme のソースコード中では <line endings> が行の終端の印である。さらに、二文字の行末 <carriage return> <linefeed> と <carriage return> <next line> もそれぞれひとつの行末と見做される。
文字列リテラルでは \ の先行しない <line ending> は改行文字を表す。これは Scheme における標準的な行末文字である。
空白文字は、スペース、改行、復帰、タブ文字、改ページ、垂直タブ、その他、カテゴリが Zs、 Zl、 Zp の文字である。空白は読み易さを向上させるために必要に応じて語彙素を区切るのに使われる。空白は任意のふたつの語彙素の間には現れるが、語彙素の中には現れない。空白は文字列の中にも現れる。ここでは意味を持つ。
字句構文には様々なコメント形式が含まれている。どの場合も、コメントは Scheme には不可視で、区切り文字として振る舞う。そのため、例えば、コメントは識別子や数値オブジェクトの中間に現れることはできない。
セミコロン(;)は行コメントの始まりを示す。コメントはセミコロンの現れた行の最後まで続く。
コメントを表現する別の方法として <datum> (4.3.1 参照)の前に #; をつける方法がある。 <datum> の前には <interlexme space> をつけてもよい。コメントはコメント接頭辞 #; と <datum> の両方から成る。この記法はコードのまとまりを「コメントアウト」するのに便利である。
正しく入れ子になった #| と |# の対でブロックコメントを表現することもできる。
#| The FACT procedure computes the factorial of a non-negative integer. |# (define fact (lambda (n) ;; base case (if (= n 0) #;(= n 1) 1 ; identity of * (* n (fact (- n 1))))))
語彙素 #!r6rs は、それに続くプログラムテキストが本報告書で述べられている字句構文やデータ構文で描かれていることを示すが、これもまたそれ以外の意味ではコメントとして扱われる。
他のプログラミング言語で使うことのできる識別子のほとんどは Scheme でも使うことができる。一般に、文字の並び、数字、「拡張アルファベット文字」は数値オブジェクトの表現を始めることのできない場合は識別子である。これに加えて、 +、 -、 ... も、文字の並び、数字、 -> という 2 文字の並びで始まる拡張アルファベット文字列と同じく識別子である。ここに識別子の例をいくつか挙げる。
lambda q soup list->vector + V17a <= a34kTMNs ->- the-word-recursion-has-many-meanings
拡張アルファベット文字は、識別子中でそれが文字であるかのように使うことができる。次に挙げるのは拡張アルファベット文字である。
! $ % & * + - . / : < = > ? @ ^ _ ~
さらに、 Unicode スカラー値が 127 より大きい文字と、 Unicode カテゴリが Lu、 Ll、 Lt、 Lm、 Lo、 Mn、 Mc、 Me、 Nd、 Nl、 No、 Pd、 Pc、 Po、 Sc、 Sm、 Sk、 So、 Co のいずれかである文字も識別子の中で使うこともできる。さらに、 <inline hex escape> を経由して指定すれば任意の文字を識別子の中で使うこともできる。例えば、識別子 H\x65;llo は識別子 Hello と同一であり、識別子 \x3BB; は識別子 λ と同一である。
任意の識別子は Scheme プログラム中で変数や構文キーワードとして使うことができる(R6RS:翻訳:R6RS:5.2 Variables, keywords, and regions と R6RS:翻訳:R6RS:9.2 Macros 参照)。任意の識別子は構文データとして使うこともできる。この場合にはシンボルを表す(R6RS:翻訳:R6RS:11.10 Symbols 参照)。
真と偽に対する標準形な真偽値オブジェクトには #t と #f という外部表現がある。
文字は #\<character> や #\<character name>、 #\x<hex scalar value> といった記法を使って表現される。
例:
小文字の a
大文字のA
左括弧
空白文字
U+0000
U+0007
U+0008
U+0009
U+000A
U+000A
U+000B
U+000C
U+000D
U+001B
U+0020。空白を書くよりも好ましい。
U+007F
U+00FF
U+03BB
U+6587
U+03BB
&lexical exception
&lexical exception
&lexical exception
U+0007 に x の続いたもの
&lexical exception
&lexical exception
U+000A
U+00FF
U+00FF
U+0078 に別のデータ ff の続いたもの
U+0078 に別のデータ、括弧でくくられた ff の続いたもの
&lexical exception
&lexical exception
U+0028 に別のデータ、括弧でくくられた x の続いたもの
&lexical exception。範囲外
U+0001
&lexical exception。除外範囲
(&lexical exception という表記は問題の行が字句構文違反であることを意味している)
#\<character> や #\<character name> では大文字小文字は重要であるが、 #\x<hex scalar value> の <hex scalar value> 部分ではそうではない。 <character> には <delimiter> か入力の終端が続かなければならない。この規則により、名前つきの文字に関する様々な曖昧さを、例えば「#\space」という文字の並びが、「#\s」という文字に「pace」という識別子の続いたものでなく、空白文字として解釈されるよう要求する、というようにして解決している。
注: #\newline という表記は後方互換性のために残されている。これは廃止予定である。代わりに #\linefeed を使うべきである。
文字列は二重引用符(")で囲まれた文字の並びとして表現される。文字列リテラルの中では、それら自体以外を表現する様々なエスケープシーケンスが文字を表現する。エスケープシーケンスは常に逆スラッシュ(\)で始まる。
ベル、 U+0007
後退、 U+0008
タブ文字、 U+0009
改行、 U+000A
行タブ、 U+000B
書式送り、 U+000C
復帰、 U+000D
二重引用符 U+0022
逆スラッシュ U+005C
「無」
指定された文字 (末端のセミコロンに注意)
<hex scalar value> の英数字が大文字でも小文字でも構わないことを除けば、これらのエスケープシーケンスは大文字小文字を区別する。
これら以外のバックスラッシュのあとの文字は構文違反である。文字列リテラル中では、行末以外では、エスケープシーケンスの外側の文字と二重引用符以外だけがそれ自体を意味している。例えば 1 文字の文字列リテラル "λ" (二重引用符、小文字の λ、二重引用符)は "\x03bb;" と同じ文字列を表している。逆スラッシュに続かない行末は改行文字を意味する。
例:
U+0061, U+0062, U+0063
"Abc" ; U+0041, U+0062, U+0063
U+0041, U+0020, U+0062, U+0063
U+41BC
&lexical exception
&lexical exception
&lexical exception
"A" ; U+0041
U+10FFFF
&lexical exception。範囲外
U+0001
&lexical exception。除外範囲
U+0041, U+000A, U+0062, U+0063。A のあとに空白の現れない場合
数値オブジェクトの外部表現の構文は形式構文の <number> 規則で形式的に説明されている。数値オブジェクトの外部表現では大文字小文字は重要ではない。
数値オブジェクトの外部表現は基数接頭辞を使って二進、八進、十進、十六進で書くことができる。基数接頭辞には #b (二進)、 #o (八進)、 #d (十進)、 #x (十六進)がある。基数接頭辞のない場合には、数値オブジェクトは十進で表現されているものと仮定される。
数値オブジェクトの表現は接頭辞で正確か不正確か指定することもできる。接頭辞 #e は正確なもの、 #i は不正確なものである。正確性接頭辞は基数接頭辞の前にも後にも現れることができる。数値オブジェクトの表現に正確性接頭辞がない場合には、定数に小数点や指数部分、仮数部が含まれる場合には不正確になり、それ以外の場合は正確なものになる。
様々な精度の不正確数の系では、定数の精度が指定できると便利なことがある。この目的のために、数値オブジェクトの表現は不正確な表現に所望の精度を示す指数マーカーを書くことができる。 s、 f、 d、 l の文字がそれぞれ順に短精度、単精度、倍精度、長精度の使用を指定する(不正確な数の内部表現が 4 つより少ない場合、それらのうち可能なものに写像される。例えば、ふたつの内部表現のある実装系は短精度と単精度を、長精度と倍精度をいっしょにしてもかまわない)。さらに、指数マーカー e が実装系既定の精度を指定する。精度の既定値は少なくとも倍精度と同じ精度がなければならないが、実装系は利用者がこの既定値を設定できるようにしてもかまわない。
単精度に丸められ、おそらく 3.141593 になる
長精度に拡張され、おそらく .600000000000000 になる
空でない仮数幅を持つ数値オブジェクトの表現、 x|p は、 p-bit の仮数を使った x の二進浮動小数点の最良の近似を表す。例えば、 1.1|53 は 1.1 の IEEE 倍精度での最良の近似である。 x が縦棒を含まない不正確な実数オブジェクトの外部表現であった場合、その数値は 53 以上の仮数幅を持つように計算されなければならない。
実数オブジェクトの二進浮動小数点表現を用いる実装系は、現実的であれば x|p に p-bit の仮数部を使うか、 p-bit の仮数部が現実的でない場合にはより大きな精度を使うか、 p やより大きなの仮数部が実装系で現実的でない場合には利用可能な最も大きな精度を使って x|p を表現すべきである。
注: 仮数部の精度と仮数部を表現するのに使うビット数を混同すべきではない。 IEEE 浮動小数点標準では、例えば、仮数の最上位ビットは暗黙裏には単精度か倍精度であるが、明示的には拡張精度である。そのようなビットは暗黙裏であれ明示的であれ、数学的な精度には影響を与えない。二進浮動小数点を使う実装系では、既定の精度は次の手続きを呼び出しで計算することができる。
(define (precision) (do ((n 0 (+ n 1)) (x 1.0 (/ x 2.0))) ((= 1.0 (+ 1.0 x)) n)))
注: 下層の浮動小数点表現が IEEE 倍精度であった場合 |p 接頭辞は常に省略されるべきである。非正規化された浮動小数点数は精度が減少し、その外部表現は |p 接頭辞を実際の仮数部の幅で伝えるべきである。
リテラル +inf.0 と -inf.0 はそれぞれ正と負の無限大を表す。 +nan.0 は (/ 0.0 0.0)の結果の非数や、他の非数も同様に表すことがある。 -nan.0 リテラルも同様に非数を表す。
x が不正確な実数オブジェクトの外部表現であり、縦線を含まず、 e 以外の指数マーカーを持たない場合、その表現する不正確な実数オブジェクトは flonum である(R6RS:翻訳:Standard Libraries:11.3 Flonums 参照)。他の不正確な実数オブジェクトの外部表現もすべてないしはいくらかは flonum を表現することがあるが、本報告書はそれを求めない。