Chapter 6 The Objective Caml language
6.1 Lexical conventions
Blanks
空白、改行、水平タブ、キャリッジリターン、ラインフィード、フォームフィードはブランクと見なされます。ブランクは基本的に無視されますが、識別子、リテラル、キーワードを区切るために使われます (間にブランクがないと複数の識別子が 1 つの識別子と見なされてしまうので) 。
Comments
コメントは (* で始まり *) で終わります。(* や *) の間にブランクを挟んではいけません。コメントはブランクとして扱われます。文字列や文字リテラルの中にコメントは入れられません。コメントは入れ子にすることも可能です。
Identifiers
ident ::= (letter| _) { letter| 0...9| _| ' } letter ::= A ... Z | a ... z
識別子は英文字、数字、_ (アンダースコア) 、' (シングルクォート) の列です。ただし最初の文字は英文字かアンダースコアしか使えません。英文字は最低でも ASCII 集合から大文字と小文字をあわせた 52 文字が使えます。現在の実装では (MacOS 以外では) ISO 8859-1 (ISO Latin 1) 文字集合のアクセント付き文字も英文字として認識します。識別子の文字はすべて意味を持ち、現在の実装では識別子の文字数に制限はありません。
Integer literals
integer-literal ::= [-] { 0...9 }+
| [-] (0x| 0X) { 0...9| A...F| a...f }+ | [-] (0o| 0O) { 0...7 }+ | [-] (0b| 0B) { 0...1 }+
整数リテラルは数字の 1 つ以上の列です。先頭にマイナス符号をつけることがあります。デフォルトでは整数リテラルは 10 進数ですが、以下の接頭辞を付けることで別の基数を指定できます。 接頭辞 基数 0x, 0X 16 進数。 0o, 0O 8 進数。 0b, 0B 2 進数。
(先頭の 0 は数字のゼロで、8 進数の O は英文字の O です。) 整数が表せる範囲を外れた整数リテラルをどのように解釈するかは未定義です。
Floating-point literals
float-literal ::= [-] { 0...9 }+ [. { 0...9 }] [(e| E) [+| -] { 0...9 }+]
浮動小数点小数は整数部、小数部、指数部の 3 つに分かれます。整数部は数字の 1 つ以上の列 (マイナス符号がつく場合もあり) 、小数部は小数点より後に続く数字の 0 個以上の列です。指数部はまず e か E かの文字があり、その後に + か - かがオプションで、最後に数字が 1 つ以上続きます。小数部や指数部は省略可能ですが、整数リテラルと区別がつかないものは許されません。浮動小数点小数が表せる範囲を外れた浮動小数点小数リテラルをどのように解釈するかは未定義です。
Character literals
char-literal ::= ' regular-char '
| ' escape-sequence '
escape-sequence ::= \ (\ | " | ' | n | t | b | r)
| \ (0...9) (0...9) (0...9)
文字リテラルは ' (シングルクォート) 文字で区切られます。2 つのシングルクォートに囲まれた文字は ' か \ 以外か、以下のエスケープ文字列のどれかになります。 エスケープ文字列 表される文字 \\ バックスラッシュ (\) \" ダブルクォート (") \' シングルクォート (') \n ラインフィード (LF) \r キャリッジリターン (CR) \t 水平タブ (TAB) \b バックスペース (BS) \ddd ASCII code ddd (10 進数) で表される文字
String literals
string-literal ::= " { string-character } " string-character ::= regular-char-str
| escape-sequence
文字列リテラルは " (ダブルクォート) で区切られます。2 つのダブルクォートに囲まれた文字は ' か \ 以外か、上の表にあるエスケープ文字列のどれかになります。
複数行にまたがるような長い文字列リテラルを書けるよう、\newline blanks (行末に \ 、次の行頭に任意数のブランク) という列は文字列リテラルの中では無視されます。
現在の実装では、事実上文字列リテラルの長さに制限はありません。
Naming labels
名前付きラベルは ~ 、ident 、: の 3 つのトークン列と文法定義すると、曖昧性が生じるため、字句解析レベルで定義されています。 label ::= ~ (a ... z) { letter| 0...9| _| ' } : optlabel ::= ? (a ... z) { letter| 0...9| _| ' } :
名前付きラベルには、label という通常の引数と、optlabel というオプション引数の 2 種類があります。これは単純に最初の文字が ~ であるか ? であるかで区別されます。
Prefix and infix symbols
infix-symbol ::= (= | < | > | @ | ^ | | | & | + | - | * | / | $ | %) { operator-char }
prefix-symbol ::= (! | ? | ~) { operator-char }
operator-char ::= ! | $ | % | & | * | + | - | . | / | : | < | = | > | ? | @ | ^ | | |
=> や !! のような演算子文字の列は infix-symbol や prefix-symbol クラスの 1 つのトークンとみなされます。これらのシンボルは式中の前置演算子や中置演算子としてパースされますが、一方で演算子のようにも振る舞います。
Keywords
以下の識別子はキーワードとして予約されているため、その他の用途には利用できません。
and as assert asr begin class closed constraint do done downto else end exception external false for fun function functor if in include inherit land lazy let lor lsl lsr lxor match method mod module mutable new of open or parser private rec sig struct then to true try type val virtual when while with
以下の文字もキーワードです。
# & ' ( ) * , -> ? ?? . .. .( .[ : :: := ; ;; <- = [ [| [< {< ] |] >] >} _ ` { | } ~
Ambiguities
字句解析の曖昧性は「最大マッチング」規則に従って解決されます。例えばある文字列を 2 つのトークンに分ける方法が複数ある場合、1 つ目のトークンが長くなる分け方が採用されます。
Line number directives
linenum-directive ::= # {0 ... 9}+
| # {0 ... 9}+ " { string-character } "
Caml のソースコードのプリプロセッサで出力に行番号指示語を加えるようにすると、エラーメッセージ中の行番号とソースファイル名をプリプロセス前のものにすることが出来ます。行番号指示語は # (シャープ) で始まり、整数 (行番号) 、その後にオプションとして文字列 (ソースファイル名) で構成されます。行番号指示語は字句解析中ではブランクとして扱われます。