#************************************************************************** #* * #* 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 \