# Can anyone reproduce this in menhir?

**URL:** https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627
**Category:** Learning
**Created:** [May 9, 2025, 12:32am UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627 "2025-05-09T00:32:28Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![HumamAlhusaini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/humamalhusaini/32/5957_2.png) [@HumamAlhusaini](https://discuss.ocaml.org/u/HumamAlhusaini)
#### Post date: [May 9, 2025, 12:32am UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/1 "2025-05-09T00:32:28Z")

</div>

If I want to parse parameters, something like this:  
`(Tralalero, Tralala, Crocodilo, Bombardilo)`

I’d make this menhir rule.

```auto
params:
 LPAREN separated_list(COMMA, identifier) RPAREN {}

```

This works!  
However, for whatever reason, I want the user to be obligated to add a comma at the end. Like this:  
`(Tralalero, Tralala, Crocodilo, Bombardilo,)`

The natural thing is to write something like

```auto
params:
 LPAREN separated_list(COMMA, identifier) COMMA RPAREN {}

```

However, this doesn’t work, for whatever reason.

So I attempted something like

```auto
parameters:
LPAREN params RPAREN {}

params:
identifier COMMA params
identifier COMMA

```

Yet this did not work either. Does anybody have an idea on how to do this?

---

<div class="post-metadata">

### Author: ![brandon](https://avatars.discourse-cdn.com/v4/letter/b/f08c70/32.png) [@brandon](https://discuss.ocaml.org/u/brandon)
#### Post date: [May 9, 2025, 12:52am UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/2 "2025-05-09T00:52:37Z")

</div>

I found this to work:

```auto
params:
  LPAREN nonempty_list(terminated(identifier, COMMA)) RPAREN {}

```

---

<div class="post-metadata">

### Author: ![HumamAlhusaini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/humamalhusaini/32/5957_2.png) [@HumamAlhusaini](https://discuss.ocaml.org/u/HumamAlhusaini)
#### Post date: [May 9, 2025, 2:09am UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/3 "2025-05-09T02:09:39Z")

</div>

Thanks. I love you 💓

---

<div class="post-metadata">

### Author: ![HumamAlhusaini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/humamalhusaini/32/5957_2.png) [@HumamAlhusaini](https://discuss.ocaml.org/u/HumamAlhusaini)
#### Post date: [May 9, 2025, 2:24pm UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/4 "2025-05-09T14:24:56Z")

</div>

What if I wanted to make it so that the end comma is optional? I attempted something like this

```auto
params:
  LPAREN nonempty_list(terminated(identifier, COMMA)) option(COMMA) RPAREN {}

```

but that gave me a shift reduce conflict

```auto
** In state 44, looking ahead at COMMA, reducing production
** separated_nonempty_list(COMMA,use_tree) -> use_tree
** is permitted because of the following sub-derivation:

simple_path_special LBRACE separated_nonempty_list(COMMA,use_tree) option(COMMA) RBRACE // lookahead token appears because option(COMMA) can begin with COMMA
                           use_tree . 

** In state 44, looking ahead at COMMA, shifting is permitted
** because of the following sub-derivation:

simple_path_special LBRACE separated_nonempty_list(COMMA,use_tree) option(COMMA) RBRACE 
                           use_tree . COMMA separated_nonempty_list(COMMA,use_tree)

```

use\_tree is interchangeable with param

---

<div class="post-metadata">

### Author: ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)
#### Post date: [May 9, 2025, 3:02pm UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/5 "2025-05-09T15:02:51Z")

</div>

> [@HumamAlhusaini](#):
>
> What if I wanted to make it so that the end comma is optional? I attempted something like this
> 
> ```auto
> params:
> LPAREN nonempty_list(terminated(identifier, COMMA)) option(COMMA) RPAREN {}
> 
> ```

The problem is that the parser cannot decide upon seeing the last `COMMA` if it is the comma following an identifier as part of the list or if it is the optional comma. You should try instead with

```auto
params:
  LPAREN separated_nonempty_list(COMMA, identifier) option(COMMA) RPAREN {}

```

Cheers,  
Nicolas

---

<div class="post-metadata">

### Author: ![grayswandyr](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/grayswandyr/32/94_2.png) [@grayswandyr](https://discuss.ocaml.org/u/grayswandyr)
#### Post date: [May 9, 2025, 3:12pm UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/6 "2025-05-09T15:12:11Z")

</div>

You might be interested in this [old post](https://gallium.inria.fr/blog/lr-lists/) by @fpottier.

---

<div class="post-metadata">

### Author: ![HumamAlhusaini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/humamalhusaini/32/5957_2.png) [@HumamAlhusaini](https://discuss.ocaml.org/u/HumamAlhusaini)
#### Post date: [May 9, 2025, 3:22pm UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/7 "2025-05-09T15:22:10Z")

</div>

This gives a shift/reduce error.

```auto
  LBRACE;
  trees = separated_nonempty_list(COMMA, use_tree);
  option(COMMA);
  RBRACE

```

```auto

** Conflict (shift/reduce) in state 44.
** Token involved: COMMA
** This state is reached from program after reading:

outer_attrs USE simple_path_special LBRACE use_tree

** The derivations that appear below have the following common factor:
** (The question mark symbol (?) represents the spot where the derivations begin to differ.)

program 
items EOF 
item items 
outer_attrs vis_item 
            use_declaration 
            USE use_tree SEMI 
                (?)

** In state 44, looking ahead at COMMA, reducing production
** separated_nonempty_list(COMMA,use_tree) -> use_tree
** is permitted because of the following sub-derivation:

simple_path_special LBRACE separated_nonempty_list(COMMA,use_tree) option(COMMA) RBRACE // lookahead token appears because option(COMMA) can begin with COMMA
                           use_tree . 

** In state 44, looking ahead at COMMA, shifting is permitted
** because of the following sub-derivation:

simple_path_special LBRACE separated_nonempty_list(COMMA,use_tree) option(COMMA) RBRACE 
                           use_tree . COMMA separated_nonempty_list(COMMA,use_tree)

```

@grayswandyr gave me the idea of using left recursion, so the first thing that I check is that there is a comma at the end.

```auto
use_trees:
  | use_tree_list option(COMMA) { $1 }

use_tree_list:
  | use_tree { [$1] }
  | use_tree_list COMMA use_tree { $3 :: $1 }

```

This worked!

---

<div class="post-metadata">

### Author: ![grayswandyr](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/grayswandyr/32/94_2.png) [@grayswandyr](https://discuss.ocaml.org/u/grayswandyr)
#### Post date: [May 9, 2025, 3:56pm UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/8 "2025-05-09T15:56:57Z")

</div>

Just keep in mind that with this technique, the computed list is in reverse order. Depending on your application, you may want to massage it through `List.rev`.

---

<div class="post-metadata">

### Author: ![HumamAlhusaini](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/humamalhusaini/32/5957_2.png) [@HumamAlhusaini](https://discuss.ocaml.org/u/HumamAlhusaini)
#### Post date: [May 9, 2025, 11:01pm UTC](https://discuss.ocaml.org/t/can-anyone-reproduce-this-in-menhir/16627/9 "2025-05-09T23:01:54Z")

</div>

Thanks for reminding me
