Parser beginner needs help

Hello OCamliens,

I’m trying to learn how to make a parser based on ocamllex and menhir.
The files on which I’m currently working on can be downloaded here :
(guarantee without virus)

running « menhir config_parser_mini.mly » return an error, about my start symbol only being able to generate the {epsilon} language (the blank, empty string).

I’m sure a seasoned menhir or ocamlyacc user will spot whats wrong with my code in 30 seconds… Myself awaiting for your answer! :slight_smile:

PS: the file preamp.cfg is the example of the syntax I must become able to parse.

Many thanks for any help

For me it also says Warning: the token EOF is unused., if I put EOF at the end of both rules for config it compiles. ie

| EOF                          { [] }
| setting_list EOF              { List.rev $1 }

Note however that setting_list can never be inhabited because it’s missing the empty case (or the only-1-setting case if you want nonempty lists). So maybe what you want is more like

| setting_list EOF              { List.rev $1 }
| { [] }
| setting_list setting      { $2 :: $1 }

(you get a shift/reduce conflict because {} can parse to the empty list in 2 ways, remove the first rule for group to remove the conflict)

Finally I don’t know why you parse lists inverted, you can just do

| { [] }
| setting setting_list      { $1 :: $2 }

and remove the List.rev uses.

Hi. Not a regular menhir user, but I think the reverted list parsing allows complexity not to be quadratic. Indeed, in the setting_list setting solution, we already have a list, and we are recognising an additional token, so we put it at the front of the list. At the end, we need to reverse the final list, but it seems to be “linear”, whereas in the second option — setting setting_list — it looks like in order to process the setting token, we need to first make sure the end of the expression is a setting_list, so we need to process the N-1 elements before adding this one to the list.

As an analogy (below), map2 does not make the stack grow, whereas map1 fails with a huge list as input. I don’t know if it applies to parsers, but I think I might have read something talking about this in Real World OCaml…

let rec map1 f = function
  | [] -> []
  | x :: xs -> f x :: map1 f xs

let map2 f l =
  let rec build acc = function
    | [] -> List.rev acc
    | x :: xs -> build (f x :: acc) xs
  in build [] l

EDIT : at this page they explain right-recursive rules are inefficient.

Thank you very much SkySkimmer for your help, I owe you a virtual beer and more :slight_smile:


cloudy hug is right about the rev list BTW.

1 Like