Open2

OCaml で 構文解析/字句解析

OnimenOnimen

環境構築とか

  • OCaml version 5.3.0
  • Libraries
    • menhir 20240715
  • dune 3.18.0

使用するライブラリをインストール

opam install menhir dune

dune でプロジェクトを作成

dune init project <project_name>

lib フォルダ内に以下のファイルを作成

parser.mly
lexer.mll

lib/dune に以下を追記.ライブラリ名なども決めてあげるとよい

(ocamllex lexer)

(menhir
    (modules parser))
OnimenOnimen

Ocamllex の扱いを学ぶ

https://qiita.com/takl/items/94cd68b9ede086a08380

  • lexer.mll の中に規則を書いていく.(lexなどと似ている感じ)
  • lexer.mllの中身はヘッダ,規則部,トレイラーに分かれる

トークン列に分解してみる

スペース or 改行を区切り文字として文字列を分解するだけのシンプルなトークナイザを作ってみる

syntax.ml
type program = 
| Eof
| Text of string


let print_program p =
  match p with
  | Eof -> print_newline ()
  | Text (text) -> print_string text; print_newline ()
lexer.mll
let whitespace = [' ' '\n' '\r']

rule main = parse
  (* ignore spacing and newline characters *)
    whitespace+ { main lexbuf }
  | ['a'-'z' '0'-'9' '_' '\'']* as lexeme { Parser.Text lexeme }
  | eof { Parser.Eof }
  | _ { Parser.Eof }
parser.mly
%{
open Syntax
%}
%token Eof
%token <string> Text
%start <program> toplevel
%%

toplevel :
| Eof { Eof }
| Text { Text ($1) }
main.ml
let () = 
  let lexbuf = Lexing.from_channel stdin in
  try
    while true do
      let program = Lang01.Parser.toplevel Lang01.Lexer.main lexbuf in
      Lang01.Syntax.print_program program;
    done
  with _ ->
    exit 0;

いろんなサイトのサンプルコードを適当に弄っただけではあるが,改行や空白に分割することは一応できた.ちょっとずつ ocamllex を使った字句解析の流れも掴めた.

さて,ここまでやってみて気がついたのだが,ocamllex ではマルチバイト文字は扱えないらしい?日本語などのマルチバイト文字を扱いたければ sedlex という別のライブラリを使う必要があるらしい.

まあ,OCaml で字句解析をするとなれば ocamllex がチュートリアルみたいなもんだし...