ocaml/Makefile.menhir

164 lines
6.2 KiB
Makefile

#**************************************************************************
#* *
#* OCaml *
#* *
#* Gabriel Scherer, projet Parsifal, INRIA Saclay *
#* *
#* Copyright 2018 Institut National de Recherche en Informatique et *
#* en Automatique. *
#* *
#* All rights reserved. This file is distributed under the terms of *
#* the GNU Lesser General Public License version 2.1, with the *
#* special exception on linking described in the file LICENSE. *
#* *
#**************************************************************************
# The rules in this Makefile use Menhir to rebuild the OCaml compiler
# parser. They are included in the main Makefile, so should be invoked
# directly, for example 'make promote-menhir'. They must be called
# after any modification to parsing/parser.mly, for the modification
# to affect the parser linked in the produced compiler:
#
# - promote-menhir builds the parser from parser.mly and stores it in
# the boot/ directory, so that future builds of the compiler use the
# updated result. Use it to make permanent changes to the compiler
# parser.
#
# - demote-menhir undoes the effect of promote-menhir. The files in
# the boot/ directory that are affected by promote-menhir and are
# under version control are restored to their normal state (HEAD).
#
# - test-menhir builds the parser from parser.mly without storing it
# in the boot/ directory, and only checks that the generated parser
# builds correctly. Use it to quickly check if a parser.mly change
# breaks the build. If you want to test a compiler produced with
# the new parser, you must use promote-menhir instead.
# (Using this rule requires a partial compiler build as obtained
# by 'make core' or 'make world'.)
#
# - clean-menhir removes the files generated by Menhir from parsing/,
# keeping only the reference sources for the grammar.
#
# - depend-menhir updates the dependency information for the
# Menhir-generated parser, which is versioned in the OCaml repository
# like all other .depend files. It should be used when the dependencies
# (of the OCaml code in the grammar semantic actions) change.
MENHIR ?= menhir
## Unused tokens
# tokens COMMENT, DOCSTRING and EOL are produced by special lexer
# modes used by other consumers than the parser.
# GREATERBRACKET ">]" was added by the parser by symmetry with "[<"
# (which is used in polymorphic variant), but is not currently used by
# the grammar.
unused_tokens := COMMENT DOCSTRING EOL GREATERRBRACKET
## Menhir compilation flags
MENHIRFLAGS := --explain --dump --ocamlc "$(CAMLC) $(COMPFLAGS)" --infer \
--lalr --strict --table -lg 1 -la 1 \
$(addprefix --unused-token ,$(unused_tokens)) --fixed-exception
## promote-menhir
.PHONY: promote-menhir
promote-menhir: parsing/parser.mly
@ $(MAKE) import-menhirLib
$(MENHIR) $(MENHIRFLAGS) parsing/parser.mly
# The generated parser.ml may contain lexer directives containing
# the absolute path to Menhir's standard library on the promoter's machine.
# This is benign but will generate pointless churn if another developer
# rebuilds the same grammar (from the same Menhir version).
@ for f in $(addprefix parser.,ml mli) ; do \
sed \
's,^#\(.*\)"[^"]*/menhir/standard.mly",#\1"menhir/standard.mly",g' \
parsing/$$f \
> boot/menhir/$$f; \
rm parsing/$$f; \
done
# The import-menhirLib invocation in promote-menhir ensures that each
# update of the boot/ parser is paired with an update of the imported
# menhirLib; otherwise it would be easy to generate a parser and keep
# an incompatible version of menhirLib, which would fail at
# compile-time.
.PHONY: import-menhirLib
import-menhirLib:
@ mkdir -p boot/menhir
@ cp \
$(addprefix `$(MENHIR) --suggest-menhirLib`/menhirLib.,ml mli) \
boot/menhir
## demote-menhir
DEMOTE:=menhirLib.ml menhirLib.mli parser.ml parser.mli
.PHONY: demote-menhir
demote-menhir:
git checkout HEAD -- $(addprefix boot/menhir/,$(DEMOTE))
## test-menhir
# This rule assumes that the `parsing/` sources and its dependencies
# have already been compiled; 'make core' suffices to be in that
# state. We don't make 'core' an explicit dependency, as building
# 'test-menhir' repeatedly would rebuild the compiler each time
# (parser.ml has changed), without actually taking the changes from
# parser.mly into account ('core' uses the parser from boot/).
# The test-menhir target does not read or write the boot directory,
# it directly builds the parser in parsing/. In particular, it must
# duplicate the MenhirLib->CamlinternalMenhirlib renaming usually
# performed by the parsing/parser.ml import rule in the main
# Makefile.
.PHONY: test-menhir
test-menhir: parsing/parser.mly
$(MENHIR) $(MENHIRFLAGS) parsing/parser.mly
for f in $(addprefix parsing/parser.,ml mli) ; do \
cat $$f | sed "s/MenhirLib/CamlinternalMenhirLib/g" > $$f.tmp && \
mv $$f.tmp $$f ; \
done
$(MAKE) parsing/parser.cmo
## clean-menhir
partialclean-menhir::
rm -f \
$(addprefix parsing/parser.,ml mli) \
$(addprefix parsing/camlinternalMenhirLib.,ml mli)
clean-menhir: partialclean-menhir
## depend-menhir
.PHONY: depend-menhir
depend-menhir:
$(MENHIR) --depend --ocamldep "$(CAMLDEP) $(DEPFLAGS) $(DEPINCLUDES)" \
parsing/parser.mly > .depend.menhir
# this rule depends on the variables CAMLDEP, DEPFLAGS, DEPINCLUDES
# defined in Makefile, so it can only be invoked from the main Makefile
include .depend.menhir
## interpret-menhir
# This rule runs Menhir in interactive mode.
# The user can enter sentences, such as:
# implementation: TYPE LIDENT EQUAL LIDENT EOF
# and see how Menhir interprets them.
interpret-menhir:
@ echo "Please wait, I am building the LALR automaton..."
@ $(MENHIR) $(MENHIRFLAGS) parsing/parser.mly \
--interpret \
--interpret-show-cst \
--trace \