10655


OCamlでUnicodeを扱うパーサを作る為にulexを使う事を考えています。  
例えば、以下のような四則演算のパーサがあります。

parser.mly

[code]

    %{
    %}
    
    %token <int> INT
    %token ADD SUB MUL DIV EOF
    %left ADD SUB
    %left MUL DIV
    %type <int> exp
    %start exp
    
    %%
    
    exp:
    | INT         { $1 }
    | exp ADD exp { $1 + $3 }
    | exp SUB exp { $1 - $3 }
    | exp MUL exp { $1 * $3 }
    | exp DIV exp { $1 / $3 }
    
[/code]

lexer.mll

[code]

    {
    open Parser
    }
    
    rule token = parse
    | [' ' '\t' '\n' '\r']+ { token lexbuf }
    | ['0'-'9']+ { INT(int_of_string (Lexing.lexeme lexbuf)) }
    | '-' { SUB }
    | '+' { ADD }
    | '*' { MUL }
    | eof { EOF }
    | _ { assert false }
    
[/code]

main.ml

[code]

    let _ =
      let lexbuf = Lexing.from_string "1+2*3" in
      let result = Parser.exp Lexer.token lexbuf in
      Printf.printf "%d\n" result
    
[/code]

Makefile

[code]

    main: parser.ml lexer.ml main.ml
        ocamlfind ocamlc -package ulex parser.mli parser.ml lexer.ml main.ml -o main
    parser.ml: parser.mly
        ocamlyacc parser.mly
    lexer.ml: lexer.mll
        ocamllex lexer.mll
    clean:
        rm -rf *.cm* parser.ml lexer.ml main *.o
    
[/code]

opamのリポジトリを検索したところ

./4.02.1/lib/ulex/ulexing.mli  
./4.02.1/lib/ulex/utf8.mli

の２つが参考になりそうでした。

> They need not work on a type named [lexbuf]: you can use the type  
>  name you want. Then, just do in your ulex-processed source, before  
>  the first lexer specification:
>
> [module Ulexing = L]
>
> Of course, you'll probably want to define functions like [lexeme]  
>  to be used in the lexers semantic actions.

と書いてあるのでlexer.mllに`module Ulexing = L`と書くと良いようなので、、、。

lexer.mllを以下のように書き換えればコンパイルは通りました。

[code]

    {
    open Parser
    module Ulexing = Lexing
    }
    
    rule token = parse
    | [' ' '\t' '\n' '\r']+ { token lexbuf }
    | ['0'-'9']+ { INT(int_of_string (Ulexing.lexeme lexbuf)) }
    | '-' { SUB }
    | '+' { ADD }
    | '*' { MUL }
    | eof { EOF }
    | _ { assert false }
    
[/code]

しかし、これでは単に名前を書き換えているだけに思えますし、LというLexerはありません。  
このような使い方で良いのか良くわからないのと、やりたい事としては、ocamllex上でutf-8を扱えるようにしたいのですが、ulexのありがたみが良くわかりません。

<https://twitter.com/takeisa/status/503531375127838720>

Webで調べたところ上記のような事が書いてありました。

このあと自分で調べるとなると、mliの内容を翻訳してみればよいと思うのですが、分かりやすいサンプルなどがあれば教えてください。


CC BY-SA 3.0
2015-05-25T07:32:25.640
10585
2015-05-27T11:36:15.800
2015-05-27T01:47:03.630
7532
7532
question
ocaml
OCamlのulexの使い方を教えてください


Ulex は ocamllex 使った字句解析手法ではありません。質問の例では lexer.mll を ocamllex で処理しているので ulex
を全く使っていません。

Ulex は .ml に直接字句解析ルールを書くためのライブラリです。 ocamllex や他の字句解析ツールに存在するルール記述のためのDSLは ulex
では pa_ulex.cma という CamlP4 文法拡張として提供されています:

[code]

    lexer
        R1 -> e1
      | R2 -> e2
        ...
      | Rn -> en
    
[/code]

これは ocamllex での

[code]

    parse
      | R1 { e1 }
      | R2 { e2 }
        ...
      | Rn { en }
    
[/code]

に相当するものですが、 `lexer R1 -> e1 | .. | Rn -> en` は pa_ulex.cma によって普通の OCaml
の式に展開されるので、普通に `let` で束縛する事ができます。Ulex での

[code]

    let rule1 = lexer R1 -> e1 | ... | Rn -> en
    
[/code]

は ocamllex での

[code]

    rule rule1 = parse R1 { e1 } | ... | Rn { en } 
    
[/code]

に大体一致します。

概要は以上です。詳しくは README および Ulex を使っている例をビルドしてみて、 pa_ulex.cma が実際にどうこの拡張文法を含む .ml
ファイルのプリプロセスに使われているかを確認してください。


CC BY-SA 3.0
2015-05-27T03:14:44.683
10655
2015-05-27T11:36:15.800
2015-05-27T11:36:15.800
898
898
10585
answer