;; Build the stage2 version of Menhir. During this stage, Menhir's parser
;; is generated by the stage1 Menhir executable.

;; -----------------------------------------------------------------------------

;; The flags that are passed to every invocation of Menhir in the rules below
;; are set in the file "menhir_flags". Any flags that affect the construction
;; of the automaton, such as --canonical, *must* be listed there.

;; We need these flags in "s-expression" format in order to use them in the
;; "menhir" stanza below. The following rule generates a file in this format
;; by wrapping the list of arguments in parentheses.

(rule
  (with-stdout-to menhir_flags.sexp
    (progn
      (echo "(")
      (cat %{dep:menhir_flags})
      (echo ")")
    )
  )
)

;; -----------------------------------------------------------------------------

;; Bind the name "menhir" to "../stage1/main.exe" within the present scope.
;; This is so that the "menhir" stanza below will use *that* executable
;; instead of whatever "menhir" executable (if any) is available on the
;; developer's machine.

(env
  (_ (binaries ../stage1/main.exe (../stage1/main.exe as menhir)))
)

;; Menhir's parser is generated by Menhir.

;; We include the flags found in the file "menhir_flags" plus extra flags
;; specified here.

(menhir
  (flags
    (:include menhir_flags.sexp)
    -lg 1 -la 1 -lc 1
    -v
  )
  (modules parser)
)

;; -----------------------------------------------------------------------------

;; As dune cannot use the same OCaml module in two different libraries or
;; executables, we must copy the source files to the present directory.

(copy_files# ../*.{ml,mli})

;; -----------------------------------------------------------------------------

;; The stage2 version of Menhir. The stanza is identical to that used for the
;; stage1 version, but the [Driver] and [Parser] modules are different.

;; The link_deps field requires running the completeness check.

(executable
  (name main)
  (libraries
    unix
    vendored_fix
    vendored_pprint
    menhirLib menhirSdk
  )
  (flags :standard -open MenhirSdk)
  (link_deps parserMessages.check)
)

;; -----------------------------------------------------------------------------

;; Install the Menhir executable under the "menhir" name. This would usually
;; be achieved by adding a "public_name" field in the "executable" stanza
;; above. However, we cannot do that here, because the public name "menhir"
;; would clash with the binding of this name to the stage1 version of Menhir
;; at the top of this file. Thus, we explicitly request its installation as
;; follows.

(install
  (section bin)
  (package menhir)
  (files (./main.exe as menhir))
)

;; -----------------------------------------------------------------------------

;; This section deals with the .messages file.

;; The module [ParserMessages] is generated by Menhir based on the source file
;; "parserMessages.messages". The completeness check is performed first.

(rule
  (deps parserMessages.check)
  (action (with-stdout-to parserMessages.ml
    (run menhir
      %{read-lines:menhir_flags}
      %{dep:parser.mly}
      --compile-errors %{dep:parserMessages.messages}
    )
  ))
)

;; In order to perform the completeness check, we must first generate a file
;; "parserMessages.auto.messages" that contains a list of all error states.

(rule
  (with-stdout-to parserMessages.auto.messages
    (run menhir
       %{read-lines:menhir_flags}
       %{dep:parser.mly}
       --list-errors
    )
  )
)

;; The completeness check verifies that all error messages are listed in the
;; ".messages" file. It compares the ".messages" file with that generated by
;; Menhir using the above rule.

(rule
  (with-stdout-to parserMessages.check
  (run menhir
    %{read-lines:menhir_flags}
    %{dep:parser.mly}
    --compare-errors %{dep:parserMessages.auto.messages}
    --compare-errors %{dep:parserMessages.messages}
  ))
)

;; -----------------------------------------------------------------------------

;; The following rule is used under the programmer's manual control,
;; after the grammar in [src/stage2/parser.mly] has been modified.

;; This rule updates the file [parserMessages.messages] with new
;; auto-generated comments for all error states.

;; It is invoked by running [make update] in the directory src/.

(rule
  (with-stdout-to parserMessages.messages.updated
    (run menhir
      %{read-lines:menhir_flags}
      --update-errors %{dep:parserMessages.messages}
                      %{dep:parser.mly}
    )
  )
)
