6.1 字句

6.1.1. ブランク
6.1.2. コメント
6.1.3. 識別子
6.1.4. 整数リテラル
6.1.5. 浮動小数点数リテラル
6.1.6. 文字リテラル
6.1.7. 文字列リテラル
6.1.8. 名前ラベル
6.1.9. 前置演算子と中置演算子
6.1.10. 予約語
6.1.11. 曖昧性
6.1.12. 行番号指示子

6.1.1 ブランク

空白、改行、水平タブ、キャリッジリターン、ラインフィード、フォームフィードはブランクと見なされます。ブランクは基本的に無視されますが、識別子、リテラル、キーワードを区切るために使われます(間にブランクがないと複数の識別子が 1 つの識別子と見なされてしまいます)。

6.1.2 コメント

コメントは (* で始まり *) で終わります。 (* や *) の間にブランクを挟んではいけません。 コメントはブランクとして扱われます。 文字列や文字リテラルの中にコメントは入れられません。 コメントは入れ子にすることも可能です。

6.1.3 識別子

ident ::= ( letter | _ ) { letter | 0...9 | _ | ' }
letter ::= A...Z | a...z

識別子は英文字、数字、_(アンダースコア)、 '(シングルクォート)の列です。ただし最初の文字には英文字かアンダースコアしか使えません。英文字は少なくとも ASCII 文字集合の大文字と小文字をあわせた 52 文字が使えます。現在の実装では(MacOS 以外では) ISO 8859-1 (ISO Latin 1)文字集合のアクセント付き文字も英文字として認識します。識別子の文字はすべて意味を持ち、現在の実装では 16000000 文字までの識別子を受け付けます。

6.1.4 整数リテラル

integer-literal ::= [-] { 0...9 }+
| [-] (0x | 0X) { 0...9 | A...F | a...f }+
| [-] (0o | 0O) { 0...7 }+
| [-] (0b | 0X) { 0...1 }+

整数リテラルは 1 つ以上の数字の列です。先頭にマイナス符号をつけることもできます。デフォルトでは整数リテラルは 10 進数ですが、以下の接頭辞を付けることで別の基数を指定することもできます。

接頭辞基数
0x, 0X16 進数
0o, 0O8 進数
0b, 0B2 進数

(先頭の 0 は数字のゼロで、8 進数の O は英文字の O です)整数で表せる範囲を外れた整数リテラルをどのように解釈するかは未定義です。

読み易さと便利のために、整数リテラルにはアンダースコア文字(_)を入れることができます(単純に無視されます)。

6.1.5 浮動小数点数リテラル

float-literal ::= [ - ] ( 0...9 ) { 0...9 | _ } [ . { 0...9 | _ } ] [ ( e | E ) [ + | - ] ( 0...9 ) { 0...9 | _ } ]

浮動小数点数は整数部、小数部、指数部の 3 つに分かれます。整数部は 1 つ以上の数字の列でマイナス符号がつけることもできます。小数部は小数点に 0 個以上の数値を続けたものです。指数部はまず文字 eE があり、その後に省略可能な +- が続き、最後に数字が 1 つ以上続きます。小数部や指数部は省略可能ですが、整数リテラルと区別がつかないものは許されません。浮動小数点数が表せる範囲を外れた浮動小数点数リテラルをどのように解釈するかは未定義です。

6.1.6 文字リテラル

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)
\dddASCII コード ddd(10 進数)で表される文字
\xhhASCII コード hh(16 進数)で表される文字

6.1.7 文字列リテラル

string-literal ::= " { string-character } "
string-character ::= regular-char
| escape-sequence

文字列リテラルは " (ダブルクォート)で区切られます。 2 つのダブルクォートで、 "\ 以外の文字か、上の文字リテラルの条の表のエスケープシーケンスのいずれかを並べたものを囲みます。

複数行にまたがるような長い文字列リテラルを書けるよう、文字列リテラル中では \newline blanks (行末に \、それに続いて次の行頭に任意個のブランク)という並びは無視されます。

現在の実装では、実際上文字列リテラルの長さに制限はありません。

6.1.8 名前ラベル

名前付きラベルは ~ident: の 3 つのトークン列と文法を定義すると曖昧性が生じるため、字句解析レベルで定義されています。

label ::= ~ ( a...z ) { letter | 0...9 | _ | ' } :
optlabel ::= ? ( a...z ) { letter | 0...9 | _ | ' } :

名前付きラベルには、通常の引数用の label と、省略可能引数用の optlabel の 2 種類があります。これは単純に最初の文字が ~ であるか ? であるかで区別されます。

6.1.9 前置演算子と中置演算子

infix-symbol ::= ( = | < | > | @ | ^ | | | & | + | - | * | / | $ | % ) { operator-char }
prefix-symbol ::= ( ! | ? | ~ ) { operator-char }
operator-char ::= ! | $ | % | & | * | + | - | . | / | | < | = | > | ? | @ | ^ | | | ~

<=>!! のような演算子文字の列は infix-symbolprefix-symbol クラスの 1 つのトークンとみなされます。これらのシンボルは式中では前置演算子や中置演算子として構文解析されますが、一方で識別子のようにも振る舞います。

6.1.10 予約語

以下の識別子はキーワードとして予約されているため、その他の用途には利用できません。

      and         as          assert      asr         begin       class
      constraint  do          done        downto      else        end
      exception   external    false       for         fun         function
      functor     if          in          include     inherit     initializer
      land        lazy        let         lor         lsl         lsr
      lxor        match       method      mod         module      mutable
      new         object      of          open        or          private
      rec         sig         struct      then        to          true
      try         type        val         virtual     when        while
      with        
    

以下の文字の並びもキーワードです。

    !=    #     &     &&    '     (     )     *     +     ,     -
    -.    ->    .     ..    :     ::    :=    :>    ;     ;;    <
    <-    =     >     >]    >}    ?     ??    [     [<    [>    [|
    ]     _     `     {     {<    |     |]    }     ~
    

また、次の識別子は Camlp4 拡張の予約語であり、互換性の理由から避けるべきであることにも注意してください。

    parser    <<    <:    >>    $     $$    $:
    

6.1.11 曖昧性

字句解析の曖昧性は「最長マッチング」規則に従って解決されます。例えばある文字列を 2 つのトークンに分ける方法が複数ある場合、1 つ目のトークンが最長になる分け方が採用されます。

6.1.12 行番号指示子

linenum-directive ::= # { 0...9 }+
| # { 0...9 }+ " { string-character } "

Caml のソースコードのプリプロセッサで出力に行番号指示語を加えるようにすると、エラーメッセージ中の行番号とソースファイル名を前処理前のものにすることが出来ます。行番号指示子は # (シャープ)で始まり、整数(行番号)、それに続く省略可能な文字列(ソースファイル名)で構成されます。行番号指示子は字句解析中ではブランクとして扱われます。