# Ocamllex and menhir examples that aren't calculators

**URL:** https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843
**Category:** Learning
**Tags:** menhir, ocamllex, ocamlyacc
**Created:** [November 18, 2021, 11:54am UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843 "2021-11-18T11:54:26Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![SeedyROM](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/seedyrom/32/3307_2.png) [@SeedyROM](https://discuss.ocaml.org/u/SeedyROM)
#### Post date: [November 18, 2021, 11:54am UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/1 "2021-11-18T11:54:26Z")

</div>

**Preface:**

I’m currently trying to parse a very simple document format using the above tools (and probably more than one document at a time), however all the examples I seem to find are for a calculator directly evaluating expressions. Feel like all my posts on this forum involve the words “maybe I’m a complete idiot” but

**Example:**

So let’s simplify my problem even more, let’s say I want parse a list of double quoted strings separated by `','`.

How would I define this grammar, do I need ocamllex? Can I do this entirely inline (as the docs vaguely hint at, and a few nearly decade old posts)? Can somebody give me a simple example?

**More Questions:**

- What is the recommended way to use ocamllex and menhir (ocamlyacc) together (not as a calculator lol)?
  - With dune especially!

- What am I missing?
- And where can I get more guidance or examples to read through.

_ **Thanks ya’ll!** _

---

<div class="post-metadata">

### Author: ![EmileTrotignon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emiletrotignon/32/5913_2.png) [@EmileTrotignon](https://discuss.ocaml.org/u/EmileTrotignon)
#### Post date: [November 18, 2021, 12:34pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/2 "2021-11-18T12:34:03Z")

</div>

I believe that you only need ocamllex for such a simple grammar, however you can use menhir  
Your menhir file would like that

```auto
%{ 
(* ocaml code here *)
%}
%token <string> STRING
%token COMMA 
%token EOF
%start <string list> main
%%
main:
    separated_list(STRING, COMMA) EOF { $1 }

```

And the lexer something like that :

```auto
{
open Parser
open LexerHelper
}

let atom_code = ('\\' digit (digit ?) (digit ?)) | ("\\0x" hexdigit (hexdigit ?))
let string_printable = [' ' - '!' '#' - '~']
let string_atom = string_printable | atom_code | "\\t" | "\\r" | "\\b" | "\\n" | "\\\"" | "\\\\"
let whitespace = [' ' '\n' '\t' '\r']*

rule string accumulator = parse
 | "\"" { STRING(
            String.of_seq
              (List.to_seq
                 (List.map (char_of_atom lexbuf)
                 (List.rev accumulator)))) }
 | string_atom { string ((Lexing.lexeme lexbuf) :: accumulator) lexbuf }
 | eof { error "during lexing" (Position.cpos lexbuf) "Unterminated string." }

and token = parse
  | whitespace { token lexbuf }
  | "," { COMMA }
  | "\"" { string [] lexbuf } 
  | eof { EOF } 

```

And a lexerHelper.ml file with the following code :

```ocaml
let char_of_atom lexbuf atom =
  match atom with
  | {|\n|} -> '\n'
  | {|\t|} -> '\t'
  | {|\b|} -> '\b'
  | {|\r|} -> '\r'
  | {|\\|} -> '\\'
  | {|\'|} -> '\''
  | {|\"|} -> '"'
  | _ when String.length atom = 1 -> atom.[0]
  | _ when atom.[0] = {|\|}.[0] -> (
      try Char.chr (int_of_string (String.sub atom 1 (String.length atom - 1)))
      with Invalid_argument _ ->
        error "during lexing" (Position.cpos lexbuf) "" )
  | _ -> failwith "Should never happen"

```

Note that I did not test any of this, I just pieced it together from old code of mine. For dune rules, and general organisation, you can look at this small DSL of mine : [chat\_botte/src/rolelang at master · EmileTrotignon/chat\_botte · GitHub](https://github.com/EmileTrotignon/chat_botte/tree/master/src/rolelang).

---

<div class="post-metadata">

### Author: ![SeedyROM](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/seedyrom/32/3307_2.png) [@SeedyROM](https://discuss.ocaml.org/u/SeedyROM)
#### Post date: [November 18, 2021, 12:39pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/3 "2021-11-18T12:39:10Z")

</div>

@EmileTrotignon

Gonna read through this in more detail later, as I’m on PST time right now where I am and it’s getting hyper late.

**Thanks for the example!**

---

<div class="post-metadata">

### Author: ![Gopiandcode](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/gopiandcode/32/5346_2.png) [@Gopiandcode](https://discuss.ocaml.org/u/Gopiandcode)
#### Post date: [November 18, 2021, 12:46pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/4 "2021-11-18T12:46:17Z")

</div>

I have an example of using Menhir+OCamllex for a custom dsl here: [parser · master · Kiran Gopinathan / GSDL - Gop-Scene Definition Language · GitLab](https://gitlab.com/gopiandcode/gsdl/-/tree/master/parser)

Relevant files are probably `lexer.mll`, `parser.mly` and `dune`.

Although more recently I’ve started using sedlex instead of ocamllex for my lexers because sedlex allows me to use normal OCaml syntax (and hence + merlin + gopcaml-mode for editing).

For other examples of Menhir parsers, the OCaml parser is also written in menhir and might be worth checking out as well.

---

<div class="post-metadata">

### Author: ![EmileTrotignon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emiletrotignon/32/5913_2.png) [@EmileTrotignon](https://discuss.ocaml.org/u/EmileTrotignon)
#### Post date: [November 18, 2021, 12:51pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/5 "2021-11-18T12:51:13Z")

</div>

Sedlex is a little complicated to plug into menhir because it does not use the same lexbuf type as ocamllex. Its a lot nicer to use though.

---

<div class="post-metadata">

### Author: ![Gopiandcode](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/gopiandcode/32/5346_2.png) [@Gopiandcode](https://discuss.ocaml.org/u/Gopiandcode)
#### Post date: [November 18, 2021, 12:56pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/6 "2021-11-18T12:56:20Z")

</div>

Yeah, good point - it does require a bit more boilerplate, although not too much nowadays.

This was all the extra code I needed to glue between the two interfaces for a recent project:

```auto
exception Error

let revised_parse lexbuf =
  let tok () =
    let tok = Lexer.token lexbuf in
    let (st,ed) = Sedlexing.lexing_positions lexbuf in
    (tok,st,ed) in
  MenhirLib.Convert.Simplified.traditional2revised
    Raw_parser.program
    tok

let parse lexbuf =
  try
    revised_parse lexbuf
  with Raw_parser.Error -> raise Error

let parse_string str =
  parse (Sedlexing.Utf8.from_string str)

```

edit: fixed locations

---

<div class="post-metadata">

### Author: ![EmileTrotignon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emiletrotignon/32/5913_2.png) [@EmileTrotignon](https://discuss.ocaml.org/u/EmileTrotignon)
#### Post date: [November 18, 2021, 1:55pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/7 "2021-11-18T13:55:04Z")

</div>

This forces you to use the table backend though ? This backend is quite slower (does not make a difference for most uses). I believe there should be a way to provide an “abstract” buffer to menhir, that is a function of type `unit -> token` and two of type `unit -> position`. But its not available yet.

---

<div class="post-metadata">

### Author: ![pmonson711](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/pmonson711/32/1691_2.png) [@pmonson711](https://discuss.ocaml.org/u/pmonson711)
#### Post date: [November 18, 2021, 5:05pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/8 "2021-11-18T17:05:59Z")

</div>

I’ve found this to be a well written set of articles and reasonably complete example language.

> **[Writing a Lexer and Parser using OCamllex and Menhir](https://mukulrathi.com/create-your-own-programming-language/parsing-ocamllex-menhir/)**
>
> The first stage of a compiler is to represent our Bolt program in a structured format. In this post, I explain how lexing and parsing work, and how we use OCamllex and Menhir to generate the lexer and parser for Bolt. I'll also cover how to fix cases...

---

<div class="post-metadata">

### Author: ![vrotaru](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/vrotaru/32/39_2.png) [@vrotaru](https://discuss.ocaml.org/u/vrotaru)
#### Post date: [November 19, 2021, 9:06am UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/9 "2021-11-19T09:06:11Z")

</div>

The is the PL Zoo where you can find many such examples.

> **[GitHub - andrejbauer/plzoo: Programming Languages Zoo](https://github.com/andrejbauer/plzoo)**
>
> Programming Languages Zoo. Contribute to andrejbauer/plzoo development by creating an account on GitHub.

---

<div class="post-metadata">

### Author: ![roddy](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/roddy/32/2261_2.png) [@roddy](https://discuss.ocaml.org/u/roddy)
#### Post date: [November 20, 2021, 12:41pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/10 "2021-11-20T12:41:20Z")

</div>

Real World OCaml has an [example](https://dev.realworldocaml.org/parsing-with-ocamllex-and-menhir.html) of JSON parsing.

---

<div class="post-metadata">

### Author: ![smolkaj](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/smolkaj/32/266_2.png) [@smolkaj](https://discuss.ocaml.org/u/smolkaj)
#### Post date: [November 20, 2021, 6:28pm UTC](https://discuss.ocaml.org/t/ocamllex-and-menhir-examples-that-arent-calculators/8843/11 "2021-11-20T18:28:24Z")

</div>

[nice-parser](https://github.com/smolkaj/nice-parser) has an [example](https://github.com/smolkaj/nice-parser/tree/master/example) of how to parse S-expressions. It’s a tiny library that encapsulates all the typical boilerplate code, so you can just focus on lexing and parsing.
