;; This is an implementation of the virtual library:
;; the file Driver.ml is present,
;; the file Driver.mli is absent.
(library
  (name driver_stage3)
  (implements driver)
  (libraries menhirSdk menhirLib base front)
  (flags :standard -open MenhirSdk -open MenhirLib -open Base -open Front)
)

;; The lexer is the same in all stages.
;; It must be placed in this directory because it depends on Parser.

(copy_files ../stage1/Lexer.mll)
(ocamllex  Lexer)

;; In stage 3, Menhir's parser is generated by the stage 2 Menhir executable.

(copy_files ../stage2/Driver.ml)
(copy_files ../stage2/Parser.mly)
(copy_files ../stage2/menhir_flags)
(copy_files ../stage2/parserMessages.messages)

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

;; 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 the stage 2 executable within the present scope.

(env
  (_ (binaries
       ../../executable/stage2/main.exe
      (../../executable/stage2/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)
)

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

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

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

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

;; The bootstrap check verifies that stage1-Menhir and stage2-Menhir produce
;; the same result when applied to Menhir's stage2 grammar. If this check
;; fails, then the ocamlyacc parser in stage1/parser.mly and the Menhir parser
;; in stage2/parser.mly have different semantics, a mistake that must be
;; fixed.

;; This check compares the [Parser] modules generated by the stage1 and stage2
;; executables, and fails if they are not identical.

;; These parsers contain line directives that are necessarily different
;; because they were generated in different directories. A helper script is
;; used to remove the "filename" part of the line directives.

;; This check is run as part of [dune test].

(rule
  (with-stdout-to Parser.stage2.ml
    (run anonymize/anonymize.exe %{dep:../stage2/Parser.ml})
  )
)

(rule
  (with-stdout-to Parser.stage3.ml
    (run anonymize/anonymize.exe %{dep:Parser.ml})
  )
)

(rule
  (alias bootstrap)
  (action (progn
    (echo "Bootstrap check: comparing the stage 2 and stage 3 parsers...\n")
    (progn
      (diff Parser.stage2.ml Parser.stage3.ml)
      (diff ../stage2/Parser.mli Parser.mli)
    )
    (echo "Bootstrap check: done.\n")
  ))
)

(rule
  (alias test)
  (deps (alias bootstrap))
  (action (progn))
)
